Skip to content

Commit 451f02c

Browse files
Add HALs for Framework Input Modules (#92)
* Add HAL for Framework LED Matrix * Add Framework 16 Keyboard HAL * boards/framework16-keyboard: Add capslock example * boards/framework16-keyboard: Add backlight example * boards/framework-ledmatrix: Add ledtest example --------- Signed-off-by: Daniel Schaefer <[email protected]>
1 parent ce80657 commit 451f02c

File tree

16 files changed

+991
-0
lines changed

16 files changed

+991
-0
lines changed

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ members = [
1010
"boards/adafruit-trinkey-qt2040",
1111
"boards/arduino_nano_connect",
1212
"boards/boardsource-blok",
13+
"boards/framework-ledmatrix",
14+
"boards/framework16-keyboard",
1315
"boards/pimoroni_badger2040",
1416
"boards/pimoroni-pico-explorer",
1517
"boards/pimoroni-pico-lipo-16mb",

boards/framework-ledmatrix/.gitignore

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
debug/
4+
target/
5+
6+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8+
Cargo.lock
9+
10+
# These are backup files generated by rustfmt
11+
**/*.rs.bk
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## Unreleased
9+
10+
## 0.1.0 - 2024-10-21
11+
12+
### Added
13+
14+
- Initial release of Framework LED Matrix HAL

boards/framework-ledmatrix/Cargo.toml

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[package]
2+
name = "framework-ledmatrix"
3+
version = "0.1.0"
4+
authors = ["Daniel Schaefer <[email protected]>", "The rp-rs Developers"]
5+
edition = "2018"
6+
homepage = "https://github.com/rp-rs/rp-hal-boards/tree/main/boards/framework-ledmatrix"
7+
description = "Board Support Package for the Framework LED Matrix"
8+
license = "MIT OR Apache-2.0"
9+
repository = "https://github.com/rp-rs/rp-hal-boards.git"
10+
11+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
12+
13+
[dependencies]
14+
cortex-m-rt = { workspace = true, optional = true }
15+
fugit.workspace = true
16+
rp2040-boot2 = { workspace = true, optional = true }
17+
rp2040-hal.workspace = true
18+
19+
[dev-dependencies]
20+
cortex-m.workspace = true
21+
critical-section.workspace = true
22+
embedded-graphics.workspace = true
23+
embedded-hal.workspace = true
24+
heapless.workspace = true
25+
nb.workspace = true
26+
panic-halt.workspace = true
27+
rp2040-hal = { workspace = true, features = [ "defmt" ] }
28+
is31fl3741 = { version = "0.4.0", features = [ "framework_ledmatrix" ] }
29+
30+
defmt.workspace = true
31+
defmt-rtt.workspace = true
32+
33+
[features]
34+
# This is the set of features we enable by default
35+
default = ["boot2", "rt", "critical-section-impl", "rom-func-cache"]
36+
37+
# critical section that is safe for multicore use
38+
critical-section-impl = ["rp2040-hal/critical-section-impl"]
39+
40+
# 2nd stage bootloaders for rp2040
41+
boot2 = ["rp2040-boot2"]
42+
43+
# Minimal startup / runtime for Cortex-M microcontrollers
44+
rt = ["cortex-m-rt","rp2040-hal/rt"]
45+
46+
# This enables a fix for USB errata 5: USB device fails to exit RESET state on busy USB bus.
47+
# Only required for RP2040 B0 and RP2040 B1, but it also works for RP2040 B2 and above
48+
rp2040-e5 = ["rp2040-hal/rp2040-e5"]
49+
50+
# Memoize(cache) ROM function pointers on first use to improve performance
51+
rom-func-cache = ["rp2040-hal/rom-func-cache"]
52+
53+
# Disable automatic mapping of language features (like floating point math) to ROM functions
54+
disable-intrinsics = ["rp2040-hal/disable-intrinsics"]
55+
56+
# This enables ROM functions for f64 math that were not present in the earliest RP2040s
57+
rom-v2-intrinsics = ["rp2040-hal/rom-v2-intrinsics"]

boards/framework-ledmatrix/README.md

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# [framework-ledmatrix] - Board Support for the [Framework LED Matrix]
2+
3+
You should include this crate if you are writing code that you want to run on
4+
a [Frameworkg LED Matrix].
5+
6+
This crate includes the [rp2040-hal], but also configures each pin of the
7+
RP2040 chip according to how it is connected up on the module.
8+
9+
[Framework LED Matrix]: https://frame.work/tw/en/products/16-led-matrix
10+
[framework-ledmatrix]: https://github.com/rp-rs/rp-hal-boards/tree/main/boards/framework-ledmatrix
11+
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
12+
[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
13+
14+
## Using
15+
16+
To use this crate, your `Cargo.toml` file should contain:
17+
18+
```toml
19+
framework-ledmatrix = "0.1.0"
20+
```
21+
22+
In your program, you will need to call `framework_ledmatrix::Pins::new` to create
23+
a new `Pins` structure. This will set up all the GPIOs for any on-board
24+
devices. See the [examples](./examples) folder for more details.
25+
26+
## Examples
27+
28+
### General Instructions
29+
30+
To compile an example, clone the _rp-hal-boards_ repository and run:
31+
32+
```console
33+
rp-hal-boards/boards/framework-ledmatrix $ cargo build --release --example <name>
34+
```
35+
36+
You will get an ELF file called
37+
`./target/thumbv6m-none-eabi/release/examples/<name>`, where the `target`
38+
folder is located at the top of the _rp-hal-boards_ repository checkout. Normally
39+
you would also need to specify `--target=thumbv6m-none-eabi` but when
40+
building examples from this git repository, that is set as the default.
41+
42+
If you want to convert the ELF file to a UF2 and automatically copy it to the
43+
USB drive exported by the RP2040 bootloader, simply boot your board into
44+
bootloader mode and run:
45+
46+
```console
47+
rp-hal-boards/boards/framework-ledmatrix $ cargo run --release --example <name>
48+
```
49+
50+
If you get an error about not being able to find `elf2uf2-rs`, try:
51+
52+
```console
53+
$ cargo install elf2uf2-rs
54+
```
55+
then try repeating the `cargo run` command above.
56+
57+
### From Scratch
58+
59+
To start a basic project from scratch, create a project using `cargo new project-name`. Within the
60+
project directory, run `cargo add framework-ledmatrix`, `cargo add cortex-m-rt`, and `cargo add panic-halt`. The
61+
first command will add this HAL (Hardware Abstraction Layer), the second is required for the `#[entry]` macro, and _panic-halt_ creates a simple panic function, which just halts.
62+
63+
You'll also need to copy the cargo config file from the [repo](https://github.com/rp-rs/rp-hal-boards/blob/main/.cargo/config.toml). It specifies the target and optimizing flags to the linker. You'll also need to copy [_memory.x_](https://github.com/rp-rs/rp-hal-boards/blob/main/memory.x) to your project root. This file tells the linker the flash and RAM layout, so it won't clobber the bootloader or write to an out of bounds memory address.
64+
65+
The simplest working example, which does nothing except loop forever, is:
66+
67+
```ignore
68+
#![no_std]
69+
#![no_main]
70+
use framework_ledmatrix::entry;
71+
use panic_halt as _;
72+
#[entry]
73+
fn see_doesnt_have_to_be_called_main() -> ! {
74+
loop {}
75+
}
76+
```
77+
78+
It can be placed in _/src/main.rs_.
79+
80+
You can use `cargo run` to compile and install it.
81+
**Note**: You won't see any activity since this program does nothing. You can use the examples provided
82+
to add more functionality.
83+
84+
### [ledtest](./examples/ledtest.rs)
85+
86+
Lights up every single LED one after another. It goes back into bootloader mode
87+
when the system goes to sleep. This makes it easy for you to reflash it to
88+
other firmware.
89+
90+
## Contributing
91+
92+
Contributions are what make the open source community such an amazing place to
93+
be learn, inspire, and create. Any contributions you make are **greatly
94+
appreciated**.
95+
96+
The steps are:
97+
98+
1. Fork the Project by clicking the 'Fork' button at the top of the page.
99+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
100+
3. Make some changes to the code or documentation.
101+
4. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
102+
5. Push to the Feature Branch (`git push origin feature/AmazingFeature`)
103+
6. Create a [New Pull Request](https://github.com/rp-rs/rp-hal-boards/pulls)
104+
7. An admin will review the Pull Request and discuss any changes that may be required.
105+
8. Once everyone is happy, the Pull Request can be merged by an admin, and your work is part of our project!
106+
107+
## Code of Conduct
108+
109+
Contribution to this crate is organized under the terms of the [Rust Code of
110+
Conduct][CoC], and the maintainer of this crate, the [rp-rs team], promises
111+
to intervene to uphold that code of conduct.
112+
113+
[CoC]: CODE_OF_CONDUCT.md
114+
[rp-rs team]: https://github.com/orgs/rp-rs/teams/rp-rs
115+
116+
## License
117+
118+
The contents of this repository are dual-licensed under the _MIT OR Apache
119+
2.0_ License. That means you can choose either the MIT license or the
120+
Apache-2.0 license when you re-use this code. See `MIT` or `APACHE2.0` for more
121+
information on each specific license.
122+
123+
Any submissions to this project (e.g. as Pull Requests) must be made available
124+
under these terms.

boards/framework-ledmatrix/build.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//! This build script makes sure the linker flag -Tdefmt.x is added
2+
//! for the examples.
3+
4+
fn main() {
5+
println!("cargo:rustc-link-arg-examples=-Tdefmt.x");
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//! # Framework LED Matrix Module LED Test Example
2+
//!
3+
//! Lights up every single LED one after another.
4+
//!
5+
//! See the `Cargo.toml` file for Copyright and license details.
6+
7+
#![no_std]
8+
#![no_main]
9+
#![allow(clippy::needless_range_loop)]
10+
11+
// The macro for our start-up function
12+
use framework_ledmatrix::entry;
13+
use framework_ledmatrix::{Pins, XOSC_CRYSTAL_FREQ};
14+
15+
use embedded_hal::digital::{InputPin, OutputPin};
16+
17+
// Ensure we halt the program on panic (if we don't mention this crate it won't
18+
// be linked)
19+
use panic_halt as _;
20+
21+
// Pull in any important traits
22+
use framework_ledmatrix::hal::prelude::*;
23+
24+
// A shorter alias for the Peripheral Access Crate, which provides low-level
25+
// register access
26+
use framework_ledmatrix::hal::pac;
27+
28+
// A shorter alias for the Hardware Abstraction Layer, which provides
29+
// higher-level drivers.
30+
use framework_ledmatrix::hal;
31+
32+
use fugit::RateExtU32;
33+
34+
/// Maximum brightness out of 255
35+
///
36+
/// 100/255 results in 250mA current draw and is plenty bright.
37+
/// 50/255 results in 160mA current draw and is plenty bright.
38+
const MAX_BRIGHTNESS: u8 = 50;
39+
40+
use is31fl3741::devices::{LedMatrix, CALC_PIXEL};
41+
42+
#[entry]
43+
fn main() -> ! {
44+
// Grab our singleton objects
45+
let mut pac = pac::Peripherals::take().unwrap();
46+
let core = pac::CorePeripherals::take().unwrap();
47+
48+
// Set up the watchdog driver - needed by the clock setup code
49+
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
50+
51+
// Configure the clocks
52+
//
53+
// The default is to generate a 125 MHz system clock
54+
let clocks = hal::clocks::init_clocks_and_plls(
55+
XOSC_CRYSTAL_FREQ,
56+
pac.XOSC,
57+
pac.CLOCKS,
58+
pac.PLL_SYS,
59+
pac.PLL_USB,
60+
&mut pac.RESETS,
61+
&mut watchdog,
62+
)
63+
.ok()
64+
.unwrap();
65+
66+
// The single-cycle I/O block controls our GPIO pins
67+
let sio = hal::Sio::new(pac.SIO);
68+
69+
// Set the pins up according to their function on this particular board
70+
let pins = Pins::new(
71+
pac.IO_BANK0,
72+
pac.PADS_BANK0,
73+
sio.gpio_bank0,
74+
&mut pac.RESETS,
75+
);
76+
77+
// The delay object lets us wait for specified amounts of time (in
78+
// milliseconds)
79+
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
80+
81+
// Enable LED controller
82+
// SDB - Gpio29
83+
let mut led_enable = pins.sdb.into_push_pull_output();
84+
led_enable.set_high().unwrap();
85+
// INTB. Currently ignoring
86+
pins.intb.into_floating_input();
87+
88+
let sda_pin: hal::gpio::Pin<_, hal::gpio::FunctionI2C, _> = pins.gpio26.reconfigure();
89+
let scl_pin: hal::gpio::Pin<_, hal::gpio::FunctionI2C, _> = pins.gpio27.reconfigure();
90+
91+
let i2c = hal::I2C::i2c1(
92+
pac.I2C1,
93+
sda_pin,
94+
scl_pin,
95+
1000.kHz(),
96+
&mut pac.RESETS,
97+
&clocks.peripheral_clock,
98+
);
99+
100+
let mut dip1 = pins.dip1.into_pull_up_input();
101+
let _ = dip1.is_high().unwrap();
102+
103+
// Detect whether the sleep pin is connected
104+
// Early revisions of the hardware didn't have it wired up, if that is the
105+
// case we have to ignore its state.
106+
let mut sleep_present = false;
107+
let mut sleep = pins.sleep.into_pull_up_input();
108+
if sleep.is_low().unwrap() {
109+
sleep_present = true;
110+
}
111+
let mut sleep = sleep.into_pull_down_input();
112+
if sleep.is_high().unwrap() {
113+
sleep_present = true;
114+
}
115+
116+
let mut matrix = LedMatrix::new(i2c, CALC_PIXEL);
117+
matrix
118+
.setup(&mut delay)
119+
.expect("failed to setup RGB controller");
120+
121+
// Enable only the SW pins that we're using.
122+
// Otherwise driving the unused pins might result in audible noise.
123+
matrix
124+
.device
125+
.sw_enablement(is31fl3741::SwSetting::Sw1Sw8)
126+
.unwrap();
127+
128+
matrix
129+
.set_scaling(MAX_BRIGHTNESS)
130+
.expect("failed to set scaling");
131+
132+
loop {
133+
// Light up each LED, one by one
134+
for y in 0..matrix.device.height {
135+
for x in 0..matrix.device.width {
136+
matrix.device.pixel(x, y, 0xFF).expect("couldn't turn on");
137+
delay.delay_ms(100);
138+
matrix.device.pixel(x, y, 0).expect("couldn't turn off");
139+
140+
// Reset into bootloader if system asleep
141+
if sleep_present && sleep.is_low().unwrap() {
142+
hal::rom_data::reset_to_usb_boot(0, 0);
143+
}
144+
}
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)