From c3b4849afa7c683745c55dc0451f355a8f7b1219 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 14 Oct 2024 13:11:38 +0800 Subject: [PATCH 1/4] Add Framework LED Matrix Signed-off-by: Daniel Schaefer --- Cargo.toml | 3 +- README.md | 6 +- src/devices.rs | 370 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 375 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7f17ba1..9bdd519 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/README.md b/README.md index 51882ea..2bc989f 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,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 diff --git a/src/devices.rs b/src/devices.rs index 0af91ef..2cc2910 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -14,7 +14,7 @@ pub struct AdafruitRGB13x9 { pub device: IS31FL3741, } -#[cfg(feature = "embedded_graphics")] +#[cfg(all(feature = "adafruit_rgb_13x9", feature = "embedded_graphics"))] use embedded_graphics_core::{pixelcolor::Rgb888, prelude::*, primitives::Rectangle}; #[cfg(all(feature = "adafruit_rgb_13x9", feature = "embedded_graphics"))] @@ -229,3 +229,371 @@ where Ok(()) } } + +#[cfg(feature = "framework_ledmatrix")] +pub const CALC_PIXEL: fn(x: u8, y: u8) -> (u8, u8) = |x: u8, y: u8| -> (u8, u8) { + // Generated by led-matrix.py + let lookup: [(u8, u8); 34 * 9] = [ + (0x00, 0), // x: 1, y: 1, sw: 1, cs: 1, id: 1 + (0x1e, 0), // x: 2, y: 1, sw: 2, cs: 1, id: 2 + (0x3c, 0), // x: 3, y: 1, sw: 3, cs: 1, id: 3 + (0x5a, 0), // x: 4, y: 1, sw: 4, cs: 1, id: 4 + (0x78, 0), // x: 5, y: 1, sw: 5, cs: 1, id: 5 + (0x96, 0), // x: 6, y: 1, sw: 6, cs: 1, id: 6 + (0x00, 1), // x: 7, y: 1, sw: 7, cs: 1, id: 7 + (0x1e, 1), // x: 8, y: 1, sw: 8, cs: 1, id: 8 + (0x5f, 1), // x: 9, y: 1, sw: 1, cs:36, id: 9 + (0x01, 0), // x: 1, y: 2, sw: 1, cs: 2, id: 10 + (0x1f, 0), // x: 2, y: 2, sw: 2, cs: 2, id: 11 + (0x3d, 0), // x: 3, y: 2, sw: 3, cs: 2, id: 12 + (0x5b, 0), // x: 4, y: 2, sw: 4, cs: 2, id: 13 + (0x79, 0), // x: 5, y: 2, sw: 5, cs: 2, id: 14 + (0x97, 0), // x: 6, y: 2, sw: 6, cs: 2, id: 15 + (0x01, 1), // x: 7, y: 2, sw: 7, cs: 2, id: 16 + (0x1f, 1), // x: 8, y: 2, sw: 8, cs: 2, id: 17 + (0x60, 1), // x: 9, y: 2, sw: 1, cs:37, id: 18 + (0x02, 0), // x: 1, y: 3, sw: 1, cs: 3, id: 19 + (0x20, 0), // x: 2, y: 3, sw: 2, cs: 3, id: 20 + (0x3e, 0), // x: 3, y: 3, sw: 3, cs: 3, id: 21 + (0x5c, 0), // x: 4, y: 3, sw: 4, cs: 3, id: 22 + (0x7a, 0), // x: 5, y: 3, sw: 5, cs: 3, id: 23 + (0x98, 0), // x: 6, y: 3, sw: 6, cs: 3, id: 24 + (0x02, 1), // x: 7, y: 3, sw: 7, cs: 3, id: 25 + (0x20, 1), // x: 8, y: 3, sw: 8, cs: 3, id: 26 + (0x61, 1), // x: 9, y: 3, sw: 1, cs:38, id: 27 + (0x03, 0), // x: 1, y: 4, sw: 1, cs: 4, id: 28 + (0x21, 0), // x: 2, y: 4, sw: 2, cs: 4, id: 29 + (0x3f, 0), // x: 3, y: 4, sw: 3, cs: 4, id: 30 + (0x5d, 0), // x: 4, y: 4, sw: 4, cs: 4, id: 31 + (0x7b, 0), // x: 5, y: 4, sw: 5, cs: 4, id: 32 + (0x99, 0), // x: 6, y: 4, sw: 6, cs: 4, id: 33 + (0x03, 1), // x: 7, y: 4, sw: 7, cs: 4, id: 34 + (0x21, 1), // x: 8, y: 4, sw: 8, cs: 4, id: 35 + (0x62, 1), // x: 9, y: 4, sw: 1, cs:39, id: 36 + (0x04, 0), // x: 1, y: 5, sw: 1, cs: 5, id: 37 + (0x22, 0), // x: 2, y: 5, sw: 2, cs: 5, id: 41 + (0x40, 0), // x: 3, y: 5, sw: 3, cs: 5, id: 45 + (0x5e, 0), // x: 4, y: 5, sw: 4, cs: 5, id: 49 + (0x7c, 0), // x: 5, y: 5, sw: 5, cs: 5, id: 53 + (0x9a, 0), // x: 6, y: 5, sw: 6, cs: 5, id: 57 + (0x04, 1), // x: 7, y: 5, sw: 7, cs: 5, id: 61 + (0x22, 1), // x: 8, y: 5, sw: 8, cs: 5, id: 65 + (0x5e, 1), // x: 9, y: 5, sw: 1, cs:35, id: 69 + (0x05, 0), // x: 1, y: 6, sw: 1, cs: 6, id: 38 + (0x23, 0), // x: 2, y: 6, sw: 2, cs: 6, id: 42 + (0x41, 0), // x: 3, y: 6, sw: 3, cs: 6, id: 46 + (0x5f, 0), // x: 4, y: 6, sw: 4, cs: 6, id: 50 + (0x7d, 0), // x: 5, y: 6, sw: 5, cs: 6, id: 54 + (0x9b, 0), // x: 6, y: 6, sw: 6, cs: 6, id: 58 + (0x05, 1), // x: 7, y: 6, sw: 7, cs: 6, id: 62 + (0x23, 1), // x: 8, y: 6, sw: 8, cs: 6, id: 66 + (0x68, 1), // x: 9, y: 6, sw: 2, cs:36, id: 70 + (0x06, 0), // x: 1, y: 7, sw: 1, cs: 7, id: 39 + (0x24, 0), // x: 2, y: 7, sw: 2, cs: 7, id: 43 + (0x42, 0), // x: 3, y: 7, sw: 3, cs: 7, id: 47 + (0x60, 0), // x: 4, y: 7, sw: 4, cs: 7, id: 51 + (0x7e, 0), // x: 5, y: 7, sw: 5, cs: 7, id: 55 + (0x9c, 0), // x: 6, y: 7, sw: 6, cs: 7, id: 59 + (0x06, 1), // x: 7, y: 7, sw: 7, cs: 7, id: 63 + (0x24, 1), // x: 8, y: 7, sw: 8, cs: 7, id: 67 + (0x69, 1), // x: 9, y: 7, sw: 2, cs:37, id: 71 + (0x07, 0), // x: 1, y: 8, sw: 1, cs: 8, id: 40 + (0x25, 0), // x: 2, y: 8, sw: 2, cs: 8, id: 44 + (0x43, 0), // x: 3, y: 8, sw: 3, cs: 8, id: 48 + (0x61, 0), // x: 4, y: 8, sw: 4, cs: 8, id: 52 + (0x7f, 0), // x: 5, y: 8, sw: 5, cs: 8, id: 56 + (0x9d, 0), // x: 6, y: 8, sw: 6, cs: 8, id: 60 + (0x07, 1), // x: 7, y: 8, sw: 7, cs: 8, id: 64 + (0x25, 1), // x: 8, y: 8, sw: 8, cs: 8, id: 68 + (0x6a, 1), // x: 9, y: 8, sw: 2, cs:38, id: 72 + (0x08, 0), // x: 1, y: 9, sw: 1, cs: 9, id: 73 + (0x26, 0), // x: 2, y: 9, sw: 2, cs: 9, id: 81 + (0x44, 0), // x: 3, y: 9, sw: 3, cs: 9, id: 89 + (0x62, 0), // x: 4, y: 9, sw: 4, cs: 9, id: 97 + (0x80, 0), // x: 5, y: 9, sw: 5, cs: 9, id:105 + (0x9e, 0), // x: 6, y: 9, sw: 6, cs: 9, id:113 + (0x08, 1), // x: 7, y: 9, sw: 7, cs: 9, id:121 + (0x26, 1), // x: 8, y: 9, sw: 8, cs: 9, id:129 + (0x6b, 1), // x: 9, y: 9, sw: 2, cs:39, id:137 + (0x09, 0), // x: 1, y:10, sw: 1, cs:10, id: 74 + (0x27, 0), // x: 2, y:10, sw: 2, cs:10, id: 82 + (0x45, 0), // x: 3, y:10, sw: 3, cs:10, id: 90 + (0x63, 0), // x: 4, y:10, sw: 4, cs:10, id: 98 + (0x81, 0), // x: 5, y:10, sw: 5, cs:10, id:106 + (0x9f, 0), // x: 6, y:10, sw: 6, cs:10, id:114 + (0x09, 1), // x: 7, y:10, sw: 7, cs:10, id:122 + (0x27, 1), // x: 8, y:10, sw: 8, cs:10, id:130 + (0x67, 1), // x: 9, y:10, sw: 2, cs:35, id:138 + (0x0a, 0), // x: 1, y:11, sw: 1, cs:11, id: 75 + (0x28, 0), // x: 2, y:11, sw: 2, cs:11, id: 83 + (0x46, 0), // x: 3, y:11, sw: 3, cs:11, id: 91 + (0x64, 0), // x: 4, y:11, sw: 4, cs:11, id: 99 + (0x82, 0), // x: 5, y:11, sw: 5, cs:11, id:107 + (0xa0, 0), // x: 6, y:11, sw: 6, cs:11, id:115 + (0x0a, 1), // x: 7, y:11, sw: 7, cs:11, id:123 + (0x28, 1), // x: 8, y:11, sw: 8, cs:11, id:131 + (0x71, 1), // x: 9, y:11, sw: 3, cs:36, id:139 + (0x0b, 0), // x: 1, y:12, sw: 1, cs:12, id: 76 + (0x29, 0), // x: 2, y:12, sw: 2, cs:12, id: 84 + (0x47, 0), // x: 3, y:12, sw: 3, cs:12, id: 92 + (0x65, 0), // x: 4, y:12, sw: 4, cs:12, id:100 + (0x83, 0), // x: 5, y:12, sw: 5, cs:12, id:108 + (0xa1, 0), // x: 6, y:12, sw: 6, cs:12, id:116 + (0x0b, 1), // x: 7, y:12, sw: 7, cs:12, id:124 + (0x29, 1), // x: 8, y:12, sw: 8, cs:12, id:132 + (0x72, 1), // x: 9, y:12, sw: 3, cs:37, id:140 + (0x0c, 0), // x: 1, y:13, sw: 1, cs:13, id: 77 + (0x2a, 0), // x: 2, y:13, sw: 2, cs:13, id: 85 + (0x48, 0), // x: 3, y:13, sw: 3, cs:13, id: 93 + (0x66, 0), // x: 4, y:13, sw: 4, cs:13, id:101 + (0x84, 0), // x: 5, y:13, sw: 5, cs:13, id:109 + (0xa2, 0), // x: 6, y:13, sw: 6, cs:13, id:117 + (0x0c, 1), // x: 7, y:13, sw: 7, cs:13, id:125 + (0x2a, 1), // x: 8, y:13, sw: 8, cs:13, id:133 + (0x73, 1), // x: 9, y:13, sw: 3, cs:38, id:141 + (0x0d, 0), // x: 1, y:14, sw: 1, cs:14, id: 78 + (0x2b, 0), // x: 2, y:14, sw: 2, cs:14, id: 86 + (0x49, 0), // x: 3, y:14, sw: 3, cs:14, id: 94 + (0x67, 0), // x: 4, y:14, sw: 4, cs:14, id:102 + (0x85, 0), // x: 5, y:14, sw: 5, cs:14, id:110 + (0xa3, 0), // x: 6, y:14, sw: 6, cs:14, id:118 + (0x0d, 1), // x: 7, y:14, sw: 7, cs:14, id:126 + (0x2b, 1), // x: 8, y:14, sw: 8, cs:14, id:134 + (0x70, 1), // x: 9, y:14, sw: 3, cs:35, id:142 + (0x0e, 0), // x: 1, y:15, sw: 1, cs:15, id: 79 + (0x2c, 0), // x: 2, y:15, sw: 2, cs:15, id: 87 + (0x4a, 0), // x: 3, y:15, sw: 3, cs:15, id: 95 + (0x68, 0), // x: 4, y:15, sw: 4, cs:15, id:103 + (0x86, 0), // x: 5, y:15, sw: 5, cs:15, id:111 + (0xa4, 0), // x: 6, y:15, sw: 6, cs:15, id:119 + (0x0e, 1), // x: 7, y:15, sw: 7, cs:15, id:127 + (0x2c, 1), // x: 8, y:15, sw: 8, cs:15, id:135 + (0x7a, 1), // x: 9, y:15, sw: 4, cs:36, id:143 + (0x0f, 0), // x: 1, y:16, sw: 1, cs:16, id: 80 + (0x2d, 0), // x: 2, y:16, sw: 2, cs:16, id: 88 + (0x4b, 0), // x: 3, y:16, sw: 3, cs:16, id: 96 + (0x69, 0), // x: 4, y:16, sw: 4, cs:16, id:104 + (0x87, 0), // x: 5, y:16, sw: 5, cs:16, id:112 + (0xa5, 0), // x: 6, y:16, sw: 6, cs:16, id:120 + (0x0f, 1), // x: 7, y:16, sw: 7, cs:16, id:128 + (0x2d, 1), // x: 8, y:16, sw: 8, cs:16, id:136 + (0x7b, 1), // x: 9, y:16, sw: 4, cs:37, id:144 + (0x10, 0), // x: 1, y:17, sw: 1, cs:17, id:145 + (0x2e, 0), // x: 2, y:17, sw: 2, cs:17, id:161 + (0x4c, 0), // x: 3, y:17, sw: 3, cs:17, id:177 + (0x6a, 0), // x: 4, y:17, sw: 4, cs:17, id:193 + (0x88, 0), // x: 5, y:17, sw: 5, cs:17, id:209 + (0xa6, 0), // x: 6, y:17, sw: 6, cs:17, id:225 + (0x10, 1), // x: 7, y:17, sw: 7, cs:17, id:241 + (0x2e, 1), // x: 8, y:17, sw: 8, cs:17, id:257 + (0x7c, 1), // x: 9, y:17, sw: 4, cs:38, id:273 + (0x11, 0), // x: 1, y:18, sw: 1, cs:18, id:146 + (0x2f, 0), // x: 2, y:18, sw: 2, cs:18, id:162 + (0x4d, 0), // x: 3, y:18, sw: 3, cs:18, id:178 + (0x6b, 0), // x: 4, y:18, sw: 4, cs:18, id:194 + (0x89, 0), // x: 5, y:18, sw: 5, cs:18, id:210 + (0xa7, 0), // x: 6, y:18, sw: 6, cs:18, id:226 + (0x11, 1), // x: 7, y:18, sw: 7, cs:18, id:242 + (0x2f, 1), // x: 8, y:18, sw: 8, cs:18, id:258 + (0x79, 1), // x: 9, y:18, sw: 4, cs:35, id:274 + (0x12, 0), // x: 1, y:19, sw: 1, cs:19, id:147 + (0x30, 0), // x: 2, y:19, sw: 2, cs:19, id:163 + (0x4e, 0), // x: 3, y:19, sw: 3, cs:19, id:179 + (0x6c, 0), // x: 4, y:19, sw: 4, cs:19, id:195 + (0x8a, 0), // x: 5, y:19, sw: 5, cs:19, id:211 + (0xa8, 0), // x: 6, y:19, sw: 6, cs:19, id:227 + (0x12, 1), // x: 7, y:19, sw: 7, cs:19, id:243 + (0x30, 1), // x: 8, y:19, sw: 8, cs:19, id:259 + (0x83, 1), // x: 9, y:19, sw: 5, cs:36, id:275 + (0x13, 0), // x: 1, y:20, sw: 1, cs:20, id:148 + (0x31, 0), // x: 2, y:20, sw: 2, cs:20, id:164 + (0x4f, 0), // x: 3, y:20, sw: 3, cs:20, id:180 + (0x6d, 0), // x: 4, y:20, sw: 4, cs:20, id:196 + (0x8b, 0), // x: 5, y:20, sw: 5, cs:20, id:212 + (0xa9, 0), // x: 6, y:20, sw: 6, cs:20, id:228 + (0x13, 1), // x: 7, y:20, sw: 7, cs:20, id:244 + (0x31, 1), // x: 8, y:20, sw: 8, cs:20, id:260 + (0x84, 1), // x: 9, y:20, sw: 5, cs:37, id:276 + (0x14, 0), // x: 1, y:21, sw: 1, cs:21, id:149 + (0x32, 0), // x: 2, y:21, sw: 2, cs:21, id:165 + (0x50, 0), // x: 3, y:21, sw: 3, cs:21, id:181 + (0x6e, 0), // x: 4, y:21, sw: 4, cs:21, id:197 + (0x8c, 0), // x: 5, y:21, sw: 5, cs:21, id:213 + (0xaa, 0), // x: 6, y:21, sw: 6, cs:21, id:229 + (0x14, 1), // x: 7, y:21, sw: 7, cs:21, id:245 + (0x32, 1), // x: 8, y:21, sw: 8, cs:21, id:261 + (0x85, 1), // x: 9, y:21, sw: 5, cs:38, id:277 + (0x15, 0), // x: 1, y:22, sw: 1, cs:22, id:150 + (0x33, 0), // x: 2, y:22, sw: 2, cs:22, id:166 + (0x51, 0), // x: 3, y:22, sw: 3, cs:22, id:182 + (0x6f, 0), // x: 4, y:22, sw: 4, cs:22, id:198 + (0x8d, 0), // x: 5, y:22, sw: 5, cs:22, id:214 + (0xab, 0), // x: 6, y:22, sw: 6, cs:22, id:230 + (0x15, 1), // x: 7, y:22, sw: 7, cs:22, id:246 + (0x33, 1), // x: 8, y:22, sw: 8, cs:22, id:262 + (0x82, 1), // x: 9, y:22, sw: 5, cs:35, id:278 + (0x16, 0), // x: 1, y:23, sw: 1, cs:23, id:151 + (0x34, 0), // x: 2, y:23, sw: 2, cs:23, id:167 + (0x52, 0), // x: 3, y:23, sw: 3, cs:23, id:183 + (0x70, 0), // x: 4, y:23, sw: 4, cs:23, id:199 + (0x8e, 0), // x: 5, y:23, sw: 5, cs:23, id:215 + (0xac, 0), // x: 6, y:23, sw: 6, cs:23, id:231 + (0x16, 1), // x: 7, y:23, sw: 7, cs:23, id:247 + (0x34, 1), // x: 8, y:23, sw: 8, cs:23, id:263 + (0x8c, 1), // x: 9, y:23, sw: 6, cs:36, id:279 + (0x17, 0), // x: 1, y:24, sw: 1, cs:24, id:152 + (0x35, 0), // x: 2, y:24, sw: 2, cs:24, id:168 + (0x53, 0), // x: 3, y:24, sw: 3, cs:24, id:184 + (0x71, 0), // x: 4, y:24, sw: 4, cs:24, id:200 + (0x8f, 0), // x: 5, y:24, sw: 5, cs:24, id:216 + (0xad, 0), // x: 6, y:24, sw: 6, cs:24, id:232 + (0x17, 1), // x: 7, y:24, sw: 7, cs:24, id:248 + (0x35, 1), // x: 8, y:24, sw: 8, cs:24, id:264 + (0x8d, 1), // x: 9, y:24, sw: 6, cs:37, id:280 + (0x18, 0), // x: 1, y:25, sw: 1, cs:25, id:153 + (0x36, 0), // x: 2, y:25, sw: 2, cs:25, id:169 + (0x54, 0), // x: 3, y:25, sw: 3, cs:25, id:185 + (0x72, 0), // x: 4, y:25, sw: 4, cs:25, id:201 + (0x90, 0), // x: 5, y:25, sw: 5, cs:25, id:217 + (0xae, 0), // x: 6, y:25, sw: 6, cs:25, id:233 + (0x18, 1), // x: 7, y:25, sw: 7, cs:25, id:249 + (0x36, 1), // x: 8, y:25, sw: 8, cs:25, id:265 + (0x8e, 1), // x: 9, y:25, sw: 6, cs:38, id:281 + (0x19, 0), // x: 1, y:26, sw: 1, cs:26, id:154 + (0x37, 0), // x: 2, y:26, sw: 2, cs:26, id:170 + (0x55, 0), // x: 3, y:26, sw: 3, cs:26, id:186 + (0x73, 0), // x: 4, y:26, sw: 4, cs:26, id:202 + (0x91, 0), // x: 5, y:26, sw: 5, cs:26, id:218 + (0xaf, 0), // x: 6, y:26, sw: 6, cs:26, id:234 + (0x19, 1), // x: 7, y:26, sw: 7, cs:26, id:250 + (0x37, 1), // x: 8, y:26, sw: 8, cs:26, id:266 + (0x8b, 1), // x: 9, y:26, sw: 6, cs:35, id:282 + (0x1a, 0), // x: 1, y:27, sw: 1, cs:27, id:155 + (0x38, 0), // x: 2, y:27, sw: 2, cs:27, id:171 + (0x56, 0), // x: 3, y:27, sw: 3, cs:27, id:187 + (0x74, 0), // x: 4, y:27, sw: 4, cs:27, id:203 + (0x92, 0), // x: 5, y:27, sw: 5, cs:27, id:219 + (0xb0, 0), // x: 6, y:27, sw: 6, cs:27, id:235 + (0x1a, 1), // x: 7, y:27, sw: 7, cs:27, id:251 + (0x38, 1), // x: 8, y:27, sw: 8, cs:27, id:267 + (0x95, 1), // x: 9, y:27, sw: 7, cs:36, id:283 + (0x1b, 0), // x: 1, y:28, sw: 1, cs:28, id:156 + (0x39, 0), // x: 2, y:28, sw: 2, cs:28, id:172 + (0x57, 0), // x: 3, y:28, sw: 3, cs:28, id:188 + (0x75, 0), // x: 4, y:28, sw: 4, cs:28, id:204 + (0x93, 0), // x: 5, y:28, sw: 5, cs:28, id:220 + (0xb1, 0), // x: 6, y:28, sw: 6, cs:28, id:236 + (0x1b, 1), // x: 7, y:28, sw: 7, cs:28, id:252 + (0x39, 1), // x: 8, y:28, sw: 8, cs:28, id:268 + (0x96, 1), // x: 9, y:28, sw: 7, cs:37, id:284 + (0x1c, 0), // x: 1, y:29, sw: 1, cs:29, id:157 + (0x3a, 0), // x: 2, y:29, sw: 2, cs:29, id:173 + (0x58, 0), // x: 3, y:29, sw: 3, cs:29, id:189 + (0x76, 0), // x: 4, y:29, sw: 4, cs:29, id:205 + (0x94, 0), // x: 5, y:29, sw: 5, cs:29, id:221 + (0xb2, 0), // x: 6, y:29, sw: 6, cs:29, id:237 + (0x1c, 1), // x: 7, y:29, sw: 7, cs:29, id:253 + (0x3a, 1), // x: 8, y:29, sw: 8, cs:29, id:269 + (0x97, 1), // x: 9, y:29, sw: 7, cs:38, id:285 + (0x1d, 0), // x: 1, y:30, sw: 1, cs:30, id:158 + (0x3b, 0), // x: 2, y:30, sw: 2, cs:30, id:174 + (0x59, 0), // x: 3, y:30, sw: 3, cs:30, id:190 + (0x77, 0), // x: 4, y:30, sw: 4, cs:30, id:206 + (0x95, 0), // x: 5, y:30, sw: 5, cs:30, id:222 + (0xb3, 0), // x: 6, y:30, sw: 6, cs:30, id:238 + (0x1d, 1), // x: 7, y:30, sw: 7, cs:30, id:254 + (0x3b, 1), // x: 8, y:30, sw: 8, cs:30, id:270 + (0x94, 1), // x: 9, y:30, sw: 7, cs:35, id:286 + (0x5a, 1), // x: 1, y:31, sw: 1, cs:31, id:159 + (0x63, 1), // x: 2, y:31, sw: 2, cs:31, id:175 + (0x6c, 1), // x: 3, y:31, sw: 3, cs:31, id:191 + (0x75, 1), // x: 4, y:31, sw: 4, cs:31, id:207 + (0x7e, 1), // x: 5, y:31, sw: 5, cs:31, id:223 + (0x87, 1), // x: 6, y:31, sw: 6, cs:31, id:239 + (0x90, 1), // x: 7, y:31, sw: 7, cs:31, id:255 + (0x99, 1), // x: 8, y:31, sw: 8, cs:31, id:271 + (0x9e, 1), // x: 9, y:31, sw: 8, cs:36, id:287 + (0x5b, 1), // x: 1, y:32, sw: 1, cs:32, id:160 + (0x64, 1), // x: 2, y:32, sw: 2, cs:32, id:176 + (0x6d, 1), // x: 3, y:32, sw: 3, cs:32, id:192 + (0x76, 1), // x: 4, y:32, sw: 4, cs:32, id:208 + (0x7f, 1), // x: 5, y:32, sw: 5, cs:32, id:224 + (0x88, 1), // x: 6, y:32, sw: 6, cs:32, id:240 + (0x91, 1), // x: 7, y:32, sw: 7, cs:32, id:256 + (0x9a, 1), // x: 8, y:32, sw: 8, cs:32, id:272 + (0x9f, 1), // x: 9, y:32, sw: 8, cs:37, id:288 + (0x5c, 1), // x: 1, y:33, sw: 1, cs:33, id:289 + (0x65, 1), // x: 2, y:33, sw: 2, cs:33, id:290 + (0x6e, 1), // x: 3, y:33, sw: 3, cs:33, id:291 + (0x77, 1), // x: 4, y:33, sw: 4, cs:33, id:292 + (0x80, 1), // x: 5, y:33, sw: 5, cs:33, id:293 + (0x89, 1), // x: 6, y:33, sw: 6, cs:33, id:294 + (0x92, 1), // x: 7, y:33, sw: 7, cs:33, id:295 + (0x9b, 1), // x: 8, y:33, sw: 8, cs:33, id:296 + (0xa0, 1), // x: 9, y:33, sw: 8, cs:38, id:297 + (0x5d, 1), // x: 1, y:34, sw: 1, cs:34, id:298 + (0x66, 1), // x: 2, y:34, sw: 2, cs:34, id:299 + (0x6f, 1), // x: 3, y:34, sw: 3, cs:34, id:300 + (0x78, 1), // x: 4, y:34, sw: 4, cs:34, id:301 + (0x81, 1), // x: 5, y:34, sw: 5, cs:34, id:302 + (0x8a, 1), // x: 6, y:34, sw: 6, cs:34, id:303 + (0x93, 1), // x: 7, y:34, sw: 7, cs:34, id:304 + (0x9c, 1), // x: 8, y:34, sw: 8, cs:34, id:305 + (0x9d, 1), // x: 9, y:34, sw: 8, cs:35, id:306 + ]; + let index: usize = (x as usize) + (y as usize) * 9; + if index < lookup.len() { + lookup[index] + } else { + (0x00, 0) + } +}; + +#[cfg(feature = "framework_ledmatrix")] +pub struct LedMatrix { + pub device: IS31FL3741, +} + +#[cfg(feature = "framework_ledmatrix")] +impl LedMatrix +where + I2C: Write, + I2C: Read, +{ + pub fn unwrap(self) -> I2C { + self.device.i2c + } + + // TODO: Maybe make this private and set it once in the constructor + pub fn set_scaling(&mut self, scale: u8) -> Result<(), I2cError> { + self.device.set_scaling(scale) + } + + pub fn new(i2c: I2C, calc_pixel: fn(x: u8, y: u8) -> (u8, u8)) -> LedMatrix { + LedMatrix { + device: IS31FL3741 { + i2c, + address: 0x30, + width: 9, + height: 34, + calc_pixel, + }, + } + } + + pub fn setup>(&mut self, delay: &mut DEL) -> Result<(), Error> { + self.device.setup(delay)?; + Ok(()) + } + + /// Fills the matrix with a _raw_ brightness value, i.e. without gamma + /// correction, to show the native PWM values. + pub fn fill_brightness(&mut self, brightness: u8) -> Result<(), Error> { + for x in 0..self.device.width { + for y in 0..self.device.height { + self.device.pixel(x, y, brightness)?; + } + } + Ok(()) + } +} From e2194145d88aa9c5f2effa1a918c425f1ca9c461 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 14 Oct 2024 13:12:05 +0800 Subject: [PATCH 2/4] Add Framework LED Matrix Example Signed-off-by: Daniel Schaefer --- .github/workflows/build.yml | 13 ++- Makefile | 5 +- README.md | 1 - examples/ledmatrix/.cargo/config.toml | 20 ++++ examples/ledmatrix/Cargo.toml | 16 +++ examples/ledmatrix/README.md | 11 ++ examples/ledmatrix/build.rs | 31 ++++++ examples/ledmatrix/examples/ledtest.rs | 133 +++++++++++++++++++++++++ examples/ledmatrix/memory.x | 15 +++ examples/ledmatrix/src/lib.rs | 1 + 10 files changed, 241 insertions(+), 5 deletions(-) create mode 100644 examples/ledmatrix/.cargo/config.toml create mode 100644 examples/ledmatrix/Cargo.toml create mode 100644 examples/ledmatrix/README.md create mode 100644 examples/ledmatrix/build.rs create mode 100644 examples/ledmatrix/examples/ledtest.rs create mode 100644 examples/ledmatrix/memory.x create mode 100644 examples/ledmatrix/src/lib.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 149769e..de06612 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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 diff --git a/Makefile b/Makefile index 4a83099..83ecc3b 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index 2bc989f..f8f889d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/examples/ledmatrix/.cargo/config.toml b/examples/ledmatrix/.cargo/config.toml new file mode 100644 index 0000000..39a2c3d --- /dev/null +++ b/examples/ledmatrix/.cargo/config.toml @@ -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" diff --git a/examples/ledmatrix/Cargo.toml b/examples/ledmatrix/Cargo.toml new file mode 100644 index 0000000..01a82ba --- /dev/null +++ b/examples/ledmatrix/Cargo.toml @@ -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" diff --git a/examples/ledmatrix/README.md b/examples/ledmatrix/README.md new file mode 100644 index 0000000..f00f9d4 --- /dev/null +++ b/examples/ledmatrix/README.md @@ -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 +``` diff --git a/examples/ledmatrix/build.rs b/examples/ledmatrix/build.rs new file mode 100644 index 0000000..d534cc3 --- /dev/null +++ b/examples/ledmatrix/build.rs @@ -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"); +} diff --git a/examples/ledmatrix/examples/ledtest.rs b/examples/ledmatrix/examples/ledtest.rs new file mode 100644 index 0000000..20dcea4 --- /dev/null +++ b/examples/ledmatrix/examples/ledtest.rs @@ -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::(), + pins.gpio27.into_mode::(), + // 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); + } + } + } + } +} diff --git a/examples/ledmatrix/memory.x b/examples/ledmatrix/memory.x new file mode 100644 index 0000000..4077aab --- /dev/null +++ b/examples/ledmatrix/memory.x @@ -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; diff --git a/examples/ledmatrix/src/lib.rs b/examples/ledmatrix/src/lib.rs new file mode 100644 index 0000000..0c9ac1a --- /dev/null +++ b/examples/ledmatrix/src/lib.rs @@ -0,0 +1 @@ +#![no_std] From 96f44e9bb238fe5d5d9b4d91d3e8f54516852c13 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 14 Oct 2024 22:28:25 +0800 Subject: [PATCH 3/4] Fix clippy Signed-off-by: Daniel Schaefer --- src/devices.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devices.rs b/src/devices.rs index 2cc2910..5521980 100644 --- a/src/devices.rs +++ b/src/devices.rs @@ -5,6 +5,7 @@ use crate::{Error, IS31FL3741}; use core::convert::TryFrom; #[allow(unused_imports)] use embedded_hal::blocking::delay::DelayMs; +#[allow(unused_imports)] use embedded_hal::blocking::i2c::Read; #[allow(unused_imports)] use embedded_hal::blocking::i2c::Write; From 1674645de674d905b2389aa4bc5a500fdaa4073c Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 14 Oct 2024 22:27:08 +0800 Subject: [PATCH 4/4] gh-actions: Also run fmt and clippy Signed-off-by: Daniel Schaefer --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de06612..be30e97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,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