Skip to content

Commit

Permalink
Merge pull request #12 from FrameworkComputer/ledmatrix
Browse files Browse the repository at this point in the history
Add Framework LED Matrix
  • Loading branch information
JohnAZoidberg authored Oct 15, 2024
2 parents 8e9856c + 1674645 commit 3a8fa42
Show file tree
Hide file tree
Showing 12 changed files with 621 additions and 10 deletions.
18 changes: 14 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,16 @@ jobs:
- '.github/workflows/**'
- if: steps.changes.outputs.rust == 'true'
run: |
cargo build --target=thumbv6m-none-eabi
cd examples/adafruit_rgb
cargo build --target=thumbv6m-none-eabi
cargo build --target=thumbv6m-none-eabi --all-features
pushd examples/adafruit_rgb
cargo build --target=thumbv6m-none-eabi --examples
popd
cargo install flip-link
pushd examples/ledmatrix
cargo build --examples
popd
rustdoc:
runs-on: ubuntu-latest
Expand All @@ -42,4 +49,7 @@ jobs:
- 'Cargo.lock'
- '.github/workflows/**'
- if: steps.changes.outputs.rust == 'true'
run: cargo doc
run: |
cargo doc
cargo fmt --all -- --check
cargo clippy -- --deny=warnings
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ all-features = true

[features]
adafruit_rgb_13x9 = []
framework_ledmatrix = []
embedded_graphics = ["embedded-graphics-core"]
default = ["adafruit_rgb_13x9", "embedded_graphics"]
default = ["embedded_graphics"]
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
build-all:
cargo build --target=thumbv6m-none-eabi --all-features
cd examples/adafruit_rgb && \
cargo build --target=thumbv6m-none-eabi --examples --all-features
cargo build --target=thumbv6m-none-eabi --examples
cd examples/ledmatrix && \
cargo build --target=thumbv6m-none-eabi --examples
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Driver for [Lumissil Microsystem's IS31FL3741 integrated circuit](https://www.lu
1. Use of embedded HAL traits (works with any embedded device that supports the required traits). This means that this driver is platform agnostic.
2. Library features (only turn on what devices you need to save compiled binary space).
3. [Examples](./examples) on how to use this driver.
Right now there is only an example on how to use this crate with a stm32 nucleo.

## Install

Expand All @@ -23,11 +22,13 @@ is31fl3741 = "0.3.0"
```

By default this version will only contain the core driver.
To use a preconfigured device (currently just [Adafruit IS31FL3741 13x9 PWM RGB LED Matrix](https://www.adafruit.com/product/5201)),

To use a preconfigured device ([Framework LED Matrix](https://frame.work/tw/en/products/16-led-matrix) or [Adafruit 13x9 RGB LED Matrix](https://www.adafruit.com/product/5201)),
you would need to change this line to include that device:

```toml
is31fl3741 = { version = "0.3.0", features = ["adafruit13x9"] }
is31fl3741 = { version = "0.3.0", features = ["framework_ledmatrix"] }
is31fl3741 = { version = "0.3.0", features = ["adafruit_rgb_13x9"] }
```

## Graphics
Expand Down
20 changes: 20 additions & 0 deletions examples/ledmatrix/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "elf2uf2-rs -d"

rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",

# Code-size optimizations.
# trap unreachable can save a lot of space, but requires nightly compiler.
# uncomment the next line if you wish to enable it
# "-Z", "trap-unreachable=no",
"-C", "no-vectorize-loops",
]

[build]
target = "thumbv6m-none-eabi"

[env]
DEFMT_LOG = "debug"
16 changes: 16 additions & 0 deletions examples/ledmatrix/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "ledmatrix"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
is31fl3741 = { path = "../../", features = ["framework_ledmatrix"] }
embedded-hal = "0.2.7"
cortex-m-rt = "0.7.3"
cortex-m = "0.7.7"
fugit = "0.3.7"
rp2040-hal = { version = "0.8", features = ["rt", "critical-section-impl"] }
rp-pico = "0.7"
rp2040-panic-usb-boot = "0.5.0"
rp2040-boot2 = "0.3"
11 changes: 11 additions & 0 deletions examples/ledmatrix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Framework LED Matrix

## Build and run

Make sure you're in bootloader mode and then run the following command, which
automatically flashes the matrix.

```
cargo install flip-link
cargo run --example ledtest
```
31 changes: 31 additions & 0 deletions examples/ledmatrix/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());

// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
}
133 changes: 133 additions & 0 deletions examples/ledmatrix/examples/ledtest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//! LED Matrix Module
//!
//!
//!
//! Goes into bootloader mode when the host is asleep. This is to make it easy to reflash your
//! firmware - the regular bootloader mechanism using the DIP switch still works.
#![no_std]
#![no_main]
#![allow(clippy::needless_range_loop)]

use embedded_hal::digital::v2::{InputPin, OutputPin};
use rp2040_hal::rom_data::reset_to_usb_boot;
use rp2040_panic_usb_boot as _;

/// Maximum brightness out of 255
///
/// 100/255 results in 250mA current draw and is plenty bright.
/// 50/255 results in 160mA current draw and is plenty bright.
const MAX_BRIGHTNESS: u8 = 50;

// Provide an alias for our BSP so we can switch targets quickly.
// Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change.
use bsp::entry;
use is31fl3741::devices::{LedMatrix, CALC_PIXEL};
use is31fl3741::{PwmFreq};
use rp_pico as bsp;

use bsp::hal::{
clocks::{init_clocks_and_plls, Clock},
gpio, pac,
sio::Sio,
watchdog::Watchdog,
};
use fugit::RateExtU32;

#[entry]
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);

let clocks = init_clocks_and_plls(
bsp::XOSC_CRYSTAL_FREQ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

let pins = bsp::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);

// Enable LED controller
// SDB - Gpio29
let mut led_enable = pins.voltage_monitor.into_push_pull_output();
led_enable.set_high().unwrap();
// INTB. Currently ignoring
pins.gpio28.into_floating_input();

let i2c = bsp::hal::I2C::i2c1(
pac.I2C1,
pins.gpio26.into_mode::<gpio::FunctionI2C>(),
pins.gpio27.into_mode::<gpio::FunctionI2C>(),
// 1000,
1000.kHz(),
&mut pac.RESETS,
&clocks.peripheral_clock,
);

// Gpio25 (LED on rp-pico)
let dip1 = pins.led.into_pull_up_input();
let _dip1_state = dip1.is_low().unwrap();

// Detect whether the sleep pin is connected
// Early revisions of the hardware didn't have it wired up, if that is the
// case we have to ignore its state.
let mut sleep_present = false;
let sleep = pins.gpio0.into_pull_up_input();
if sleep.is_low().unwrap() {
sleep_present = true;
}
let sleep = sleep.into_pull_down_input();
if sleep.is_high().unwrap() {
sleep_present = true;
}

let mut matrix = LedMatrix::new(i2c, CALC_PIXEL);
matrix
.setup(&mut delay)
.expect("failed to setup RGB controller");

// Enable only the SW pins that we're using.
// Otherwise driving the unused pins might result in audible noise.
matrix
.device
.sw_enablement(is31fl3741::SwSetting::Sw1Sw8)
.unwrap();

matrix
.set_scaling(MAX_BRIGHTNESS)
.expect("failed to set scaling");

matrix.device.set_pwm_freq(PwmFreq::P29k).unwrap();

loop {
// Light up each LED, one by one
for y in 0..matrix.device.height {
for x in 0..matrix.device.width {
matrix
.device
.pixel(x, y, 0xFF)
.expect("couldn't turn on");
delay.delay_ms(100);
matrix.device.pixel(x, y, 0).expect("couldn't turn off");

// Reset into bootloader if system asleep
if sleep_present && sleep.is_low().unwrap(){
reset_to_usb_boot(0, 0);
}
}
}
}
}
15 changes: 15 additions & 0 deletions examples/ledmatrix/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}

EXTERN(BOOT2_FIRMWARE)

SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;
1 change: 1 addition & 0 deletions examples/ledmatrix/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#![no_std]
Loading

0 comments on commit 3a8fa42

Please sign in to comment.