├── .gitignore ├── adafruit-macropad-macros ├── Cargo.toml └── src │ └── lib.rs ├── cnc-pendant ├── .cargo │ └── config.toml ├── Cargo.lock ├── Cargo.toml ├── Embed.toml ├── build.rs ├── memory.x └── src │ ├── core1.rs │ ├── keybindings.rs │ ├── main.rs │ └── painter.rs ├── display-exp1 ├── .cargo │ └── config.toml ├── Cargo.lock ├── Cargo.toml ├── Embed.toml ├── build.rs ├── memory.x └── src │ ├── graphics_exp.rs │ └── main.rs ├── gaming-pad ├── .cargo │ └── config.toml ├── Cargo.lock ├── Cargo.toml ├── Embed.toml ├── build.rs ├── memory.x └── src │ ├── core1.rs │ ├── main.rs │ ├── mission_modes.rs │ └── painter.rs ├── kbd-exp1 ├── .cargo │ └── config.toml ├── Cargo.lock ├── Cargo.toml ├── Embed.toml ├── build.rs ├── memory.x └── src │ └── main.rs ├── macropad-helpers ├── Cargo.toml └── src │ └── lib.rs └── multicore-exp1 ├── .cargo └── config.toml ├── Cargo.lock ├── Cargo.toml ├── memory.x └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.rs.bk 2 | .#* 3 | .gdb_history 4 | # Cargo.lock 5 | target/ 6 | 7 | # editor files 8 | .vscode/* 9 | !.vscode/*.md 10 | !.vscode/*.svd 11 | !.vscode/launch.json 12 | !.vscode/tasks.json 13 | !.vscode/extensions.json 14 | !.vscode/settings.json.idea 15 | 16 | *.iml 17 | .idea 18 | -------------------------------------------------------------------------------- /adafruit-macropad-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "adafruit-macropad-macros" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | 10 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 11 | embedded-time = "0.12" 12 | 13 | adafruit-macropad = "*" 14 | ws2812-pio = "0.3.0" 15 | sh1106 = "*" 16 | -------------------------------------------------------------------------------- /adafruit-macropad-macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | pub use adafruit_macropad::hal::clocks::init_clocks_and_plls; 4 | pub use adafruit_macropad::hal::clocks::Clock; 5 | pub use adafruit_macropad::hal::gpio::bank0::{ 6 | Gpio1, Gpio10, Gpio11, Gpio12, Gpio2, Gpio3, Gpio4, Gpio5, Gpio6, Gpio7, Gpio8, Gpio9, 7 | }; 8 | pub use adafruit_macropad::hal::gpio::AnyPin; 9 | pub use adafruit_macropad::hal::gpio::{FunctionSpi, Pin, PullUpInput, PushPullOutput}; 10 | pub use adafruit_macropad::hal::pio::PIOExt; 11 | pub use adafruit_macropad::hal::sio::Sio; 12 | pub use adafruit_macropad::hal::Spi; 13 | pub use adafruit_macropad::Pins; 14 | pub use adafruit_macropad::XOSC_CRYSTAL_FREQ; 15 | use core::convert::Infallible; 16 | use embedded_hal::digital::v2::InputPin; 17 | pub use embedded_hal::spi::MODE_0; 18 | pub use embedded_time::fixed_point::FixedPoint; 19 | pub use embedded_time::rate::Extensions; 20 | pub use sh1106::prelude::GraphicsMode; 21 | 22 | #[macro_export] 23 | macro_rules! macropad_neopixels { 24 | ($pins:expr, $pio:expr, $sm0: expr, $clocks:expr, $timer:expr) => {{ 25 | ws2812_pio::Ws2812::new( 26 | $pins.neopixel.into_mode(), 27 | &mut $pio, 28 | $sm0, 29 | $crate::Clock::freq(&$clocks.peripheral_clock), 30 | $timer.count_down(), 31 | ) 32 | }}; 33 | ($pins: expr, $clocks:expr, $timer:expr, $pac:expr) => {{ 34 | let (mut pio, sm0, _, _, _) = $pac.PIO0.split(&mut $pac.RESETS); 35 | macropad_neopixels!($pins, pio, sm0, $clocks, $timer) 36 | }}; 37 | } 38 | 39 | #[macro_export] 40 | macro_rules! macropad_oled { 41 | ($pins:expr, $clocks:expr, $delay: expr, $pac:expr) => {{ 42 | let _spi_sclk = $pins.sclk.into_mode::<$crate::FunctionSpi>(); 43 | let _spi_sclk = $pins.mosi.into_mode::<$crate::FunctionSpi>(); 44 | 45 | let spi1 = $crate::Spi::<_, _, 8>::new($pac.SPI1).init( 46 | &mut $pac.RESETS, 47 | $crate::Clock::freq(&$clocks.peripheral_clock), 48 | $crate::Extensions::Hz(16_000_000u32), 49 | // (16_000_000u32 as embedded_time::rate::Extensions).Hz(), 50 | &$crate::MODE_0, 51 | ); 52 | 53 | let mut oled_reset = $pins.oled_reset.into_push_pull_output(); 54 | 55 | let mut disp: $crate::GraphicsMode<_> = sh1106::Builder::new() 56 | .connect_spi( 57 | spi1, 58 | $pins.oled_dc.into_push_pull_output(), 59 | $pins.oled_cs.into_push_pull_output(), 60 | ) 61 | .into(); 62 | 63 | disp.reset(&mut oled_reset, &mut $delay).unwrap(); 64 | 65 | disp.init().unwrap(); 66 | disp 67 | }}; 68 | } 69 | 70 | #[macro_export] 71 | macro_rules! macropad_pins { 72 | ($pac:expr) => {{ 73 | let sio = $crate::Sio::new($pac.SIO); 74 | $crate::Pins::new( 75 | $pac.IO_BANK0, 76 | $pac.PADS_BANK0, 77 | sio.gpio_bank0, 78 | &mut $pac.RESETS, 79 | ) 80 | }}; 81 | } 82 | 83 | #[macro_export] 84 | macro_rules! macropad_clocks { 85 | ($pac:expr, $watchdog:expr) => { 86 | $crate::init_clocks_and_plls( 87 | $crate::XOSC_CRYSTAL_FREQ, 88 | $pac.XOSC, 89 | $pac.CLOCKS, 90 | $pac.PLL_SYS, 91 | $pac.PLL_USB, 92 | &mut $pac.RESETS, 93 | &mut $watchdog, 94 | ) 95 | .ok() 96 | .unwrap() 97 | }; 98 | } 99 | 100 | #[macro_export] 101 | macro_rules! macropad_rotary_encoder { 102 | ($pins:expr) => { 103 | Rotary::new( 104 | $pins.encoder_rota.into_pull_up_input(), 105 | $pins.encoder_rotb.into_pull_up_input(), 106 | ) 107 | }; 108 | } 109 | 110 | #[macro_export] 111 | macro_rules! macropad_keypad { 112 | ($pins:expr) => { 113 | KeysTwelve { 114 | key1: $pins.key1.into_pull_up_input(), 115 | key2: $pins.key2.into_pull_up_input(), 116 | key3: $pins.key3.into_pull_up_input(), 117 | key4: $pins.key4.into_pull_up_input(), 118 | key5: $pins.key5.into_pull_up_input(), 119 | key6: $pins.key6.into_pull_up_input(), 120 | key7: $pins.key7.into_pull_up_input(), 121 | key8: $pins.key8.into_pull_up_input(), 122 | key9: $pins.key9.into_pull_up_input(), 123 | key10: $pins.key10.into_pull_up_input(), 124 | key11: $pins.key11.into_pull_up_input(), 125 | key12: $pins.key12.into_pull_up_input(), 126 | } 127 | }; 128 | } 129 | 130 | pub struct KeysTwelve { 131 | pub key1: Pin, 132 | pub key2: Pin, 133 | pub key3: Pin, 134 | pub key4: Pin, 135 | pub key5: Pin, 136 | pub key6: Pin, 137 | pub key7: Pin, 138 | pub key8: Pin, 139 | pub key9: Pin, 140 | pub key10: Pin, 141 | pub key11: Pin, 142 | pub key12: Pin, 143 | } 144 | 145 | impl KeysTwelve { 146 | pub fn get_0based(&self, idx: i8) -> Option<&dyn InputPin> { 147 | self.get_1based(1 + idx) 148 | } 149 | 150 | pub fn get_1based(&self, idx: i8) -> Option<&dyn InputPin> { 151 | match idx { 152 | 1 => Some(&self.key1), 153 | 2 => Some(&self.key2), 154 | 3 => Some(&self.key3), 155 | 4 => Some(&self.key4), 156 | 5 => Some(&self.key5), 157 | 6 => Some(&self.key6), 158 | 7 => Some(&self.key7), 159 | 8 => Some(&self.key8), 160 | 9 => Some(&self.key9), 161 | 10 => Some(&self.key10), 162 | 11 => Some(&self.key11), 163 | 12 => Some(&self.key12), 164 | _ => None, 165 | } 166 | } 167 | 168 | pub fn array_0based(&self) -> [&dyn InputPin; 12] { 169 | [ 170 | &self.key1, 171 | &self.key2, 172 | &self.key3, 173 | &self.key4, 174 | &self.key5, 175 | &self.key6, 176 | &self.key7, 177 | &self.key8, 178 | &self.key9, 179 | &self.key10, 180 | &self.key11, 181 | &self.key12, 182 | ] 183 | } 184 | } 185 | 186 | #[cfg(bacon_check)] 187 | pub fn check1() { 188 | let mut pac = bsp::hal::pac::Peripherals::take().unwrap(); 189 | let core = bsp::hal::pac::CorePeripherals::take().unwrap(); 190 | 191 | let mut watchdog = adafruit_macropad::hal::Watchdog::new(pac.WATCHDOG); 192 | 193 | let clocks = macropad_clocks!(pac, watchdog); 194 | 195 | let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); 196 | 197 | let pins = macropad_pins!(pac); 198 | 199 | let timer = adafruit_macropad::hal::Timer::new(pac.TIMER, &mut pac.RESETS); 200 | 201 | // 202 | 203 | let mut disp = macropad_oled!(pins, clocks, delay, pac); 204 | 205 | let mut led_pin = pins.led.into_push_pull_output(); 206 | 207 | let mut neopixels = macropad_neopixels!(pins, clocks, timer, pac); 208 | } 209 | -------------------------------------------------------------------------------- /cnc-pendant/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # Choose a default "cargo run" tool: 3 | # - probe-run provides flashing and defmt via a hardware debugger 4 | # - cargo embed offers flashing, rtt, defmt and a gdb server via a hardware debugger 5 | # it is configured via the Embed.toml in the root of this project 6 | # - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode 7 | # runner = "probe-run --chip RP2040" 8 | # runner = "cargo embed" 9 | runner = "elf2uf2-rs -d" 10 | 11 | rustflags = [ 12 | "-C", "linker=flip-link", 13 | "-C", "link-arg=--nmagic", 14 | "-C", "link-arg=-Tlink.x", 15 | "-C", "link-arg=-Tdefmt.x", 16 | 17 | # Code-size optimizations. 18 | # trap unreachable can save a lot of space, but requires nightly compiler. 19 | # uncomment the next line if you wish to enable it 20 | # "-Z", "trap-unreachable=no", 21 | "-C", "inline-threshold=5", 22 | "-C", "no-vectorize-loops", 23 | ] 24 | 25 | [build] 26 | target = "thumbv6m-none-eabi" 27 | 28 | [env] 29 | DEFMT_LOG = "debug" 30 | -------------------------------------------------------------------------------- /cnc-pendant/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adafruit-macropad" 7 | version = "0.3.1" 8 | dependencies = [ 9 | "cortex-m", 10 | "cortex-m-rt", 11 | "embedded-graphics", 12 | "embedded-hal", 13 | "embedded-time", 14 | "rotary-encoder-hal", 15 | "rp2040-boot2", 16 | "rp2040-hal", 17 | "sh1106", 18 | "ws2812-pio", 19 | ] 20 | 21 | [[package]] 22 | name = "aho-corasick" 23 | version = "0.7.18" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 26 | dependencies = [ 27 | "memchr", 28 | ] 29 | 30 | [[package]] 31 | name = "arrayvec" 32 | version = "0.7.2" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 35 | 36 | [[package]] 37 | name = "autocfg" 38 | version = "1.1.0" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 41 | 42 | [[package]] 43 | name = "az" 44 | version = "1.2.0" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" 47 | 48 | [[package]] 49 | name = "bare-metal" 50 | version = "0.2.5" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 53 | dependencies = [ 54 | "rustc_version", 55 | ] 56 | 57 | [[package]] 58 | name = "bare-metal" 59 | version = "1.0.0" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 62 | 63 | [[package]] 64 | name = "bit_field" 65 | version = "0.10.1" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" 68 | 69 | [[package]] 70 | name = "bitfield" 71 | version = "0.13.2" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 74 | 75 | [[package]] 76 | name = "bitflags" 77 | version = "1.3.2" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 80 | 81 | [[package]] 82 | name = "bitmap-font" 83 | version = "0.2.2" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "75b536cf99182451e737798afe085702c72051d2499ffcdc9a77e4e7e36359b0" 86 | dependencies = [ 87 | "embedded-graphics", 88 | ] 89 | 90 | [[package]] 91 | name = "bytemuck" 92 | version = "1.10.0" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a" 95 | 96 | [[package]] 97 | name = "byteorder" 98 | version = "1.3.4" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 101 | 102 | [[package]] 103 | name = "cfg-if" 104 | version = "1.0.0" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 107 | 108 | [[package]] 109 | name = "cnc-pendant" 110 | version = "0.1.0" 111 | dependencies = [ 112 | "adafruit-macropad", 113 | "bitmap-font", 114 | "cortex-m", 115 | "cortex-m-rt", 116 | "defmt", 117 | "defmt-rtt", 118 | "either", 119 | "embedded-graphics", 120 | "embedded-graphics-core", 121 | "embedded-hal", 122 | "embedded-time", 123 | "embedded-vintage-fonts", 124 | "panic-probe", 125 | "rotary-encoder-hal", 126 | "rp-pico", 127 | "sh1106", 128 | "smart-leds-trait", 129 | "ufmt", 130 | "usb-device", 131 | "usbd-hid", 132 | "ws2812-pio", 133 | ] 134 | 135 | [[package]] 136 | name = "cortex-m" 137 | version = "0.7.5" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" 140 | dependencies = [ 141 | "bare-metal 0.2.5", 142 | "bitfield", 143 | "embedded-hal", 144 | "volatile-register", 145 | ] 146 | 147 | [[package]] 148 | name = "cortex-m-rt" 149 | version = "0.7.1" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7" 152 | dependencies = [ 153 | "cortex-m-rt-macros", 154 | ] 155 | 156 | [[package]] 157 | name = "cortex-m-rt-macros" 158 | version = "0.7.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 161 | dependencies = [ 162 | "proc-macro2", 163 | "quote", 164 | "syn", 165 | ] 166 | 167 | [[package]] 168 | name = "crc-any" 169 | version = "2.4.3" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "774646b687f63643eb0f4bf13dc263cb581c8c9e57973b6ddf78bda3994d88df" 172 | dependencies = [ 173 | "debug-helper", 174 | ] 175 | 176 | [[package]] 177 | name = "critical-section" 178 | version = "0.2.7" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" 181 | dependencies = [ 182 | "bare-metal 1.0.0", 183 | "cfg-if", 184 | "cortex-m", 185 | "riscv", 186 | ] 187 | 188 | [[package]] 189 | name = "debug-helper" 190 | version = "0.3.13" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" 193 | 194 | [[package]] 195 | name = "defmt" 196 | version = "0.3.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "d3a0ae7494d9bff013d7b89471f4c424356a71e9752e0c78abe7e6c608a16bb3" 199 | dependencies = [ 200 | "bitflags", 201 | "defmt-macros", 202 | ] 203 | 204 | [[package]] 205 | name = "defmt-macros" 206 | version = "0.3.2" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "6d944432e281084511691b36e5e9c794c19c33675822c9019e3b64f5b89e10da" 209 | dependencies = [ 210 | "defmt-parser", 211 | "proc-macro-error", 212 | "proc-macro2", 213 | "quote", 214 | "syn", 215 | ] 216 | 217 | [[package]] 218 | name = "defmt-parser" 219 | version = "0.3.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e" 222 | 223 | [[package]] 224 | name = "defmt-rtt" 225 | version = "0.3.2" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "1d2cbbbd58847d508d97629b32cd9730a2d28532f71e219714614406029f18b1" 228 | dependencies = [ 229 | "critical-section", 230 | "defmt", 231 | ] 232 | 233 | [[package]] 234 | name = "either" 235 | version = "1.7.0" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" 238 | 239 | [[package]] 240 | name = "embedded-graphics" 241 | version = "0.7.1" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b" 244 | dependencies = [ 245 | "az", 246 | "byteorder", 247 | "embedded-graphics-core", 248 | "float-cmp", 249 | "micromath", 250 | ] 251 | 252 | [[package]] 253 | name = "embedded-graphics-core" 254 | version = "0.3.3" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa" 257 | dependencies = [ 258 | "az", 259 | "byteorder", 260 | ] 261 | 262 | [[package]] 263 | name = "embedded-hal" 264 | version = "0.2.7" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 267 | dependencies = [ 268 | "nb 0.1.3", 269 | "void", 270 | ] 271 | 272 | [[package]] 273 | name = "embedded-time" 274 | version = "0.12.1" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" 277 | dependencies = [ 278 | "num", 279 | ] 280 | 281 | [[package]] 282 | name = "embedded-vintage-fonts" 283 | version = "0.1.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "d08cb21f1106211a8aa7cdf8b2e5838d9f2efa904138afefde867cd52f08ea01" 286 | dependencies = [ 287 | "embedded-graphics", 288 | ] 289 | 290 | [[package]] 291 | name = "encode_unicode" 292 | version = "0.3.6" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 295 | 296 | [[package]] 297 | name = "float-cmp" 298 | version = "0.8.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" 301 | dependencies = [ 302 | "num-traits", 303 | ] 304 | 305 | [[package]] 306 | name = "itertools" 307 | version = "0.10.3" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" 310 | dependencies = [ 311 | "either", 312 | ] 313 | 314 | [[package]] 315 | name = "lazy_static" 316 | version = "1.4.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 319 | 320 | [[package]] 321 | name = "memchr" 322 | version = "2.5.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 325 | 326 | [[package]] 327 | name = "micromath" 328 | version = "1.1.1" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94" 331 | 332 | [[package]] 333 | name = "nb" 334 | version = "0.1.3" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 337 | dependencies = [ 338 | "nb 1.0.0", 339 | ] 340 | 341 | [[package]] 342 | name = "nb" 343 | version = "1.0.0" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 346 | 347 | [[package]] 348 | name = "num" 349 | version = "0.3.1" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" 352 | dependencies = [ 353 | "num-complex", 354 | "num-integer", 355 | "num-iter", 356 | "num-rational", 357 | "num-traits", 358 | ] 359 | 360 | [[package]] 361 | name = "num-complex" 362 | version = "0.3.1" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 365 | dependencies = [ 366 | "num-traits", 367 | ] 368 | 369 | [[package]] 370 | name = "num-integer" 371 | version = "0.1.45" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 374 | dependencies = [ 375 | "autocfg", 376 | "num-traits", 377 | ] 378 | 379 | [[package]] 380 | name = "num-iter" 381 | version = "0.1.43" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 384 | dependencies = [ 385 | "autocfg", 386 | "num-integer", 387 | "num-traits", 388 | ] 389 | 390 | [[package]] 391 | name = "num-rational" 392 | version = "0.3.2" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 395 | dependencies = [ 396 | "autocfg", 397 | "num-integer", 398 | "num-traits", 399 | ] 400 | 401 | [[package]] 402 | name = "num-traits" 403 | version = "0.2.15" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 406 | dependencies = [ 407 | "autocfg", 408 | ] 409 | 410 | [[package]] 411 | name = "num_enum" 412 | version = "0.5.7" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" 415 | dependencies = [ 416 | "num_enum_derive", 417 | ] 418 | 419 | [[package]] 420 | name = "num_enum_derive" 421 | version = "0.5.7" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" 424 | dependencies = [ 425 | "proc-macro2", 426 | "quote", 427 | "syn", 428 | ] 429 | 430 | [[package]] 431 | name = "panic-probe" 432 | version = "0.3.0" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "3ab1f00eac22bd18f8e5cae9555f2820b3a0c166b5b556ee3e203746ea6dcf3a" 435 | dependencies = [ 436 | "cortex-m", 437 | "defmt", 438 | ] 439 | 440 | [[package]] 441 | name = "paste" 442 | version = "1.0.7" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" 445 | 446 | [[package]] 447 | name = "pio" 448 | version = "0.2.0" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "0fd642eada42517e6589cd7f5e830630324aec628fb4aa719000f8801e40c0a2" 451 | dependencies = [ 452 | "arrayvec", 453 | "num_enum", 454 | "paste", 455 | ] 456 | 457 | [[package]] 458 | name = "proc-macro-error" 459 | version = "1.0.4" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 462 | dependencies = [ 463 | "proc-macro-error-attr", 464 | "proc-macro2", 465 | "quote", 466 | "syn", 467 | "version_check", 468 | ] 469 | 470 | [[package]] 471 | name = "proc-macro-error-attr" 472 | version = "1.0.4" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 475 | dependencies = [ 476 | "proc-macro2", 477 | "quote", 478 | "version_check", 479 | ] 480 | 481 | [[package]] 482 | name = "proc-macro-hack" 483 | version = "0.5.19" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 486 | 487 | [[package]] 488 | name = "proc-macro2" 489 | version = "1.0.40" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" 492 | dependencies = [ 493 | "unicode-ident", 494 | ] 495 | 496 | [[package]] 497 | name = "quote" 498 | version = "1.0.20" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" 501 | dependencies = [ 502 | "proc-macro2", 503 | ] 504 | 505 | [[package]] 506 | name = "rand_core" 507 | version = "0.6.3" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 510 | 511 | [[package]] 512 | name = "regex" 513 | version = "1.6.0" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 516 | dependencies = [ 517 | "aho-corasick", 518 | "memchr", 519 | "regex-syntax", 520 | ] 521 | 522 | [[package]] 523 | name = "regex-syntax" 524 | version = "0.6.27" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 527 | 528 | [[package]] 529 | name = "rgb" 530 | version = "0.8.33" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" 533 | dependencies = [ 534 | "bytemuck", 535 | ] 536 | 537 | [[package]] 538 | name = "riscv" 539 | version = "0.7.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" 542 | dependencies = [ 543 | "bare-metal 1.0.0", 544 | "bit_field", 545 | "riscv-target", 546 | ] 547 | 548 | [[package]] 549 | name = "riscv-target" 550 | version = "0.1.2" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" 553 | dependencies = [ 554 | "lazy_static", 555 | "regex", 556 | ] 557 | 558 | [[package]] 559 | name = "rotary-encoder-hal" 560 | version = "0.5.0" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "ca5f10fcd6842ed448d9f5913815a343cdcbe10e53da6cac948251d529b75487" 563 | dependencies = [ 564 | "either", 565 | "embedded-hal", 566 | ] 567 | 568 | [[package]] 569 | name = "rp-pico" 570 | version = "0.4.1" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "6b83448890aab5f6e35aa64d6a2441d69b768e7a22aaf943a84b7459340028ec" 573 | dependencies = [ 574 | "cortex-m", 575 | "cortex-m-rt", 576 | "embedded-time", 577 | "rp2040-boot2", 578 | "rp2040-hal", 579 | "usb-device", 580 | "usbd-hid", 581 | "usbd-serial", 582 | ] 583 | 584 | [[package]] 585 | name = "rp2040-boot2" 586 | version = "0.2.0" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "8b480fe63133f0d639f82ce5a027fee7cac7ac92f67ef1896ee036a6f9737128" 589 | dependencies = [ 590 | "crc-any", 591 | ] 592 | 593 | [[package]] 594 | name = "rp2040-hal" 595 | version = "0.5.0" 596 | dependencies = [ 597 | "cortex-m", 598 | "cortex-m-rt", 599 | "critical-section", 600 | "embedded-hal", 601 | "embedded-time", 602 | "itertools", 603 | "nb 1.0.0", 604 | "paste", 605 | "pio", 606 | "rand_core", 607 | "rp2040-hal-macros", 608 | "rp2040-pac", 609 | "usb-device", 610 | "vcell", 611 | "void", 612 | ] 613 | 614 | [[package]] 615 | name = "rp2040-hal-macros" 616 | version = "0.1.0" 617 | dependencies = [ 618 | "cortex-m-rt", 619 | "proc-macro2", 620 | "quote", 621 | "syn", 622 | ] 623 | 624 | [[package]] 625 | name = "rp2040-pac" 626 | version = "0.3.0" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "13a6106d5db01c7171a39c1f7696780912db9b42fe7ac722db60069c8904ea7c" 629 | dependencies = [ 630 | "cortex-m", 631 | "cortex-m-rt", 632 | "vcell", 633 | ] 634 | 635 | [[package]] 636 | name = "rustc_version" 637 | version = "0.2.3" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 640 | dependencies = [ 641 | "semver", 642 | ] 643 | 644 | [[package]] 645 | name = "semver" 646 | version = "0.9.0" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 649 | dependencies = [ 650 | "semver-parser", 651 | ] 652 | 653 | [[package]] 654 | name = "semver-parser" 655 | version = "0.7.0" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 658 | 659 | [[package]] 660 | name = "serde" 661 | version = "1.0.140" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" 664 | 665 | [[package]] 666 | name = "sh1106" 667 | version = "0.4.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "4b4022685baa7cc82b2fb97ced2b53fd753a21d98f45b0fd0b55fc717de9075a" 670 | dependencies = [ 671 | "embedded-graphics-core", 672 | "embedded-hal", 673 | ] 674 | 675 | [[package]] 676 | name = "smart-leds-trait" 677 | version = "0.2.1" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3" 680 | dependencies = [ 681 | "rgb", 682 | ] 683 | 684 | [[package]] 685 | name = "ssmarshal" 686 | version = "1.0.0" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" 689 | dependencies = [ 690 | "encode_unicode", 691 | "serde", 692 | ] 693 | 694 | [[package]] 695 | name = "syn" 696 | version = "1.0.98" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" 699 | dependencies = [ 700 | "proc-macro2", 701 | "quote", 702 | "unicode-ident", 703 | ] 704 | 705 | [[package]] 706 | name = "ufmt" 707 | version = "0.1.0" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "2e7ecea7ef79d3f8f878eee614afdf5256475c63ad76139d4da6125617c784a0" 710 | dependencies = [ 711 | "proc-macro-hack", 712 | "ufmt-macros", 713 | "ufmt-write", 714 | ] 715 | 716 | [[package]] 717 | name = "ufmt-macros" 718 | version = "0.1.1" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "ed813e34a2bfa9dc58ee2ed8c8314d25e6d70c911486d64b8085cb695cfac069" 721 | dependencies = [ 722 | "proc-macro-hack", 723 | "proc-macro2", 724 | "quote", 725 | "syn", 726 | ] 727 | 728 | [[package]] 729 | name = "ufmt-write" 730 | version = "0.1.0" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" 733 | 734 | [[package]] 735 | name = "unicode-ident" 736 | version = "1.0.2" 737 | source = "registry+https://github.com/rust-lang/crates.io-index" 738 | checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" 739 | 740 | [[package]] 741 | name = "usb-device" 742 | version = "0.2.8" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245" 745 | 746 | [[package]] 747 | name = "usbd-hid" 748 | version = "0.5.2" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "183b7e65bbd75512aedf250deda89394c74ae3118b79fe41f159e8503e1d5d7f" 751 | dependencies = [ 752 | "serde", 753 | "ssmarshal", 754 | "usb-device", 755 | "usbd-hid-macros", 756 | ] 757 | 758 | [[package]] 759 | name = "usbd-hid-descriptors" 760 | version = "0.1.1" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "9e00430c0b39caf3957aba6c2b2824f8e70e1ac0278941418bf1fe35f9566d64" 763 | dependencies = [ 764 | "bitfield", 765 | ] 766 | 767 | [[package]] 768 | name = "usbd-hid-macros" 769 | version = "0.5.2" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "78bd005b3aa54e62905d99df49a75d11888bb958eb780adb5e8f2029733077df" 772 | dependencies = [ 773 | "byteorder", 774 | "proc-macro2", 775 | "quote", 776 | "serde", 777 | "syn", 778 | "usbd-hid-descriptors", 779 | ] 780 | 781 | [[package]] 782 | name = "usbd-serial" 783 | version = "0.1.1" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe" 786 | dependencies = [ 787 | "embedded-hal", 788 | "nb 0.1.3", 789 | "usb-device", 790 | ] 791 | 792 | [[package]] 793 | name = "vcell" 794 | version = "0.1.3" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 797 | 798 | [[package]] 799 | name = "version_check" 800 | version = "0.9.4" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 803 | 804 | [[package]] 805 | name = "void" 806 | version = "1.0.2" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 809 | 810 | [[package]] 811 | name = "volatile-register" 812 | version = "0.2.1" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" 815 | dependencies = [ 816 | "vcell", 817 | ] 818 | 819 | [[package]] 820 | name = "ws2812-pio" 821 | version = "0.3.0" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "59c8b2e9830ab583b86349261a5980a0a33151f812abbb21019444822bb61d27" 824 | dependencies = [ 825 | "cortex-m", 826 | "embedded-hal", 827 | "embedded-time", 828 | "nb 1.0.0", 829 | "pio", 830 | "rp2040-hal", 831 | "smart-leds-trait", 832 | ] 833 | -------------------------------------------------------------------------------- /cnc-pendant/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "cnc-pendant" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | cortex-m = "0.7" 8 | cortex-m-rt = "0.7" 9 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 10 | embedded-time = "0.12" 11 | 12 | defmt = "0.3" 13 | defmt-rtt = "0.3" 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } 15 | 16 | 17 | adafruit-macropad = "*" 18 | ws2812-pio = "0.3.0" 19 | smart-leds-trait = "*" 20 | embedded-graphics-core = "*" 21 | embedded-graphics = "0.7.1" 22 | sh1106="*" 23 | bitmap-font="*" 24 | embedded-vintage-fonts = "*" 25 | 26 | 27 | rotary-encoder-hal = "*" 28 | ufmt="*" 29 | usbd-hid="*" 30 | usb-device="*" 31 | 32 | # We're using a Pico by default on this template 33 | rp-pico = "0.4" 34 | # but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead 35 | # sparkfun-pro-micro-rp2040 = "0.3" 36 | 37 | # If you're not going to use a Board Support Package you'll need these: 38 | # rp2040-hal = { version="0.5", features=["rt"] } 39 | # rp2040-boot2 = "0.2" 40 | 41 | 42 | #[dependencies.sh1107] 43 | #git="https://github.com/aaron-hardin/sh1107.git" 44 | 45 | [dependencies.either] 46 | version = "*" 47 | default-features = false 48 | 49 | 50 | # cargo build/run 51 | [profile.dev] 52 | codegen-units = 1 53 | debug = 2 54 | debug-assertions = true 55 | incremental = false 56 | opt-level = 3 57 | overflow-checks = true 58 | 59 | # cargo build/run --release 60 | [profile.release] 61 | codegen-units = 1 62 | debug = 2 63 | debug-assertions = false 64 | incremental = false 65 | lto = 'fat' 66 | opt-level = 3 67 | overflow-checks = false 68 | 69 | # do not optimize proc-macro crates = faster builds from scratch 70 | [profile.dev.build-override] 71 | codegen-units = 8 72 | debug = false 73 | debug-assertions = false 74 | opt-level = 0 75 | overflow-checks = false 76 | 77 | [profile.release.build-override] 78 | codegen-units = 8 79 | debug = false 80 | debug-assertions = false 81 | opt-level = 0 82 | overflow-checks = false 83 | 84 | # cargo test 85 | [profile.test] 86 | codegen-units = 1 87 | debug = 2 88 | debug-assertions = true 89 | incremental = false 90 | opt-level = 3 91 | overflow-checks = true 92 | 93 | # cargo test --release 94 | [profile.bench] 95 | codegen-units = 1 96 | debug = 2 97 | debug-assertions = false 98 | incremental = false 99 | lto = 'fat' 100 | opt-level = 3 101 | 102 | 103 | [patch.crates-io] 104 | 105 | adafruit-macropad = { path = "../../../vendor/rp-hal/boards/adafruit-macropad"} 106 | rp2040-hal = { path = "../../../vendor/rp-hal/rp2040-hal"} 107 | -------------------------------------------------------------------------------- /cnc-pendant/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | protocol = "Swd" 3 | speed = 20000 4 | # If you only have one probe cargo embed will pick automatically 5 | # Otherwise: add your probe's VID/PID/serial to filter 6 | 7 | ## rust-dap 8 | # usb_vid = "6666" 9 | # usb_pid = "4444" 10 | # serial = "test" 11 | 12 | 13 | [default.flashing] 14 | enabled = true 15 | 16 | [default.reset] 17 | enabled = true 18 | halt_afterwards = false 19 | 20 | [default.general] 21 | chip = "RP2040" 22 | log_level = "WARN" 23 | # RP2040 does not support connect_under_reset 24 | connect_under_reset = false 25 | 26 | [default.rtt] 27 | enabled = true 28 | up_mode = "NoBlockSkip" 29 | channels = [ 30 | { up = 0, down = 0, name = "name", up_mode = "NoBlockSkip", format = "Defmt" }, 31 | ] 32 | timeout = 3000 33 | show_timestamps = true 34 | log_enabled = false 35 | log_path = "./logs" 36 | 37 | [default.gdb] 38 | enabled = false 39 | gdb_connection_string = "127.0.0.1:2345" 40 | -------------------------------------------------------------------------------- /cnc-pendant/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /cnc-pendant/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; -------------------------------------------------------------------------------- /cnc-pendant/src/core1.rs: -------------------------------------------------------------------------------- 1 | use adafruit_macropad::hal::sio::SioFifo; 2 | use adafruit_macropad::{pac, KeysTwelve, Sio}; 3 | use embedded_hal::digital::v2::InputPin; 4 | use rotary_encoder_hal::{Direction, Rotary}; 5 | 6 | #[derive(Debug, Copy, Clone, PartialEq)] 7 | pub enum JogAxis { 8 | X, 9 | Y, 10 | Z, 11 | } 12 | 13 | impl JogAxis { 14 | pub fn as_int(&self) -> u32 { 15 | match self { 16 | JogAxis::X => 0, 17 | JogAxis::Y => 1, 18 | JogAxis::Z => 2, 19 | } 20 | } 21 | } 22 | 23 | impl TryFrom for JogAxis { 24 | type Error = (); 25 | 26 | fn try_from(value: u32) -> Result { 27 | match value { 28 | 0 => Ok(JogAxis::X), 29 | 1 => Ok(JogAxis::Y), 30 | 2 => Ok(JogAxis::Z), 31 | _ => Err(()), 32 | } 33 | } 34 | } 35 | 36 | #[derive(Debug, Copy, Clone)] 37 | #[allow(clippy::upper_case_acronyms)] 38 | pub enum LastJog { 39 | None, 40 | CW, 41 | CCW, 42 | } 43 | 44 | impl LastJog { 45 | pub fn as_int(&self) -> u32 { 46 | match self { 47 | LastJog::None => 0, 48 | LastJog::CW => 1, 49 | LastJog::CCW => 2, 50 | } 51 | } 52 | } 53 | 54 | impl TryFrom for LastJog { 55 | type Error = (); 56 | 57 | fn try_from(value: u32) -> Result { 58 | match value { 59 | 0 => Ok(LastJog::None), 60 | 1 => Ok(LastJog::CW), 61 | 2 => Ok(LastJog::CCW), 62 | _ => Err(()), 63 | } 64 | } 65 | } 66 | 67 | // 68 | 69 | struct Core1Application 70 | where 71 | RotA: InputPin, 72 | RotB: InputPin, 73 | { 74 | rotary: Rotary, 75 | keys: KeysTwelve, 76 | 77 | jog_axis: JogAxis, 78 | jog_scale: u8, 79 | last_jog: LastJog, 80 | last_key: Option, 81 | key_state: [bool; 12], 82 | old_key_state: [bool; 12], 83 | } 84 | 85 | impl Core1Application 86 | where 87 | RotA: InputPin, 88 | RotB: InputPin, 89 | { 90 | pub fn new(rotary: Rotary, keys: KeysTwelve) -> Self { 91 | Core1Application { 92 | rotary, 93 | keys, 94 | jog_axis: JogAxis::X, 95 | jog_scale: 0, 96 | last_jog: LastJog::None, 97 | last_key: None, 98 | key_state: [false; 12], 99 | old_key_state: [false; 12], 100 | } 101 | } 102 | 103 | pub fn one_pass(&mut self, fifo: &mut SioFifo) { 104 | self.last_jog = match self.rotary.update() { 105 | Ok(Direction::Clockwise) => LastJog::CW, 106 | Ok(Direction::CounterClockwise) => LastJog::CCW, 107 | _ => LastJog::None, 108 | }; 109 | 110 | { 111 | let keys_array = self.keys.array_0based(); 112 | for (idx, state) in self.key_state.iter_mut().enumerate() { 113 | let pressed = keys_array[idx].is_low().unwrap(); 114 | *state = pressed; 115 | } 116 | } 117 | 118 | let recently_pressed = self 119 | .key_state 120 | .iter() 121 | .zip(self.old_key_state.iter()) 122 | .enumerate() 123 | .find(|(_, (fresh, old))| **fresh && !**old) 124 | .map(|(idx, _)| idx as u8); 125 | 126 | let recently_pressed = recently_pressed.or_else(|| { 127 | if let Some(idx) = self.last_key { 128 | if self.key_state[idx as usize] { 129 | return Some(idx); 130 | } 131 | } 132 | self.key_state 133 | .iter() 134 | .enumerate() 135 | .filter_map(|(idx, fresh)| if *fresh { Some(idx as u8) } else { None }) 136 | .next() 137 | }); 138 | 139 | self.last_key = recently_pressed; 140 | 141 | match self.last_key { 142 | Some(9) => self.jog_axis = JogAxis::X, 143 | Some(10) => self.jog_axis = JogAxis::Y, 144 | Some(11) => self.jog_axis = JogAxis::Z, 145 | _ => {} 146 | } 147 | 148 | // 149 | 150 | self.maybe_send_state(fifo); 151 | 152 | self.old_key_state = self.key_state; 153 | } 154 | 155 | fn maybe_send_state(&mut self, fifo: &mut SioFifo) { 156 | let msg = fifo.read(); 157 | if let Some(msg) = msg { 158 | if 0 == msg { 159 | InterCoreMessage { 160 | jog_axis: self.jog_axis, 161 | jog_action: self.last_jog, 162 | last_key: self.last_key, 163 | jog_scale: self.jog_scale, 164 | } 165 | .send(fifo); 166 | } 167 | } 168 | } 169 | } 170 | 171 | pub fn core1_task(rotary: Rotary, keys: KeysTwelve) -> ! 172 | where 173 | ROTA: InputPin, 174 | ROTB: InputPin, 175 | { 176 | let pac = unsafe { pac::Peripherals::steal() }; 177 | // let core = unsafe { pac::CorePeripherals::steal() }; 178 | let mut sio = Sio::new(pac.SIO); 179 | 180 | let mut app = Core1Application::new(rotary, keys); 181 | 182 | // 183 | 184 | loop { 185 | app.one_pass(&mut sio.fifo); 186 | } 187 | } 188 | 189 | pub struct InterCoreMessage { 190 | pub jog_axis: JogAxis, 191 | pub jog_action: LastJog, 192 | pub jog_scale: u8, 193 | pub last_key: Option, 194 | } 195 | 196 | impl InterCoreMessage { 197 | pub fn send(&self, fifo: &mut SioFifo) { 198 | fifo.write_blocking(self.jog_axis.as_int()); 199 | 200 | fifo.write_blocking(self.jog_action.as_int()); 201 | 202 | fifo.write_blocking(self.jog_scale as u32); 203 | 204 | let last_key = self.last_key.map(|x| x as u32).unwrap_or(u32::MAX) as u32; 205 | fifo.write_blocking(last_key); 206 | } 207 | 208 | pub fn receive(fifo: &mut SioFifo) -> Result { 209 | let jog_axis: JogAxis = fifo.read_blocking().try_into()?; 210 | let jog_action: LastJog = fifo.read_blocking().try_into()?; 211 | let jog_scale = fifo.read_blocking().clamp(0, 3) as u8; 212 | let raw = fifo.read_blocking(); 213 | let last_key = match raw { 214 | 0..=11 => Some(raw as u8), 215 | _ => None, 216 | }; 217 | 218 | Ok(Self { 219 | jog_axis, 220 | last_key, 221 | jog_action, 222 | jog_scale, 223 | }) 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /cnc-pendant/src/keybindings.rs: -------------------------------------------------------------------------------- 1 | use usbd_hid::descriptor::KeyboardReport; 2 | 3 | pub const LEFT_CTRL: u8 = 1; 4 | #[allow(dead_code)] 5 | pub const LEFT_SHIFT: u8 = 2; 6 | pub const LEFT_ALT: u8 = 4; 7 | #[allow(dead_code)] 8 | pub const LEFT_META: u8 = 8; 9 | 10 | pub const KP_PAGE_UP: u8 = 0x4b; 11 | pub const KP_PAGE_DOWN: u8 = 0x4e; 12 | pub const KP_RIGHT_ARROW: u8 = 0x4f; 13 | pub const KP_LEFT_ARROW: u8 = 0x50; 14 | pub const KP_DOWN_ARROW: u8 = 0x51; 15 | pub const KP_UP_ARROW: u8 = 0x52; 16 | 17 | pub fn simple_kr(modifier: u8, keycodes: [u8; 6]) -> KeyboardReport { 18 | KeyboardReport { 19 | modifier, 20 | reserved: 0, 21 | leds: 0, 22 | keycodes, 23 | } 24 | } 25 | 26 | pub fn simple_kr1(modifier: u8, key_code_1: u8) -> KeyboardReport { 27 | simple_kr(modifier, [key_code_1, 0, 0, 0, 0, 0]) 28 | } 29 | 30 | fn number_keycode(digit: u8) -> u8 { 31 | match digit { 32 | 0 => 0x27, 33 | _ => 0x1d + digit, 34 | } 35 | } 36 | 37 | // 38 | 39 | pub fn key_z_minus() -> KeyboardReport { 40 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_PAGE_DOWN) 41 | } 42 | 43 | pub fn key_z_plus() -> KeyboardReport { 44 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_PAGE_UP) 45 | } 46 | 47 | pub fn key_y_minus() -> KeyboardReport { 48 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_DOWN_ARROW) 49 | } 50 | 51 | pub fn key_x_plus() -> KeyboardReport { 52 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_RIGHT_ARROW) 53 | } 54 | 55 | pub fn key_x_minus() -> KeyboardReport { 56 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_LEFT_ARROW) 57 | } 58 | 59 | pub fn key_y_plus() -> KeyboardReport { 60 | simple_kr1(LEFT_CTRL | LEFT_ALT, KP_UP_ARROW) 61 | } 62 | 63 | pub fn key_jog_scale(jog_scale: u8) -> KeyboardReport { 64 | simple_kr1(LEFT_CTRL | LEFT_ALT, number_keycode(1 + jog_scale)) 65 | } 66 | -------------------------------------------------------------------------------- /cnc-pendant/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Blinks the LED on a Pico board 2 | //! 3 | //! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. 4 | #![no_std] 5 | #![no_main] 6 | 7 | use core::str::from_utf8_unchecked; 8 | // Provide an alias for our BSP so we can switch targets quickly. 9 | // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. 10 | use rp_pico as bsp; 11 | // use sparkfun_pro_micro_rp2040 as bsp; 12 | 13 | use crate::core1::{InterCoreMessage, JogAxis, LastJog}; 14 | use crate::keybindings::{ 15 | key_x_minus, key_x_plus, key_y_minus, key_y_plus, key_z_minus, key_z_plus, 16 | }; 17 | use adafruit_macropad::hal::gpio::{Function, Pin, PinId, PushPullOutput, ValidPinMode}; 18 | use adafruit_macropad::hal::multicore::{Multicore, Stack}; 19 | use adafruit_macropad::hal::pio::SM0; 20 | use adafruit_macropad::hal::sio::SioFifo; 21 | use adafruit_macropad::hal::timer::CountDown; 22 | use adafruit_macropad::hal::usb::UsbBus; 23 | use adafruit_macropad::hal::Timer; 24 | use adafruit_macropad::{ 25 | macropad_clocks, macropad_keypad, macropad_neopixels, macropad_oled, macropad_pins, 26 | macropad_rotary_encoder, Sio, 27 | }; 28 | use bsp::entry; 29 | use bsp::hal::pac::PIO0; 30 | use bsp::hal::{clocks::Clock, pac, watchdog::Watchdog}; 31 | use defmt::*; 32 | use defmt_rtt as _; 33 | use embedded_hal::digital::v2::OutputPin; 34 | use embedded_time::fixed_point::FixedPoint; 35 | use painter::DisplayPainter; 36 | use panic_probe as _; 37 | use smart_leds_trait::SmartLedsWrite; 38 | use ufmt::{uWrite, uwrite}; 39 | use usb_device::bus::UsbBusAllocator; 40 | use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbDeviceState, UsbVidPid}; 41 | use usbd_hid::descriptor::{KeyboardReport, MouseReport, SerializedDescriptor}; 42 | use usbd_hid::hid_class::HIDClass; 43 | use ws2812_pio::Ws2812; 44 | 45 | mod core1; 46 | mod keybindings; 47 | mod painter; 48 | 49 | static mut CORE1_STACK: Stack<4096> = Stack::new(); 50 | 51 | #[entry] 52 | fn main() -> ! { 53 | info!("Program start"); 54 | let mut pac = pac::Peripherals::take().unwrap(); 55 | let core = pac::CorePeripherals::take().unwrap(); 56 | 57 | let mut watchdog = Watchdog::new(pac.WATCHDOG); 58 | 59 | let clocks = macropad_clocks!(pac, watchdog); 60 | 61 | let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); 62 | let mut sio = Sio::new(pac.SIO); 63 | let pins = macropad_pins!(pac, sio); 64 | 65 | let timer = Timer::new(pac.TIMER, &mut pac.RESETS); 66 | 67 | // 68 | 69 | let mut disp = macropad_oled!(pins, clocks, delay, pac); 70 | 71 | let mut led_pin = pins.led.into_push_pull_output(); 72 | 73 | let mut neopixels = macropad_neopixels!(pins, clocks, timer, pac); 74 | 75 | // 76 | 77 | let rotary = macropad_rotary_encoder!(pins); 78 | 79 | let keys = macropad_keypad!(pins); 80 | 81 | let usb_bus = UsbBusAllocator::new(adafruit_macropad::hal::usb::UsbBus::new( 82 | pac.USBCTRL_REGS, 83 | pac.USBCTRL_DPRAM, 84 | clocks.usb_clock, 85 | true, 86 | &mut pac.RESETS, 87 | )); 88 | let mut keyboard_hid = HIDClass::new(&usb_bus, KeyboardReport::desc(), 10); 89 | let mut mouse_hid = HIDClass::new(&usb_bus, MouseReport::desc(), 10); 90 | let mut usb_device = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x239a, 0xbeef)) 91 | .product("macropad-usbd") 92 | .manufacturer("Bob's mad science") 93 | .build(); 94 | 95 | loop { 96 | //support::poll_logger(); 97 | if !usb_device.poll(&mut [&mut keyboard_hid, &mut mouse_hid]) { 98 | continue; 99 | } 100 | let state = usb_device.state(); 101 | if state == UsbDeviceState::Configured { 102 | break; 103 | } 104 | } 105 | 106 | // usb_device.bus().configure(); 107 | 108 | // 109 | // 110 | 111 | disp.clear(); 112 | 113 | //let sys_freq = clocks.system_clock.freq().integer(); 114 | let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo); 115 | let cores = mc.cores(); 116 | let core1 = &mut cores[1]; 117 | let _test = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { 118 | core1::core1_task(rotary, keys) 119 | }); 120 | 121 | let mut application = ApplicationLoop::new( 122 | disp, 123 | &mut led_pin, 124 | &mut neopixels, 125 | sio.fifo, 126 | &mut usb_device, 127 | &mut keyboard_hid, 128 | ); 129 | 130 | loop { 131 | let usec = timer.get_counter(); 132 | application.one_pass((usec / 1000) as u32); 133 | let _ = application.display_painter.disp.flush(); 134 | //delay.delay_ms(1); 135 | } 136 | } 137 | 138 | // 139 | 140 | struct UsbGenerator<'a> { 141 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 142 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 143 | debug_msg: UfmtWrapper<200>, 144 | } 145 | 146 | impl<'a> UsbGenerator<'a> { 147 | pub fn new( 148 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 149 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 150 | ) -> Self { 151 | UsbGenerator { 152 | usb_device, 153 | keyboard_hid, 154 | debug_msg: UfmtWrapper::new(), 155 | } 156 | } 157 | 158 | pub fn generate_usb_events( 159 | &mut self, 160 | jog_axis: JogAxis, 161 | jog_action: LastJog, 162 | key_pressed: Option, 163 | ) { 164 | self.debug_msg.reset(); 165 | 166 | let kr = Self::simple_keyboard_action(key_pressed); 167 | 168 | let _ = uwrite!(&mut self.debug_msg, "k {:?}", key_pressed); 169 | 170 | self.send_keyboard_report(&kr); 171 | } 172 | 173 | pub fn send_keyboard_report(&mut self, kr: &KeyboardReport) -> bool { 174 | self.usb_device.poll(&mut [self.keyboard_hid]); 175 | 176 | self.keyboard_hid.push_input(kr).is_ok() 177 | } 178 | 179 | pub fn simple_keyboard_action(key_pressed: Option) -> KeyboardReport { 180 | let kr: KeyboardReport = match key_pressed { 181 | Some(1) => key_y_plus(), 182 | Some(3) => key_x_minus(), 183 | Some(5) => key_x_plus(), 184 | Some(7) => key_y_minus(), 185 | Some(2) => key_z_plus(), 186 | Some(8) => key_z_minus(), 187 | _ => keybindings::simple_kr1(0, 0), 188 | }; 189 | kr 190 | } 191 | } 192 | 193 | // 194 | 195 | struct ApplicationLoop<'a, D, LED, NEOPIN, E> 196 | where 197 | D: embedded_graphics_core::draw_target::DrawTarget< 198 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 199 | Error = E, 200 | >, 201 | LED: PinId, 202 | NEOPIN: PinId, 203 | Function: ValidPinMode, 204 | { 205 | display_painter: DisplayPainter, 206 | led_pin: &'a mut Pin, 207 | neopixels: &'a mut Ws2812, NEOPIN>, 208 | 209 | last_key: Option, 210 | jog_axis: JogAxis, 211 | jog_scale: u8, 212 | jog_scale_down: bool, 213 | 214 | fifo: SioFifo, 215 | generator: UsbGenerator<'a>, 216 | } 217 | 218 | impl<'a, D, LED, NEOPIN, E> ApplicationLoop<'a, D, LED, NEOPIN, E> 219 | where 220 | D: embedded_graphics_core::draw_target::DrawTarget< 221 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 222 | Error = E, 223 | >, 224 | LED: PinId, 225 | 226 | NEOPIN: PinId, 227 | Function: ValidPinMode, 228 | { 229 | pub fn new( 230 | disp: D, 231 | led_pin: &'a mut Pin, 232 | neopixels: &'a mut Ws2812, NEOPIN>, 233 | fifo: SioFifo, 234 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 235 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 236 | ) -> Self { 237 | ApplicationLoop { 238 | display_painter: DisplayPainter::new(disp), 239 | led_pin, 240 | neopixels, 241 | last_key: None, 242 | jog_axis: JogAxis::X, 243 | jog_scale: 0, 244 | jog_scale_down: false, 245 | fifo, 246 | generator: UsbGenerator::new(usb_device, keyboard_hid), 247 | } 248 | } 249 | 250 | pub fn one_pass(&mut self, epoch_millis: u32) { 251 | if epoch_millis & 0x100 == 0 { 252 | self.led_pin.set_high().unwrap(); 253 | } else { 254 | self.led_pin.set_low().unwrap(); 255 | } 256 | 257 | let (jog_action, _) = match poll_core1(&mut self.fifo) { 258 | Some(msg) => { 259 | self.last_key = msg.last_key; 260 | self.jog_axis = msg.jog_axis; 261 | (msg.jog_action, msg.jog_scale) 262 | } 263 | None => (LastJog::None, self.jog_scale), 264 | }; 265 | 266 | let jog_scale = if self.last_key == Some(4) { 267 | if !self.jog_scale_down { 268 | (1 + self.jog_scale) % 4 269 | } else { 270 | self.jog_scale 271 | } 272 | } else { 273 | self.jog_scale_down = false; 274 | self.jog_scale 275 | }; 276 | 277 | let _ = self 278 | .neopixels 279 | .write(lights_for(self.jog_axis, self.last_key)); 280 | 281 | if jog_scale != self.jog_scale { 282 | let kr = keybindings::key_jog_scale(jog_scale); 283 | if self.generator.send_keyboard_report(&kr) { 284 | self.jog_scale = jog_scale; 285 | self.jog_scale_down = true; 286 | } 287 | } else { 288 | self.generator 289 | .generate_usb_events(self.jog_axis, jog_action, self.last_key); 290 | } 291 | 292 | if false { 293 | let _ = self.display_painter.update_display( 294 | 0, 295 | [false; 12], 296 | None, 297 | self.generator.debug_msg.as_str(), 298 | ); 299 | self.generator.debug_msg.reset(); 300 | } else { 301 | let _ = self.display_painter.idle_display(); 302 | } 303 | } 304 | } 305 | 306 | fn poll_core1(fifo: &mut SioFifo) -> Option { 307 | if !fifo.is_write_ready() { 308 | return None; 309 | } 310 | 311 | fifo.write(0); 312 | 313 | InterCoreMessage::receive(fifo).ok() 314 | } 315 | 316 | fn lights_for(jog_axis: JogAxis, last_key: Option) -> impl Iterator { 317 | const X_COLOR: (u8, u8, u8) = (255, 0, 255); 318 | const Y_COLOR: (u8, u8, u8) = (0, 255, 255); 319 | const Z_COLOR: (u8, u8, u8) = (0, 0, 255); 320 | 321 | let mut rgbs = [ 322 | (0, 0, 0), 323 | Y_COLOR, 324 | Z_COLOR, 325 | X_COLOR, 326 | (255, 255, 0), 327 | X_COLOR, 328 | (0, 0, 0), 329 | Y_COLOR, 330 | Z_COLOR, 331 | X_COLOR, 332 | Y_COLOR, 333 | Z_COLOR, 334 | ]; 335 | 336 | if let Some(idx) = last_key { 337 | rgbs[idx as usize] = (255, 255, 255); 338 | } 339 | 340 | { 341 | rgbs[(jog_axis.as_int() + 9) as usize] = (0, 255, 255); 342 | } 343 | 344 | let dim = 32; 345 | rgbs[9] = if jog_axis == JogAxis::X { 346 | X_COLOR 347 | } else { 348 | (dim, 0, dim) 349 | }; 350 | rgbs[10] = if jog_axis == JogAxis::Y { 351 | Y_COLOR 352 | } else { 353 | (0, dim, dim) 354 | }; 355 | rgbs[11] = if jog_axis == JogAxis::Z { 356 | Z_COLOR 357 | } else { 358 | (0, 0, dim) 359 | }; 360 | 361 | rgbs.into_iter() 362 | } 363 | 364 | struct ChangeDetector { 365 | pub old: T, 366 | } 367 | 368 | impl ChangeDetector { 369 | pub fn new(first: T) -> Self { 370 | ChangeDetector { old: first } 371 | } 372 | 373 | pub fn changed(&mut self, new_val: T) -> bool { 374 | if new_val == self.old { 375 | false 376 | } else { 377 | self.old = new_val; 378 | true 379 | } 380 | } 381 | } 382 | 383 | // 384 | // 385 | 386 | struct UfmtWrapper { 387 | cursor: usize, 388 | buffer: [u8; N], 389 | } 390 | 391 | impl UfmtWrapper { 392 | pub fn new() -> Self { 393 | UfmtWrapper { 394 | cursor: 0, 395 | buffer: [0; N], 396 | } 397 | } 398 | 399 | pub fn as_str(&self) -> &str { 400 | unsafe { from_utf8_unchecked(&self.buffer[..self.cursor]) } 401 | } 402 | pub fn reset(&mut self) { 403 | self.cursor = 0; 404 | } 405 | } 406 | 407 | impl uWrite for UfmtWrapper { 408 | type Error = (); 409 | 410 | fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { 411 | let bytes = s.as_bytes(); 412 | self.buffer[self.cursor..(self.cursor + bytes.len())].copy_from_slice(bytes); 413 | self.cursor += bytes.len(); 414 | Ok(()) 415 | } 416 | } 417 | 418 | // 419 | -------------------------------------------------------------------------------- /cnc-pendant/src/painter.rs: -------------------------------------------------------------------------------- 1 | use crate::{ChangeDetector, UfmtWrapper}; 2 | use bitmap_font::tamzen::FONT_8x15; 3 | use bitmap_font::TextStyle; 4 | use embedded_graphics::mono_font::MonoTextStyle; 5 | use embedded_graphics::pixelcolor::BinaryColor; 6 | use embedded_graphics::prelude::{Point, Size}; 7 | use embedded_graphics::primitives::Rectangle; 8 | use embedded_graphics::text::renderer::TextRenderer; 9 | use embedded_graphics::text::Text; 10 | use embedded_graphics_core::Drawable; 11 | use embedded_vintage_fonts::FONT_6X8; 12 | use ufmt::uwrite; 13 | 14 | pub fn easy_text_at( 15 | msg: &str, 16 | x: i32, 17 | y: i32, 18 | disp: &mut D, 19 | style: S, 20 | ) -> Result 21 | where 22 | D: embedded_graphics_core::prelude::DrawTarget, 23 | S: TextRenderer, 24 | { 25 | Text::new(msg, embedded_graphics::geometry::Point::new(x, y), style).draw( 26 | disp, // &mut DTWrapper { inner: disp } 27 | ) 28 | } 29 | 30 | fn paint_multiline_text( 31 | x: i32, 32 | mut y: i32, 33 | mut msg: &str, 34 | fg: embedded_graphics::pixelcolor::BinaryColor, 35 | bg: BinaryColor, 36 | disp: &mut D, 37 | ) -> Result<(), E> 38 | where 39 | D: embedded_graphics_core::draw_target::DrawTarget< 40 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 41 | Error = E, 42 | >, 43 | { 44 | loop { 45 | let ab = msg.split_once('\n'); 46 | let (submessage, more) = match ab { 47 | Some((a, b)) => (a, Some(b)), 48 | None => (msg, None), 49 | }; 50 | const DISPLAY_WIDTH: i32 = 128; 51 | disp.fill_solid( 52 | &Rectangle::new(Point::new(x, y), Size::new((DISPLAY_WIDTH - x) as u32, 10)), 53 | bg, 54 | )?; 55 | 56 | easy_text_at( 57 | submessage, 58 | x, 59 | y + 1, 60 | disp, 61 | MonoTextStyle::new(&FONT_6X8, fg), 62 | )?; 63 | match more { 64 | None => { 65 | break; 66 | } 67 | Some(more) => { 68 | msg = more; 69 | y += 9; 70 | } 71 | } 72 | } 73 | Ok(()) 74 | } 75 | 76 | // 77 | 78 | pub struct DisplayPainter 79 | where 80 | D: embedded_graphics_core::draw_target::DrawTarget< 81 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 82 | Error = E, 83 | >, 84 | { 85 | pub dirty: bool, 86 | pub disp: D, 87 | old_brightness: ChangeDetector, 88 | old_key_state: ChangeDetector<[bool; 12]>, 89 | } 90 | 91 | impl DisplayPainter 92 | where 93 | D: embedded_graphics_core::draw_target::DrawTarget< 94 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 95 | Error = E, 96 | >, 97 | { 98 | pub fn new(disp: D) -> Self { 99 | DisplayPainter { 100 | dirty: true, 101 | disp, 102 | old_brightness: ChangeDetector::new(0), 103 | old_key_state: ChangeDetector::new([true; 12]), 104 | } 105 | } 106 | 107 | pub fn idle_display(&mut self) -> Result<(), E> { 108 | if !self.dirty { 109 | return Ok(()); 110 | } 111 | 112 | const LABELS: [[&str; 3]; 4] = [ 113 | [".", "Y+", "z+"], 114 | ["X-", ".", "X+"], 115 | [".", "Y-", "z-"], 116 | ["X", "Y", "Z"], 117 | ]; 118 | self.disp 119 | .clear(embedded_graphics_core::pixelcolor::BinaryColor::Off)?; 120 | 121 | easy_text_at( 122 | "Bob's Macro Pad", 123 | 1, 124 | 0, 125 | &mut self.disp, 126 | TextStyle::new( 127 | &FONT_8x15, 128 | embedded_graphics_core::pixelcolor::BinaryColor::On, 129 | ), 130 | )?; 131 | 132 | for (row, labels) in LABELS.iter().enumerate() { 133 | for (col, label) in labels.iter().enumerate() { 134 | let x = (128 + 1) * col / 3 + 21 - label.len() * 3; 135 | let y = 10 * row + 25; 136 | easy_text_at( 137 | *label, 138 | x as i32, 139 | y as i32, 140 | &mut self.disp, 141 | MonoTextStyle::new( 142 | &FONT_6X8, 143 | embedded_graphics_core::pixelcolor::BinaryColor::On, 144 | ), 145 | )?; 146 | } 147 | } 148 | self.dirty = false; 149 | Ok(()) 150 | } 151 | 152 | pub fn update_display( 153 | &mut self, 154 | bright: u8, 155 | key_state: [bool; 12], 156 | active_mission: Option, 157 | debug_msg: &str, 158 | ) -> Result<(), E> { 159 | if self.old_brightness.changed(bright) { 160 | self.paint_brightness()?; 161 | } 162 | 163 | if self.old_key_state.changed(key_state) { 164 | self.paint_key0_state(key_state)?; 165 | } 166 | 167 | if true { 168 | return Ok(()); 169 | } 170 | 171 | self.paint_key_grid(active_mission)?; 172 | 173 | if !debug_msg.is_empty() { 174 | paint_multiline_text( 175 | 0, 176 | 10, 177 | debug_msg, 178 | embedded_graphics::pixelcolor::BinaryColor::On, 179 | BinaryColor::Off, 180 | &mut self.disp, 181 | )?; 182 | } 183 | 184 | Ok(()) 185 | } 186 | 187 | fn paint_key_grid(&mut self, active_mission: Option) -> Result<(), E> { 188 | let diam = 5; 189 | for row in 0..4 { 190 | for col in 0..3 { 191 | let idx = row * 3 + col; 192 | self.disp.fill_solid( 193 | &Rectangle::new( 194 | Point::new(col * diam, row * diam), 195 | Size::new(diam as u32, diam as u32), 196 | ), 197 | if active_mission == Some(idx as u8) { 198 | BinaryColor::On 199 | } else { 200 | BinaryColor::Off 201 | }, 202 | )?; 203 | } 204 | } 205 | Ok(()) 206 | } 207 | 208 | fn paint_key0_state(&mut self, key_state: [bool; 12]) -> Result { 209 | let p1 = Point::new(20, 1); 210 | self.disp 211 | .fill_solid(&Rectangle::new(p1, Size::new(100, 10)), BinaryColor::Off)?; 212 | easy_text_at( 213 | if key_state[0] { "0down" } else { "0up" }, 214 | p1.x + 1, 215 | p1.y + 1, 216 | &mut self.disp, 217 | MonoTextStyle::new( 218 | &FONT_6X8, 219 | embedded_graphics_core::pixelcolor::BinaryColor::On, 220 | ), 221 | ) 222 | } 223 | 224 | fn paint_brightness(&mut self) -> Result { 225 | let p1 = Point::new(20, 40); 226 | self.disp 227 | .fill_solid(&Rectangle::new(p1, Size::new(100, 60)), BinaryColor::On)?; 228 | 229 | let mut fmt_buffer = UfmtWrapper::<80>::new(); 230 | 231 | let bright = self.old_brightness.old; 232 | // fmt_buffer.write_str("bright"); 233 | uwrite!(&mut fmt_buffer, "brightness={}", bright).unwrap(); 234 | 235 | easy_text_at( 236 | fmt_buffer.as_str(), 237 | // "brightness", 238 | p1.x + 1, 239 | p1.y + 1, 240 | &mut self.disp, 241 | MonoTextStyle::new( 242 | &FONT_6X8, 243 | embedded_graphics_core::pixelcolor::BinaryColor::On, 244 | ), 245 | ) 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /display-exp1/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # Choose a default "cargo run" tool: 3 | # - probe-run provides flashing and defmt via a hardware debugger 4 | # - cargo embed offers flashing, rtt, defmt and a gdb server via a hardware debugger 5 | # it is configured via the Embed.toml in the root of this project 6 | # - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode 7 | # runner = "probe-run --chip RP2040" 8 | # runner = "cargo embed" 9 | runner = "elf2uf2-rs -d" 10 | 11 | rustflags = [ 12 | "-C", "linker=flip-link", 13 | "-C", "link-arg=--nmagic", 14 | "-C", "link-arg=-Tlink.x", 15 | "-C", "link-arg=-Tdefmt.x", 16 | 17 | # Code-size optimizations. 18 | # trap unreachable can save a lot of space, but requires nightly compiler. 19 | # uncomment the next line if you wish to enable it 20 | # "-Z", "trap-unreachable=no", 21 | "-C", "inline-threshold=5", 22 | "-C", "no-vectorize-loops", 23 | ] 24 | 25 | [build] 26 | target = "thumbv6m-none-eabi" 27 | 28 | [env] 29 | DEFMT_LOG = "debug" 30 | -------------------------------------------------------------------------------- /display-exp1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adafruit-macropad" 7 | version = "0.3.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "edc9cdc0c832cb024f86584c01bbb7e62fe022c68a0d91f46d74af11e6c78e29" 10 | dependencies = [ 11 | "cortex-m", 12 | "cortex-m-rt", 13 | "rp2040-boot2", 14 | "rp2040-hal", 15 | ] 16 | 17 | [[package]] 18 | name = "adafruit-macropad-macros" 19 | version = "0.1.0" 20 | dependencies = [ 21 | "adafruit-macropad", 22 | "embedded-hal", 23 | "embedded-time", 24 | "sh1106", 25 | "ws2812-pio", 26 | ] 27 | 28 | [[package]] 29 | name = "aho-corasick" 30 | version = "0.7.18" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 33 | dependencies = [ 34 | "memchr", 35 | ] 36 | 37 | [[package]] 38 | name = "arrayvec" 39 | version = "0.7.2" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 42 | 43 | [[package]] 44 | name = "autocfg" 45 | version = "1.1.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 48 | 49 | [[package]] 50 | name = "az" 51 | version = "1.2.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" 54 | 55 | [[package]] 56 | name = "bare-metal" 57 | version = "0.2.5" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 60 | dependencies = [ 61 | "rustc_version", 62 | ] 63 | 64 | [[package]] 65 | name = "bare-metal" 66 | version = "1.0.0" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 69 | 70 | [[package]] 71 | name = "bit_field" 72 | version = "0.10.1" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" 75 | 76 | [[package]] 77 | name = "bitfield" 78 | version = "0.13.2" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 81 | 82 | [[package]] 83 | name = "bitflags" 84 | version = "1.3.2" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 87 | 88 | [[package]] 89 | name = "bytemuck" 90 | version = "1.10.0" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a" 93 | 94 | [[package]] 95 | name = "byteorder" 96 | version = "1.3.4" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 99 | 100 | [[package]] 101 | name = "cfg-if" 102 | version = "1.0.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 105 | 106 | [[package]] 107 | name = "cortex-m" 108 | version = "0.7.5" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" 111 | dependencies = [ 112 | "bare-metal 0.2.5", 113 | "bitfield", 114 | "embedded-hal", 115 | "volatile-register", 116 | ] 117 | 118 | [[package]] 119 | name = "cortex-m-rt" 120 | version = "0.7.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7" 123 | dependencies = [ 124 | "cortex-m-rt-macros", 125 | ] 126 | 127 | [[package]] 128 | name = "cortex-m-rt-macros" 129 | version = "0.7.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 132 | dependencies = [ 133 | "proc-macro2", 134 | "quote", 135 | "syn", 136 | ] 137 | 138 | [[package]] 139 | name = "crc-any" 140 | version = "2.4.3" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "774646b687f63643eb0f4bf13dc263cb581c8c9e57973b6ddf78bda3994d88df" 143 | dependencies = [ 144 | "debug-helper", 145 | ] 146 | 147 | [[package]] 148 | name = "critical-section" 149 | version = "0.2.7" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" 152 | dependencies = [ 153 | "bare-metal 1.0.0", 154 | "cfg-if", 155 | "cortex-m", 156 | "riscv", 157 | ] 158 | 159 | [[package]] 160 | name = "debug-helper" 161 | version = "0.3.13" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" 164 | 165 | [[package]] 166 | name = "defmt" 167 | version = "0.3.2" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "d3a0ae7494d9bff013d7b89471f4c424356a71e9752e0c78abe7e6c608a16bb3" 170 | dependencies = [ 171 | "bitflags", 172 | "defmt-macros", 173 | ] 174 | 175 | [[package]] 176 | name = "defmt-macros" 177 | version = "0.3.2" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "6d944432e281084511691b36e5e9c794c19c33675822c9019e3b64f5b89e10da" 180 | dependencies = [ 181 | "defmt-parser", 182 | "proc-macro-error", 183 | "proc-macro2", 184 | "quote", 185 | "syn", 186 | ] 187 | 188 | [[package]] 189 | name = "defmt-parser" 190 | version = "0.3.1" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "0db23d29972d99baa3de2ee2ae3f104c10564a6d05a346eb3f4c4f2c0525a06e" 193 | 194 | [[package]] 195 | name = "defmt-rtt" 196 | version = "0.3.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "1d2cbbbd58847d508d97629b32cd9730a2d28532f71e219714614406029f18b1" 199 | dependencies = [ 200 | "critical-section", 201 | "defmt", 202 | ] 203 | 204 | [[package]] 205 | name = "display-exp-1" 206 | version = "0.1.0" 207 | dependencies = [ 208 | "adafruit-macropad", 209 | "adafruit-macropad-macros", 210 | "cortex-m", 211 | "cortex-m-rt", 212 | "defmt", 213 | "defmt-rtt", 214 | "either", 215 | "embedded-graphics", 216 | "embedded-graphics-core", 217 | "embedded-hal", 218 | "embedded-time", 219 | "macropad-helpers", 220 | "panic-probe", 221 | "rotary-encoder-hal", 222 | "rp-pico", 223 | "sh1106", 224 | "smart-leds-trait", 225 | "ufmt", 226 | "ws2812-pio", 227 | ] 228 | 229 | [[package]] 230 | name = "either" 231 | version = "1.7.0" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" 234 | 235 | [[package]] 236 | name = "embedded-graphics" 237 | version = "0.7.1" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b" 240 | dependencies = [ 241 | "az", 242 | "byteorder", 243 | "embedded-graphics-core", 244 | "float-cmp", 245 | "micromath", 246 | ] 247 | 248 | [[package]] 249 | name = "embedded-graphics-core" 250 | version = "0.3.3" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa" 253 | dependencies = [ 254 | "az", 255 | "byteorder", 256 | ] 257 | 258 | [[package]] 259 | name = "embedded-hal" 260 | version = "0.2.7" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 263 | dependencies = [ 264 | "nb 0.1.3", 265 | "void", 266 | ] 267 | 268 | [[package]] 269 | name = "embedded-time" 270 | version = "0.12.1" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" 273 | dependencies = [ 274 | "num", 275 | ] 276 | 277 | [[package]] 278 | name = "encode_unicode" 279 | version = "0.3.6" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 282 | 283 | [[package]] 284 | name = "float-cmp" 285 | version = "0.8.0" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" 288 | dependencies = [ 289 | "num-traits", 290 | ] 291 | 292 | [[package]] 293 | name = "itertools" 294 | version = "0.10.3" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" 297 | dependencies = [ 298 | "either", 299 | ] 300 | 301 | [[package]] 302 | name = "lazy_static" 303 | version = "1.4.0" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 306 | 307 | [[package]] 308 | name = "macropad-helpers" 309 | version = "0.1.0" 310 | dependencies = [ 311 | "embedded-graphics", 312 | "embedded-graphics-core", 313 | ] 314 | 315 | [[package]] 316 | name = "memchr" 317 | version = "2.5.0" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 320 | 321 | [[package]] 322 | name = "micromath" 323 | version = "1.1.1" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94" 326 | 327 | [[package]] 328 | name = "nb" 329 | version = "0.1.3" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 332 | dependencies = [ 333 | "nb 1.0.0", 334 | ] 335 | 336 | [[package]] 337 | name = "nb" 338 | version = "1.0.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 341 | 342 | [[package]] 343 | name = "num" 344 | version = "0.3.1" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" 347 | dependencies = [ 348 | "num-complex", 349 | "num-integer", 350 | "num-iter", 351 | "num-rational", 352 | "num-traits", 353 | ] 354 | 355 | [[package]] 356 | name = "num-complex" 357 | version = "0.3.1" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 360 | dependencies = [ 361 | "num-traits", 362 | ] 363 | 364 | [[package]] 365 | name = "num-integer" 366 | version = "0.1.45" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 369 | dependencies = [ 370 | "autocfg", 371 | "num-traits", 372 | ] 373 | 374 | [[package]] 375 | name = "num-iter" 376 | version = "0.1.43" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 379 | dependencies = [ 380 | "autocfg", 381 | "num-integer", 382 | "num-traits", 383 | ] 384 | 385 | [[package]] 386 | name = "num-rational" 387 | version = "0.3.2" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 390 | dependencies = [ 391 | "autocfg", 392 | "num-integer", 393 | "num-traits", 394 | ] 395 | 396 | [[package]] 397 | name = "num-traits" 398 | version = "0.2.15" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 401 | dependencies = [ 402 | "autocfg", 403 | ] 404 | 405 | [[package]] 406 | name = "num_enum" 407 | version = "0.5.7" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" 410 | dependencies = [ 411 | "num_enum_derive", 412 | ] 413 | 414 | [[package]] 415 | name = "num_enum_derive" 416 | version = "0.5.7" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" 419 | dependencies = [ 420 | "proc-macro2", 421 | "quote", 422 | "syn", 423 | ] 424 | 425 | [[package]] 426 | name = "panic-probe" 427 | version = "0.3.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "3ab1f00eac22bd18f8e5cae9555f2820b3a0c166b5b556ee3e203746ea6dcf3a" 430 | dependencies = [ 431 | "cortex-m", 432 | "defmt", 433 | ] 434 | 435 | [[package]] 436 | name = "paste" 437 | version = "1.0.7" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" 440 | 441 | [[package]] 442 | name = "pio" 443 | version = "0.2.0" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "0fd642eada42517e6589cd7f5e830630324aec628fb4aa719000f8801e40c0a2" 446 | dependencies = [ 447 | "arrayvec", 448 | "num_enum", 449 | "paste", 450 | ] 451 | 452 | [[package]] 453 | name = "proc-macro-error" 454 | version = "1.0.4" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 457 | dependencies = [ 458 | "proc-macro-error-attr", 459 | "proc-macro2", 460 | "quote", 461 | "syn", 462 | "version_check", 463 | ] 464 | 465 | [[package]] 466 | name = "proc-macro-error-attr" 467 | version = "1.0.4" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 470 | dependencies = [ 471 | "proc-macro2", 472 | "quote", 473 | "version_check", 474 | ] 475 | 476 | [[package]] 477 | name = "proc-macro-hack" 478 | version = "0.5.19" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 481 | 482 | [[package]] 483 | name = "proc-macro2" 484 | version = "1.0.40" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" 487 | dependencies = [ 488 | "unicode-ident", 489 | ] 490 | 491 | [[package]] 492 | name = "quote" 493 | version = "1.0.20" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" 496 | dependencies = [ 497 | "proc-macro2", 498 | ] 499 | 500 | [[package]] 501 | name = "rand_core" 502 | version = "0.6.3" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 505 | 506 | [[package]] 507 | name = "regex" 508 | version = "1.6.0" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 511 | dependencies = [ 512 | "aho-corasick", 513 | "memchr", 514 | "regex-syntax", 515 | ] 516 | 517 | [[package]] 518 | name = "regex-syntax" 519 | version = "0.6.27" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 522 | 523 | [[package]] 524 | name = "rgb" 525 | version = "0.8.33" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "c3b221de559e4a29df3b957eec92bc0de6bc8eaf6ca9cfed43e5e1d67ff65a34" 528 | dependencies = [ 529 | "bytemuck", 530 | ] 531 | 532 | [[package]] 533 | name = "riscv" 534 | version = "0.7.0" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" 537 | dependencies = [ 538 | "bare-metal 1.0.0", 539 | "bit_field", 540 | "riscv-target", 541 | ] 542 | 543 | [[package]] 544 | name = "riscv-target" 545 | version = "0.1.2" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" 548 | dependencies = [ 549 | "lazy_static", 550 | "regex", 551 | ] 552 | 553 | [[package]] 554 | name = "rotary-encoder-hal" 555 | version = "0.5.0" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "ca5f10fcd6842ed448d9f5913815a343cdcbe10e53da6cac948251d529b75487" 558 | dependencies = [ 559 | "either", 560 | "embedded-hal", 561 | ] 562 | 563 | [[package]] 564 | name = "rp-pico" 565 | version = "0.4.1" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "6b83448890aab5f6e35aa64d6a2441d69b768e7a22aaf943a84b7459340028ec" 568 | dependencies = [ 569 | "cortex-m", 570 | "cortex-m-rt", 571 | "embedded-time", 572 | "rp2040-boot2", 573 | "rp2040-hal", 574 | "usb-device", 575 | "usbd-hid", 576 | "usbd-serial", 577 | ] 578 | 579 | [[package]] 580 | name = "rp2040-boot2" 581 | version = "0.2.0" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "8b480fe63133f0d639f82ce5a027fee7cac7ac92f67ef1896ee036a6f9737128" 584 | dependencies = [ 585 | "crc-any", 586 | ] 587 | 588 | [[package]] 589 | name = "rp2040-hal" 590 | version = "0.5.0" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "0de1bc8bf092f5da649a417ad9f18c9705b6226afe3521a469f15d1d2bcb7f66" 593 | dependencies = [ 594 | "cortex-m", 595 | "cortex-m-rt", 596 | "critical-section", 597 | "embedded-hal", 598 | "embedded-time", 599 | "itertools", 600 | "nb 1.0.0", 601 | "paste", 602 | "pio", 603 | "rand_core", 604 | "rp2040-hal-macros", 605 | "rp2040-pac", 606 | "usb-device", 607 | "vcell", 608 | "void", 609 | ] 610 | 611 | [[package]] 612 | name = "rp2040-hal-macros" 613 | version = "0.1.0" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e" 616 | dependencies = [ 617 | "cortex-m-rt", 618 | "proc-macro2", 619 | "quote", 620 | "syn", 621 | ] 622 | 623 | [[package]] 624 | name = "rp2040-pac" 625 | version = "0.3.0" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "13a6106d5db01c7171a39c1f7696780912db9b42fe7ac722db60069c8904ea7c" 628 | dependencies = [ 629 | "cortex-m", 630 | "cortex-m-rt", 631 | "vcell", 632 | ] 633 | 634 | [[package]] 635 | name = "rustc_version" 636 | version = "0.2.3" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 639 | dependencies = [ 640 | "semver", 641 | ] 642 | 643 | [[package]] 644 | name = "semver" 645 | version = "0.9.0" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 648 | dependencies = [ 649 | "semver-parser", 650 | ] 651 | 652 | [[package]] 653 | name = "semver-parser" 654 | version = "0.7.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 657 | 658 | [[package]] 659 | name = "serde" 660 | version = "1.0.140" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" 663 | 664 | [[package]] 665 | name = "sh1106" 666 | version = "0.4.0" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "4b4022685baa7cc82b2fb97ced2b53fd753a21d98f45b0fd0b55fc717de9075a" 669 | dependencies = [ 670 | "embedded-graphics-core", 671 | "embedded-hal", 672 | ] 673 | 674 | [[package]] 675 | name = "smart-leds-trait" 676 | version = "0.2.1" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3" 679 | dependencies = [ 680 | "rgb", 681 | ] 682 | 683 | [[package]] 684 | name = "ssmarshal" 685 | version = "1.0.0" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" 688 | dependencies = [ 689 | "encode_unicode", 690 | "serde", 691 | ] 692 | 693 | [[package]] 694 | name = "syn" 695 | version = "1.0.98" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" 698 | dependencies = [ 699 | "proc-macro2", 700 | "quote", 701 | "unicode-ident", 702 | ] 703 | 704 | [[package]] 705 | name = "ufmt" 706 | version = "0.1.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "2e7ecea7ef79d3f8f878eee614afdf5256475c63ad76139d4da6125617c784a0" 709 | dependencies = [ 710 | "proc-macro-hack", 711 | "ufmt-macros", 712 | "ufmt-write", 713 | ] 714 | 715 | [[package]] 716 | name = "ufmt-macros" 717 | version = "0.1.1" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "ed813e34a2bfa9dc58ee2ed8c8314d25e6d70c911486d64b8085cb695cfac069" 720 | dependencies = [ 721 | "proc-macro-hack", 722 | "proc-macro2", 723 | "quote", 724 | "syn", 725 | ] 726 | 727 | [[package]] 728 | name = "ufmt-write" 729 | version = "0.1.0" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" 732 | 733 | [[package]] 734 | name = "unicode-ident" 735 | version = "1.0.2" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" 738 | 739 | [[package]] 740 | name = "usb-device" 741 | version = "0.2.8" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245" 744 | 745 | [[package]] 746 | name = "usbd-hid" 747 | version = "0.5.2" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "183b7e65bbd75512aedf250deda89394c74ae3118b79fe41f159e8503e1d5d7f" 750 | dependencies = [ 751 | "serde", 752 | "ssmarshal", 753 | "usb-device", 754 | "usbd-hid-macros", 755 | ] 756 | 757 | [[package]] 758 | name = "usbd-hid-descriptors" 759 | version = "0.1.1" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "9e00430c0b39caf3957aba6c2b2824f8e70e1ac0278941418bf1fe35f9566d64" 762 | dependencies = [ 763 | "bitfield", 764 | ] 765 | 766 | [[package]] 767 | name = "usbd-hid-macros" 768 | version = "0.5.2" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "78bd005b3aa54e62905d99df49a75d11888bb958eb780adb5e8f2029733077df" 771 | dependencies = [ 772 | "byteorder", 773 | "proc-macro2", 774 | "quote", 775 | "serde", 776 | "syn", 777 | "usbd-hid-descriptors", 778 | ] 779 | 780 | [[package]] 781 | name = "usbd-serial" 782 | version = "0.1.1" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe" 785 | dependencies = [ 786 | "embedded-hal", 787 | "nb 0.1.3", 788 | "usb-device", 789 | ] 790 | 791 | [[package]] 792 | name = "vcell" 793 | version = "0.1.3" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 796 | 797 | [[package]] 798 | name = "version_check" 799 | version = "0.9.4" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 802 | 803 | [[package]] 804 | name = "void" 805 | version = "1.0.2" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 808 | 809 | [[package]] 810 | name = "volatile-register" 811 | version = "0.2.1" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" 814 | dependencies = [ 815 | "vcell", 816 | ] 817 | 818 | [[package]] 819 | name = "ws2812-pio" 820 | version = "0.3.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "59c8b2e9830ab583b86349261a5980a0a33151f812abbb21019444822bb61d27" 823 | dependencies = [ 824 | "cortex-m", 825 | "embedded-hal", 826 | "embedded-time", 827 | "nb 1.0.0", 828 | "pio", 829 | "rp2040-hal", 830 | "smart-leds-trait", 831 | ] 832 | -------------------------------------------------------------------------------- /display-exp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "display-exp-1" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | cortex-m = "0.7" 8 | cortex-m-rt = "0.7" 9 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 10 | embedded-time = "0.12" 11 | 12 | defmt = "0.3" 13 | defmt-rtt = "0.3" 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } 15 | 16 | 17 | adafruit-macropad = "*" 18 | ws2812-pio = "0.3.0" 19 | smart-leds-trait = "*" 20 | embedded-graphics-core = "*" 21 | embedded-graphics = "*" 22 | sh1106="*" 23 | 24 | rotary-encoder-hal = "*" 25 | ufmt="*" 26 | 27 | adafruit-macropad-macros = { path="../adafruit-macropad-macros"} 28 | macropad-helpers = { path="../macropad-helpers"} 29 | 30 | # We're using a Pico by default on this template 31 | rp-pico = "0.4" 32 | # but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead 33 | # sparkfun-pro-micro-rp2040 = "0.3" 34 | 35 | # If you're not going to use a Board Support Package you'll need these: 36 | # rp2040-hal = { version="0.5", features=["rt"] } 37 | # rp2040-boot2 = "0.2" 38 | 39 | 40 | #[dependencies.sh1107] 41 | #git="https://github.com/aaron-hardin/sh1107.git" 42 | 43 | [dependencies.either] 44 | version = "*" 45 | default-features = false 46 | 47 | 48 | # cargo build/run 49 | [profile.dev] 50 | codegen-units = 1 51 | debug = 2 52 | debug-assertions = true 53 | incremental = false 54 | opt-level = 3 55 | overflow-checks = true 56 | 57 | # cargo build/run --release 58 | [profile.release] 59 | codegen-units = 1 60 | debug = 2 61 | debug-assertions = false 62 | incremental = false 63 | lto = 'fat' 64 | opt-level = 3 65 | overflow-checks = false 66 | 67 | # do not optimize proc-macro crates = faster builds from scratch 68 | [profile.dev.build-override] 69 | codegen-units = 8 70 | debug = false 71 | debug-assertions = false 72 | opt-level = 0 73 | overflow-checks = false 74 | 75 | [profile.release.build-override] 76 | codegen-units = 8 77 | debug = false 78 | debug-assertions = false 79 | opt-level = 0 80 | overflow-checks = false 81 | 82 | # cargo test 83 | [profile.test] 84 | codegen-units = 1 85 | debug = 2 86 | debug-assertions = true 87 | incremental = false 88 | opt-level = 3 89 | overflow-checks = true 90 | 91 | # cargo test --release 92 | [profile.bench] 93 | codegen-units = 1 94 | debug = 2 95 | debug-assertions = false 96 | incremental = false 97 | lto = 'fat' 98 | opt-level = 3 99 | -------------------------------------------------------------------------------- /display-exp1/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | protocol = "Swd" 3 | speed = 20000 4 | # If you only have one probe cargo embed will pick automatically 5 | # Otherwise: add your probe's VID/PID/serial to filter 6 | 7 | ## rust-dap 8 | # usb_vid = "6666" 9 | # usb_pid = "4444" 10 | # serial = "test" 11 | 12 | 13 | [default.flashing] 14 | enabled = true 15 | 16 | [default.reset] 17 | enabled = true 18 | halt_afterwards = false 19 | 20 | [default.general] 21 | chip = "RP2040" 22 | log_level = "WARN" 23 | # RP2040 does not support connect_under_reset 24 | connect_under_reset = false 25 | 26 | [default.rtt] 27 | enabled = true 28 | up_mode = "NoBlockSkip" 29 | channels = [ 30 | { up = 0, down = 0, name = "name", up_mode = "NoBlockSkip", format = "Defmt" }, 31 | ] 32 | timeout = 3000 33 | show_timestamps = true 34 | log_enabled = false 35 | log_path = "./logs" 36 | 37 | [default.gdb] 38 | enabled = false 39 | gdb_connection_string = "127.0.0.1:2345" 40 | -------------------------------------------------------------------------------- /display-exp1/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /display-exp1/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; -------------------------------------------------------------------------------- /display-exp1/src/graphics_exp.rs: -------------------------------------------------------------------------------- 1 | use embedded_graphics::drawable::Drawable; 2 | use embedded_graphics::fonts::{Font6x8, Text}; 3 | use embedded_graphics::primitives::Line; 4 | use embedded_graphics::style::{PrimitiveStyle, Styled, TextStyle}; 5 | use macropad_helpers::DTWrapper; 6 | use sh1106::interface::DisplayInterface; 7 | use sh1106::mode::GraphicsMode; 8 | 9 | pub fn try_to_draw(disp: &mut GraphicsMode) { 10 | use embedded_graphics::pixelcolor::BinaryColor; 11 | use embedded_graphics::prelude::Point; 12 | let wrapper = &mut DTWrapper { inner: disp }; 13 | Text::new("hail Bob!", Point::zero()) 14 | .into_styled(TextStyle::new(Font6x8, BinaryColor::On)) 15 | .draw(wrapper) 16 | .unwrap(); 17 | 18 | Text::new("or die", Point::new(5, 10)) 19 | .into_styled(TextStyle::new(Font6x8, BinaryColor::On)) 20 | .draw(wrapper) 21 | .unwrap(); 22 | 23 | Styled::new( 24 | Line::new(Point::new(5, 35), Point::new(30, 40)), 25 | PrimitiveStyle::with_stroke(BinaryColor::On, 2), 26 | ) 27 | .draw(wrapper) 28 | .unwrap(); 29 | 30 | Styled::new( 31 | Line::new(Point::new(5, 40), Point::new(30, 50)), 32 | PrimitiveStyle::with_stroke(BinaryColor::On, 2), 33 | ) 34 | .draw(wrapper) 35 | .unwrap(); 36 | 37 | let _ = disp.flush(); 38 | } 39 | -------------------------------------------------------------------------------- /display-exp1/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Blinks the LED on a Pico board 2 | //! 3 | //! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. 4 | #![no_std] 5 | #![no_main] 6 | 7 | use core::str::from_utf8_unchecked; 8 | // Provide an alias for our BSP so we can switch targets quickly. 9 | // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. 10 | use rp_pico as bsp; 11 | // use sparkfun_pro_micro_rp2040 as bsp; 12 | 13 | use adafruit_macropad::hal::gpio::{Input, PullUp}; 14 | use adafruit_macropad::hal::pio::PIOExt; 15 | use adafruit_macropad::hal::Timer; 16 | use adafruit_macropad_macros::{macropad_clocks, macropad_neopixels, macropad_oled, macropad_pins}; 17 | use bsp::entry; 18 | use bsp::hal::{clocks::Clock, pac, watchdog::Watchdog}; 19 | use defmt::*; 20 | use defmt_rtt as _; 21 | use embedded_graphics::fonts::{Font6x8, Text}; 22 | use embedded_graphics::style::TextStyle; 23 | use embedded_graphics_core::draw_target::DrawTarget as DT_; 24 | use embedded_graphics_core::geometry::{Point, Size}; 25 | use embedded_graphics_core::pixelcolor::BinaryColor; 26 | use embedded_graphics_core::primitives::Rectangle; 27 | use embedded_hal::digital::v2::OutputPin; 28 | use embedded_time::fixed_point::FixedPoint; 29 | use macropad_helpers::DTWrapper; 30 | use panic_probe as _; 31 | use rotary_encoder_hal::{Direction, Rotary}; 32 | use smart_leds_trait::SmartLedsWrite; 33 | use ufmt::{uWrite, uwrite}; 34 | 35 | mod graphics_exp; 36 | 37 | #[entry] 38 | fn main() -> ! { 39 | info!("Program start"); 40 | let mut pac = pac::Peripherals::take().unwrap(); 41 | let core = pac::CorePeripherals::take().unwrap(); 42 | 43 | let mut watchdog = Watchdog::new(pac.WATCHDOG); 44 | 45 | let clocks = macropad_clocks!(pac, watchdog); 46 | 47 | let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); 48 | 49 | let pins = macropad_pins!(pac); 50 | 51 | let timer = Timer::new(pac.TIMER, &mut pac.RESETS); 52 | 53 | // 54 | 55 | let mut disp = macropad_oled!(pins, clocks, delay, pac); 56 | 57 | let mut led_pin = pins.led.into_push_pull_output(); 58 | 59 | let mut neopixels = macropad_neopixels!(pins, clocks, timer, pac); 60 | 61 | // 62 | 63 | let mut rotary = Rotary::new( 64 | pins.encoder_rota.into_mode::>(), 65 | pins.encoder_rotb.into_mode::>(), 66 | ); 67 | 68 | // 69 | // 70 | 71 | disp.clear(); 72 | 73 | let _ = disp.draw_iter((0..10).flat_map(move |y| { 74 | (70..90).map(move |x| { 75 | embedded_graphics_core::Pixel( 76 | embedded_graphics_core::prelude::Point::new(x, y), 77 | if 0 == 1 & (x + y) { 78 | embedded_graphics_core::pixelcolor::BinaryColor::On 79 | } else { 80 | embedded_graphics_core::pixelcolor::BinaryColor::Off 81 | }, 82 | ) 83 | }) 84 | })); 85 | 86 | let _ = disp.flush(); 87 | 88 | let _ = graphics_exp::try_to_draw(&mut disp); 89 | 90 | let mut bright = 200; 91 | let mut old_brightness = ChangeDetector::new(0); 92 | 93 | let mut ticks: u16 = 0; 94 | loop { 95 | let black = [(0, 0, 0); 3]; 96 | let rgb = [(bright, 0, 0), (0, bright, 0), (0, 0, bright)]; 97 | let cmy = [ 98 | (0, bright, bright), 99 | (bright, 0, bright), 100 | (bright, bright, 0), 101 | ]; 102 | 103 | // const DECODE: [i8; 4] = [0, 1, 3, 2]; 104 | // let phase = DECODE[rotary.state as usize]; 105 | let phase = bright as i8; 106 | 107 | if ticks & 0x200 == 0 { 108 | led_pin.set_high().unwrap(); 109 | let _ = neopixels.write(wacky_lights(&black, &cmy, phase)); 110 | } else { 111 | led_pin.set_low().unwrap(); 112 | let _ = neopixels.write(wacky_lights(&black, &rgb, phase)); 113 | } 114 | 115 | match rotary.update() { 116 | Ok(Direction::Clockwise) => { 117 | bright = (bright as u16 + 1).min(255) as u8; 118 | } 119 | Ok(Direction::CounterClockwise) => { 120 | bright = (bright as i16 - 1).max(0) as u8; 121 | } 122 | Ok(Direction::None) => {} 123 | Err(_) => { 124 | // don't care 125 | } 126 | } 127 | 128 | if old_brightness.changed(bright) { 129 | use embedded_graphics::drawable::Drawable; 130 | let p1 = Point::new(20, 40); 131 | let _ = disp.fill_solid( 132 | &Rectangle::new(p1.clone(), Size::new(100, 60)), 133 | BinaryColor::On, 134 | ); 135 | 136 | let mut fmt_buffer = UfmtWrapper::<80>::new(); 137 | 138 | // fmt_buffer.write_str("bright"); 139 | uwrite!(&mut fmt_buffer, "brightness={}", bright).unwrap(); 140 | 141 | let _ = Text::new( 142 | fmt_buffer.as_str(), 143 | // "brightness", 144 | embedded_graphics::geometry::Point::new(p1.x + 1, p1.y + 1), 145 | ) 146 | .into_styled(TextStyle::new( 147 | Font6x8, 148 | embedded_graphics::pixelcolor::BinaryColor::Off, 149 | )) 150 | .draw(&mut DTWrapper { inner: &mut disp }); 151 | let _ = disp.flush(); 152 | } 153 | 154 | ticks = ticks.wrapping_add(1); 155 | 156 | delay.delay_ms(1); 157 | } 158 | } 159 | 160 | struct ChangeDetector { 161 | old: T, 162 | } 163 | 164 | impl ChangeDetector { 165 | pub fn new(first: T) -> Self { 166 | ChangeDetector { old: first } 167 | } 168 | 169 | pub fn changed(&mut self, new_val: T) -> bool { 170 | if new_val == self.old { 171 | false 172 | } else { 173 | self.old = new_val; 174 | true 175 | } 176 | } 177 | } 178 | 179 | struct UfmtWrapper { 180 | cursor: usize, 181 | buffer: [u8; N], 182 | } 183 | 184 | impl UfmtWrapper { 185 | pub fn new() -> Self { 186 | UfmtWrapper { 187 | cursor: 0, 188 | buffer: [0; N], 189 | } 190 | } 191 | 192 | pub fn as_str<'a>(&'a self) -> &'a str { 193 | unsafe { from_utf8_unchecked(&self.buffer[..self.cursor]) } 194 | } 195 | } 196 | 197 | impl uWrite for UfmtWrapper { 198 | type Error = (); 199 | 200 | fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { 201 | let bytes = s.as_bytes(); 202 | self.buffer[self.cursor..(self.cursor + bytes.len())].copy_from_slice(bytes); 203 | self.cursor += bytes.len(); 204 | Ok(()) 205 | } 206 | } 207 | 208 | fn wacky_lights<'a>( 209 | black: &'a [(u8, u8, u8); 3], 210 | rgb: &'a [(u8, u8, u8); 3], 211 | phase: i8, 212 | ) -> impl Iterator + 'a { 213 | (0..4) 214 | .flat_map(move |row| { 215 | if (row as i16 - phase as i16) % 4 == 0 { 216 | rgb.iter() 217 | } else { 218 | black.iter() 219 | } 220 | }) 221 | .copied() 222 | } 223 | -------------------------------------------------------------------------------- /gaming-pad/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # Choose a default "cargo run" tool: 3 | # - probe-run provides flashing and defmt via a hardware debugger 4 | # - cargo embed offers flashing, rtt, defmt and a gdb server via a hardware debugger 5 | # it is configured via the Embed.toml in the root of this project 6 | # - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode 7 | # runner = "probe-run --chip RP2040" 8 | # runner = "cargo embed" 9 | runner = "elf2uf2-rs -d" 10 | 11 | rustflags = [ 12 | "-C", "linker=flip-link", 13 | "-C", "link-arg=--nmagic", 14 | "-C", "link-arg=-Tlink.x", 15 | "-C", "link-arg=-Tdefmt.x", 16 | 17 | # Code-size optimizations. 18 | # trap unreachable can save a lot of space, but requires nightly compiler. 19 | # uncomment the next line if you wish to enable it 20 | # "-Z", "trap-unreachable=no", 21 | "-C", "inline-threshold=5", 22 | "-C", "no-vectorize-loops", 23 | ] 24 | 25 | [build] 26 | target = "thumbv6m-none-eabi" 27 | 28 | [env] 29 | DEFMT_LOG = "debug" 30 | -------------------------------------------------------------------------------- /gaming-pad/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adafruit-macropad" 7 | version = "0.3.1" 8 | dependencies = [ 9 | "cortex-m", 10 | "cortex-m-rt", 11 | "embedded-graphics", 12 | "embedded-hal", 13 | "embedded-time", 14 | "rotary-encoder-hal", 15 | "rp2040-boot2", 16 | "rp2040-hal", 17 | "sh1106", 18 | "ws2812-pio", 19 | ] 20 | 21 | [[package]] 22 | name = "arrayvec" 23 | version = "0.7.4" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" 26 | 27 | [[package]] 28 | name = "autocfg" 29 | version = "1.1.0" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 32 | 33 | [[package]] 34 | name = "az" 35 | version = "1.2.1" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" 38 | 39 | [[package]] 40 | name = "bare-metal" 41 | version = "0.2.5" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 44 | dependencies = [ 45 | "rustc_version", 46 | ] 47 | 48 | [[package]] 49 | name = "bare-metal" 50 | version = "1.0.0" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 53 | 54 | [[package]] 55 | name = "bitfield" 56 | version = "0.13.2" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 59 | 60 | [[package]] 61 | name = "bitflags" 62 | version = "1.3.2" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 65 | 66 | [[package]] 67 | name = "bitmap-font" 68 | version = "0.2.2" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "75b536cf99182451e737798afe085702c72051d2499ffcdc9a77e4e7e36359b0" 71 | dependencies = [ 72 | "embedded-graphics", 73 | ] 74 | 75 | [[package]] 76 | name = "bytemuck" 77 | version = "1.14.3" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" 80 | 81 | [[package]] 82 | name = "byteorder" 83 | version = "1.3.4" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 86 | 87 | [[package]] 88 | name = "cortex-m" 89 | version = "0.7.7" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" 92 | dependencies = [ 93 | "bare-metal 0.2.5", 94 | "bitfield", 95 | "embedded-hal", 96 | "volatile-register", 97 | ] 98 | 99 | [[package]] 100 | name = "cortex-m-rt" 101 | version = "0.7.3" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1" 104 | dependencies = [ 105 | "cortex-m-rt-macros", 106 | ] 107 | 108 | [[package]] 109 | name = "cortex-m-rt-macros" 110 | version = "0.7.0" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 113 | dependencies = [ 114 | "proc-macro2", 115 | "quote", 116 | "syn 1.0.109", 117 | ] 118 | 119 | [[package]] 120 | name = "crc-any" 121 | version = "2.4.4" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "c01a5e1f881f6fb6099a7bdf949e946719fd4f1fefa56264890574febf0eb6d0" 124 | dependencies = [ 125 | "debug-helper", 126 | ] 127 | 128 | [[package]] 129 | name = "critical-section" 130 | version = "0.2.8" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "c1706d332edc22aef4d9f23a6bb1c92360a403013c291af51247a737472dcae6" 133 | dependencies = [ 134 | "bare-metal 1.0.0", 135 | "critical-section 1.1.2", 136 | ] 137 | 138 | [[package]] 139 | name = "critical-section" 140 | version = "1.1.2" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" 143 | 144 | [[package]] 145 | name = "debug-helper" 146 | version = "0.3.13" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" 149 | 150 | [[package]] 151 | name = "defmt" 152 | version = "0.3.6" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "3939552907426de152b3c2c6f51ed53f98f448babd26f28694c95f5906194595" 155 | dependencies = [ 156 | "bitflags", 157 | "defmt-macros", 158 | ] 159 | 160 | [[package]] 161 | name = "defmt-macros" 162 | version = "0.3.7" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "18bdc7a7b92ac413e19e95240e75d3a73a8d8e78aa24a594c22cbb4d44b4bbda" 165 | dependencies = [ 166 | "defmt-parser", 167 | "proc-macro-error", 168 | "proc-macro2", 169 | "quote", 170 | "syn 2.0.48", 171 | ] 172 | 173 | [[package]] 174 | name = "defmt-parser" 175 | version = "0.3.4" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" 178 | dependencies = [ 179 | "thiserror", 180 | ] 181 | 182 | [[package]] 183 | name = "defmt-rtt" 184 | version = "0.3.2" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "1d2cbbbd58847d508d97629b32cd9730a2d28532f71e219714614406029f18b1" 187 | dependencies = [ 188 | "critical-section 0.2.8", 189 | "defmt", 190 | ] 191 | 192 | [[package]] 193 | name = "either" 194 | version = "1.10.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" 197 | 198 | [[package]] 199 | name = "embedded-graphics" 200 | version = "0.7.1" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b" 203 | dependencies = [ 204 | "az", 205 | "byteorder", 206 | "embedded-graphics-core", 207 | "float-cmp", 208 | "micromath", 209 | ] 210 | 211 | [[package]] 212 | name = "embedded-graphics-core" 213 | version = "0.3.3" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa" 216 | dependencies = [ 217 | "az", 218 | "byteorder", 219 | ] 220 | 221 | [[package]] 222 | name = "embedded-hal" 223 | version = "0.2.7" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 226 | dependencies = [ 227 | "nb 0.1.3", 228 | "void", 229 | ] 230 | 231 | [[package]] 232 | name = "embedded-time" 233 | version = "0.12.1" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" 236 | dependencies = [ 237 | "num", 238 | ] 239 | 240 | [[package]] 241 | name = "embedded-vintage-fonts" 242 | version = "0.1.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "d08cb21f1106211a8aa7cdf8b2e5838d9f2efa904138afefde867cd52f08ea01" 245 | dependencies = [ 246 | "embedded-graphics", 247 | ] 248 | 249 | [[package]] 250 | name = "encode_unicode" 251 | version = "0.3.6" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 254 | 255 | [[package]] 256 | name = "float-cmp" 257 | version = "0.8.0" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" 260 | dependencies = [ 261 | "num-traits", 262 | ] 263 | 264 | [[package]] 265 | name = "gaming-pad" 266 | version = "0.1.0" 267 | dependencies = [ 268 | "adafruit-macropad", 269 | "bitmap-font", 270 | "cortex-m", 271 | "cortex-m-rt", 272 | "defmt", 273 | "defmt-rtt", 274 | "either", 275 | "embedded-graphics", 276 | "embedded-graphics-core", 277 | "embedded-hal", 278 | "embedded-time", 279 | "embedded-vintage-fonts", 280 | "panic-probe", 281 | "rotary-encoder-hal", 282 | "rp-pico", 283 | "sh1106", 284 | "smart-leds-trait", 285 | "ufmt", 286 | "usb-device", 287 | "usbd-hid", 288 | "ws2812-pio", 289 | ] 290 | 291 | [[package]] 292 | name = "itertools" 293 | version = "0.10.5" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 296 | dependencies = [ 297 | "either", 298 | ] 299 | 300 | [[package]] 301 | name = "micromath" 302 | version = "1.1.1" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94" 305 | 306 | [[package]] 307 | name = "nb" 308 | version = "0.1.3" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 311 | dependencies = [ 312 | "nb 1.1.0", 313 | ] 314 | 315 | [[package]] 316 | name = "nb" 317 | version = "1.1.0" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" 320 | 321 | [[package]] 322 | name = "num" 323 | version = "0.3.1" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" 326 | dependencies = [ 327 | "num-complex", 328 | "num-integer", 329 | "num-iter", 330 | "num-rational", 331 | "num-traits", 332 | ] 333 | 334 | [[package]] 335 | name = "num-complex" 336 | version = "0.3.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 339 | dependencies = [ 340 | "num-traits", 341 | ] 342 | 343 | [[package]] 344 | name = "num-integer" 345 | version = "0.1.46" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 348 | dependencies = [ 349 | "num-traits", 350 | ] 351 | 352 | [[package]] 353 | name = "num-iter" 354 | version = "0.1.44" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" 357 | dependencies = [ 358 | "autocfg", 359 | "num-integer", 360 | "num-traits", 361 | ] 362 | 363 | [[package]] 364 | name = "num-rational" 365 | version = "0.3.2" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 368 | dependencies = [ 369 | "autocfg", 370 | "num-integer", 371 | "num-traits", 372 | ] 373 | 374 | [[package]] 375 | name = "num-traits" 376 | version = "0.2.18" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" 379 | dependencies = [ 380 | "autocfg", 381 | ] 382 | 383 | [[package]] 384 | name = "num_enum" 385 | version = "0.5.11" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" 388 | dependencies = [ 389 | "num_enum_derive", 390 | ] 391 | 392 | [[package]] 393 | name = "num_enum_derive" 394 | version = "0.5.11" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" 397 | dependencies = [ 398 | "proc-macro2", 399 | "quote", 400 | "syn 1.0.109", 401 | ] 402 | 403 | [[package]] 404 | name = "panic-probe" 405 | version = "0.3.1" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "aa6fa5645ef5a760cd340eaa92af9c1ce131c8c09e7f8926d8a24b59d26652b9" 408 | dependencies = [ 409 | "cortex-m", 410 | "defmt", 411 | ] 412 | 413 | [[package]] 414 | name = "paste" 415 | version = "1.0.14" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 418 | 419 | [[package]] 420 | name = "pio" 421 | version = "0.2.1" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3" 424 | dependencies = [ 425 | "arrayvec", 426 | "num_enum", 427 | "paste", 428 | ] 429 | 430 | [[package]] 431 | name = "proc-macro-error" 432 | version = "1.0.4" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 435 | dependencies = [ 436 | "proc-macro-error-attr", 437 | "proc-macro2", 438 | "quote", 439 | "syn 1.0.109", 440 | "version_check", 441 | ] 442 | 443 | [[package]] 444 | name = "proc-macro-error-attr" 445 | version = "1.0.4" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 448 | dependencies = [ 449 | "proc-macro2", 450 | "quote", 451 | "version_check", 452 | ] 453 | 454 | [[package]] 455 | name = "proc-macro2" 456 | version = "1.0.78" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 459 | dependencies = [ 460 | "unicode-ident", 461 | ] 462 | 463 | [[package]] 464 | name = "quote" 465 | version = "1.0.35" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 468 | dependencies = [ 469 | "proc-macro2", 470 | ] 471 | 472 | [[package]] 473 | name = "rand_core" 474 | version = "0.6.4" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 477 | 478 | [[package]] 479 | name = "rgb" 480 | version = "0.8.37" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" 483 | dependencies = [ 484 | "bytemuck", 485 | ] 486 | 487 | [[package]] 488 | name = "rotary-encoder-hal" 489 | version = "0.5.0" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | checksum = "ca5f10fcd6842ed448d9f5913815a343cdcbe10e53da6cac948251d529b75487" 492 | dependencies = [ 493 | "either", 494 | "embedded-hal", 495 | ] 496 | 497 | [[package]] 498 | name = "rp-pico" 499 | version = "0.4.1" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "6b83448890aab5f6e35aa64d6a2441d69b768e7a22aaf943a84b7459340028ec" 502 | dependencies = [ 503 | "cortex-m", 504 | "cortex-m-rt", 505 | "embedded-time", 506 | "rp2040-boot2", 507 | "rp2040-hal", 508 | "usb-device", 509 | "usbd-hid", 510 | "usbd-serial", 511 | ] 512 | 513 | [[package]] 514 | name = "rp2040-boot2" 515 | version = "0.2.1" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "3c773ec49b836077aa144b58dc7654a243e1eecdb6cf0d25361ae7c7600fabd8" 518 | dependencies = [ 519 | "crc-any", 520 | ] 521 | 522 | [[package]] 523 | name = "rp2040-hal" 524 | version = "0.5.0" 525 | dependencies = [ 526 | "cortex-m", 527 | "cortex-m-rt", 528 | "critical-section 0.2.8", 529 | "embedded-hal", 530 | "embedded-time", 531 | "itertools", 532 | "nb 1.1.0", 533 | "paste", 534 | "pio", 535 | "rand_core", 536 | "rp2040-hal-macros", 537 | "rp2040-pac", 538 | "usb-device", 539 | "vcell", 540 | "void", 541 | ] 542 | 543 | [[package]] 544 | name = "rp2040-hal-macros" 545 | version = "0.1.0" 546 | dependencies = [ 547 | "cortex-m-rt", 548 | "proc-macro2", 549 | "quote", 550 | "syn 1.0.109", 551 | ] 552 | 553 | [[package]] 554 | name = "rp2040-pac" 555 | version = "0.3.0" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "13a6106d5db01c7171a39c1f7696780912db9b42fe7ac722db60069c8904ea7c" 558 | dependencies = [ 559 | "cortex-m", 560 | "cortex-m-rt", 561 | "vcell", 562 | ] 563 | 564 | [[package]] 565 | name = "rustc_version" 566 | version = "0.2.3" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 569 | dependencies = [ 570 | "semver", 571 | ] 572 | 573 | [[package]] 574 | name = "semver" 575 | version = "0.9.0" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 578 | dependencies = [ 579 | "semver-parser", 580 | ] 581 | 582 | [[package]] 583 | name = "semver-parser" 584 | version = "0.7.0" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 587 | 588 | [[package]] 589 | name = "serde" 590 | version = "1.0.196" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" 593 | dependencies = [ 594 | "serde_derive", 595 | ] 596 | 597 | [[package]] 598 | name = "serde_derive" 599 | version = "1.0.196" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" 602 | dependencies = [ 603 | "proc-macro2", 604 | "quote", 605 | "syn 2.0.48", 606 | ] 607 | 608 | [[package]] 609 | name = "sh1106" 610 | version = "0.4.0" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "4b4022685baa7cc82b2fb97ced2b53fd753a21d98f45b0fd0b55fc717de9075a" 613 | dependencies = [ 614 | "embedded-graphics-core", 615 | "embedded-hal", 616 | ] 617 | 618 | [[package]] 619 | name = "smart-leds-trait" 620 | version = "0.2.1" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3" 623 | dependencies = [ 624 | "rgb", 625 | ] 626 | 627 | [[package]] 628 | name = "ssmarshal" 629 | version = "1.0.0" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" 632 | dependencies = [ 633 | "encode_unicode", 634 | "serde", 635 | ] 636 | 637 | [[package]] 638 | name = "syn" 639 | version = "1.0.109" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 642 | dependencies = [ 643 | "proc-macro2", 644 | "quote", 645 | "unicode-ident", 646 | ] 647 | 648 | [[package]] 649 | name = "syn" 650 | version = "2.0.48" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" 653 | dependencies = [ 654 | "proc-macro2", 655 | "quote", 656 | "unicode-ident", 657 | ] 658 | 659 | [[package]] 660 | name = "thiserror" 661 | version = "1.0.57" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" 664 | dependencies = [ 665 | "thiserror-impl", 666 | ] 667 | 668 | [[package]] 669 | name = "thiserror-impl" 670 | version = "1.0.57" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" 673 | dependencies = [ 674 | "proc-macro2", 675 | "quote", 676 | "syn 2.0.48", 677 | ] 678 | 679 | [[package]] 680 | name = "ufmt" 681 | version = "0.2.0" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "1a64846ec02b57e9108d6469d98d1648782ad6bb150a95a9baac26900bbeab9d" 684 | dependencies = [ 685 | "ufmt-macros", 686 | "ufmt-write", 687 | ] 688 | 689 | [[package]] 690 | name = "ufmt-macros" 691 | version = "0.3.0" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "d337d3be617449165cb4633c8dece429afd83f84051024079f97ad32a9663716" 694 | dependencies = [ 695 | "proc-macro2", 696 | "quote", 697 | "syn 1.0.109", 698 | ] 699 | 700 | [[package]] 701 | name = "ufmt-write" 702 | version = "0.1.0" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" 705 | 706 | [[package]] 707 | name = "unicode-ident" 708 | version = "1.0.12" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 711 | 712 | [[package]] 713 | name = "usb-device" 714 | version = "0.2.9" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" 717 | 718 | [[package]] 719 | name = "usbd-hid" 720 | version = "0.5.2" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "183b7e65bbd75512aedf250deda89394c74ae3118b79fe41f159e8503e1d5d7f" 723 | dependencies = [ 724 | "serde", 725 | "ssmarshal", 726 | "usb-device", 727 | "usbd-hid-macros", 728 | ] 729 | 730 | [[package]] 731 | name = "usbd-hid-descriptors" 732 | version = "0.1.2" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "dcbee8c6735e90894fba04770bc41e11fd3c5256018856e15dc4dd1e6c8a3dd1" 735 | dependencies = [ 736 | "bitfield", 737 | ] 738 | 739 | [[package]] 740 | name = "usbd-hid-macros" 741 | version = "0.5.2" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "78bd005b3aa54e62905d99df49a75d11888bb958eb780adb5e8f2029733077df" 744 | dependencies = [ 745 | "byteorder", 746 | "proc-macro2", 747 | "quote", 748 | "serde", 749 | "syn 1.0.109", 750 | "usbd-hid-descriptors", 751 | ] 752 | 753 | [[package]] 754 | name = "usbd-serial" 755 | version = "0.1.1" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe" 758 | dependencies = [ 759 | "embedded-hal", 760 | "nb 0.1.3", 761 | "usb-device", 762 | ] 763 | 764 | [[package]] 765 | name = "vcell" 766 | version = "0.1.3" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 769 | 770 | [[package]] 771 | name = "version_check" 772 | version = "0.9.4" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 775 | 776 | [[package]] 777 | name = "void" 778 | version = "1.0.2" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 781 | 782 | [[package]] 783 | name = "volatile-register" 784 | version = "0.2.2" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" 787 | dependencies = [ 788 | "vcell", 789 | ] 790 | 791 | [[package]] 792 | name = "ws2812-pio" 793 | version = "0.3.0" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "59c8b2e9830ab583b86349261a5980a0a33151f812abbb21019444822bb61d27" 796 | dependencies = [ 797 | "cortex-m", 798 | "embedded-hal", 799 | "embedded-time", 800 | "nb 1.1.0", 801 | "pio", 802 | "rp2040-hal", 803 | "smart-leds-trait", 804 | ] 805 | -------------------------------------------------------------------------------- /gaming-pad/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "gaming-pad" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | cortex-m = "0.7" 8 | cortex-m-rt = "0.7" 9 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 10 | embedded-time = "0.12" 11 | 12 | defmt = "0.3" 13 | defmt-rtt = "0.3" 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } 15 | 16 | 17 | adafruit-macropad = "*" 18 | ws2812-pio = "0.3.0" 19 | smart-leds-trait = "0.2.1" 20 | embedded-graphics-core = "0.3.3" 21 | embedded-graphics = "0.7.1" 22 | sh1106="0.4.0" 23 | bitmap-font="*" 24 | embedded-vintage-fonts = "*" 25 | 26 | 27 | rotary-encoder-hal = "*" 28 | ufmt="*" 29 | usbd-hid="0.5.2" 30 | usb-device="0.2.9" 31 | 32 | # We're using a Pico by default on this template 33 | rp-pico = "0.4" 34 | # but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead 35 | # sparkfun-pro-micro-rp2040 = "0.3" 36 | 37 | # If you're not going to use a Board Support Package you'll need these: 38 | # rp2040-hal = { version="0.5", features=["rt"] } 39 | # rp2040-boot2 = "0.2" 40 | 41 | 42 | #[dependencies.sh1107] 43 | #git="https://github.com/aaron-hardin/sh1107.git" 44 | 45 | [dependencies.either] 46 | version = "*" 47 | default-features = false 48 | 49 | 50 | # cargo build/run 51 | [profile.dev] 52 | codegen-units = 1 53 | debug = 2 54 | debug-assertions = true 55 | incremental = false 56 | opt-level = 3 57 | overflow-checks = true 58 | 59 | # cargo build/run --release 60 | [profile.release] 61 | codegen-units = 1 62 | debug = 2 63 | debug-assertions = false 64 | incremental = false 65 | lto = 'fat' 66 | opt-level = 3 67 | overflow-checks = false 68 | 69 | # do not optimize proc-macro crates = faster builds from scratch 70 | [profile.dev.build-override] 71 | codegen-units = 8 72 | debug = false 73 | debug-assertions = false 74 | opt-level = 0 75 | overflow-checks = false 76 | 77 | [profile.release.build-override] 78 | codegen-units = 8 79 | debug = false 80 | debug-assertions = false 81 | opt-level = 0 82 | overflow-checks = false 83 | 84 | # cargo test 85 | [profile.test] 86 | codegen-units = 1 87 | debug = 2 88 | debug-assertions = true 89 | incremental = false 90 | opt-level = 3 91 | overflow-checks = true 92 | 93 | # cargo test --release 94 | [profile.bench] 95 | codegen-units = 1 96 | debug = 2 97 | debug-assertions = false 98 | incremental = false 99 | lto = 'fat' 100 | opt-level = 3 101 | 102 | 103 | [patch.crates-io] 104 | 105 | adafruit-macropad = { path = "../../../vendor/rp-hal/boards/adafruit-macropad"} 106 | rp2040-hal = { path = "../../../vendor/rp-hal/rp2040-hal"} 107 | -------------------------------------------------------------------------------- /gaming-pad/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | protocol = "Swd" 3 | speed = 20000 4 | # If you only have one probe cargo embed will pick automatically 5 | # Otherwise: add your probe's VID/PID/serial to filter 6 | 7 | ## rust-dap 8 | # usb_vid = "6666" 9 | # usb_pid = "4444" 10 | # serial = "test" 11 | 12 | 13 | [default.flashing] 14 | enabled = true 15 | 16 | [default.reset] 17 | enabled = true 18 | halt_afterwards = false 19 | 20 | [default.general] 21 | chip = "RP2040" 22 | log_level = "WARN" 23 | # RP2040 does not support connect_under_reset 24 | connect_under_reset = false 25 | 26 | [default.rtt] 27 | enabled = true 28 | up_mode = "NoBlockSkip" 29 | channels = [ 30 | { up = 0, down = 0, name = "name", up_mode = "NoBlockSkip", format = "Defmt" }, 31 | ] 32 | timeout = 3000 33 | show_timestamps = true 34 | log_enabled = false 35 | log_path = "./logs" 36 | 37 | [default.gdb] 38 | enabled = false 39 | gdb_connection_string = "127.0.0.1:2345" 40 | -------------------------------------------------------------------------------- /gaming-pad/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /gaming-pad/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; -------------------------------------------------------------------------------- /gaming-pad/src/core1.rs: -------------------------------------------------------------------------------- 1 | use adafruit_macropad::hal::sio::SioFifo; 2 | use adafruit_macropad::{pac, KeysTwelve, Sio}; 3 | use embedded_hal::digital::v2::InputPin; 4 | use rotary_encoder_hal::{Direction, Rotary}; 5 | 6 | struct Core1Application 7 | where 8 | RotA: InputPin, 9 | RotB: InputPin, 10 | { 11 | rotary: Rotary, 12 | keys: KeysTwelve, 13 | 14 | rotary_delta: i32, 15 | fire_idx: i32, 16 | key_state: [bool; 12], 17 | old_key_state: [bool; 12], 18 | } 19 | 20 | impl Core1Application 21 | where 22 | RotA: InputPin, 23 | RotB: InputPin, 24 | { 25 | pub fn new(rotary: Rotary, keys: KeysTwelve) -> Self { 26 | Core1Application { 27 | rotary, 28 | keys, 29 | rotary_delta: 0, 30 | fire_idx: -1, 31 | key_state: [false; 12], 32 | old_key_state: [false; 12], 33 | } 34 | } 35 | 36 | pub fn one_pass(&mut self, fifo: &mut SioFifo) { 37 | match self.rotary.update() { 38 | Ok(Direction::Clockwise) => { 39 | self.rotary_delta += 1; 40 | } 41 | Ok(Direction::CounterClockwise) => { 42 | self.rotary_delta -= 1; 43 | } 44 | Ok(Direction::None) => {} 45 | Err(_) => { 46 | // don't care 47 | } 48 | } 49 | 50 | { 51 | let keys_array = self.keys.array_0based(); 52 | for (idx, state) in self.key_state.iter_mut().enumerate() { 53 | let pressed = keys_array[idx].is_low().unwrap(); 54 | *state = pressed; 55 | } 56 | } 57 | 58 | let mut fire_array = [false; 12]; 59 | for (idx, fire) in fire_array.iter_mut().enumerate() { 60 | *fire = self.key_state[idx] && !self.old_key_state[idx]; 61 | } 62 | 63 | let fire_idx = fire_array 64 | .iter() 65 | .enumerate() 66 | .find(|(_, b)| **b) 67 | .map(|(idx, _)| idx as i32); 68 | 69 | if let Some(fire_idx) = fire_idx { 70 | self.fire_idx = fire_idx; 71 | } 72 | 73 | // 74 | 75 | self.old_key_state = self.key_state; 76 | 77 | self.maybe_send_state(fifo); 78 | } 79 | 80 | fn maybe_send_state(&mut self, fifo: &mut SioFifo) { 81 | let msg = fifo.read(); 82 | if let Some(msg) = msg { 83 | if 0 == msg { 84 | fifo.write_blocking(self.rotary_delta as u32); 85 | self.rotary_delta = 0; 86 | fifo.write_blocking(self.fire_idx as u32); 87 | self.fire_idx = -1; 88 | } 89 | } 90 | } 91 | } 92 | 93 | pub fn core1_task(rotary: Rotary, keys: KeysTwelve) -> ! 94 | where 95 | ROTA: InputPin, 96 | ROTB: InputPin, 97 | { 98 | let pac = unsafe { pac::Peripherals::steal() }; 99 | // let core = unsafe { pac::CorePeripherals::steal() }; 100 | let mut sio = Sio::new(pac.SIO); 101 | 102 | let mut app = Core1Application::new(rotary, keys); 103 | 104 | // 105 | 106 | loop { 107 | app.one_pass(&mut sio.fifo); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /gaming-pad/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Blinks the LED on a Pico board 2 | //! 3 | //! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. 4 | #![no_std] 5 | #![no_main] 6 | 7 | use core::str::from_utf8_unchecked; 8 | // Provide an alias for our BSP so we can switch targets quickly. 9 | // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. 10 | use rp_pico as bsp; 11 | // use sparkfun_pro_micro_rp2040 as bsp; 12 | 13 | use crate::mission_modes::HoldKey; 14 | use adafruit_macropad::hal::gpio::{Function, Pin, PinId, PushPullOutput, ValidPinMode}; 15 | use adafruit_macropad::hal::multicore::{Multicore, Stack}; 16 | use adafruit_macropad::hal::pio::SM0; 17 | use adafruit_macropad::hal::sio::SioFifo; 18 | use adafruit_macropad::hal::timer::CountDown; 19 | use adafruit_macropad::hal::usb::UsbBus; 20 | use adafruit_macropad::hal::Timer; 21 | use adafruit_macropad::{ 22 | macropad_clocks, macropad_keypad, macropad_neopixels, macropad_oled, macropad_pins, 23 | macropad_rotary_encoder, Sio, 24 | }; 25 | use bsp::entry; 26 | use bsp::hal::pac::PIO0; 27 | use bsp::hal::{clocks::Clock, pac, watchdog::Watchdog}; 28 | use defmt::*; 29 | use defmt_rtt as _; 30 | use embedded_hal::digital::v2::OutputPin; 31 | use embedded_time::fixed_point::FixedPoint; 32 | use mission_modes::{simple_kr1, IcarusJog, KeyboardOrMouse, MissionMode, MouseHold}; 33 | use painter::DisplayPainter; 34 | use panic_probe as _; 35 | use smart_leds_trait::SmartLedsWrite; 36 | use ufmt::{uWrite, uwrite}; 37 | use usb_device::bus::UsbBusAllocator; 38 | use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbDeviceState, UsbVidPid}; 39 | use usb_device::UsbError; 40 | use usbd_hid::descriptor::{KeyboardReport, MouseReport, SerializedDescriptor}; 41 | use usbd_hid::hid_class::HIDClass; 42 | use ws2812_pio::Ws2812; 43 | 44 | mod core1; 45 | mod mission_modes; 46 | mod painter; 47 | 48 | static mut CORE1_STACK: Stack<4096> = Stack::new(); 49 | 50 | #[entry] 51 | fn main() -> ! { 52 | info!("Program start"); 53 | let mut pac = pac::Peripherals::take().unwrap(); 54 | let core = pac::CorePeripherals::take().unwrap(); 55 | 56 | let mut watchdog = Watchdog::new(pac.WATCHDOG); 57 | 58 | let clocks = macropad_clocks!(pac, watchdog); 59 | 60 | let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); 61 | let mut sio = Sio::new(pac.SIO); 62 | let pins = macropad_pins!(pac, sio); 63 | 64 | let timer = Timer::new(pac.TIMER, &mut pac.RESETS); 65 | 66 | // 67 | 68 | let mut disp = macropad_oled!(pins, clocks, delay, pac); 69 | 70 | let mut led_pin = pins.led.into_push_pull_output(); 71 | 72 | let mut neopixels = macropad_neopixels!(pins, clocks, timer, pac); 73 | 74 | // 75 | 76 | let rotary = macropad_rotary_encoder!(pins); 77 | 78 | let keys = macropad_keypad!(pins); 79 | 80 | let usb_bus = UsbBusAllocator::new(adafruit_macropad::hal::usb::UsbBus::new( 81 | pac.USBCTRL_REGS, 82 | pac.USBCTRL_DPRAM, 83 | clocks.usb_clock, 84 | true, 85 | &mut pac.RESETS, 86 | )); 87 | let mut keyboard_hid = HIDClass::new(&usb_bus, KeyboardReport::desc(), 10); 88 | let mut mouse_hid = HIDClass::new(&usb_bus, MouseReport::desc(), 10); 89 | let mut usb_device = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x239a, 0xbeef)) 90 | .product("macropad-usbd") 91 | .manufacturer("Bob's mad science") 92 | .build(); 93 | 94 | loop { 95 | //support::poll_logger(); 96 | if !usb_device.poll(&mut [&mut keyboard_hid, &mut mouse_hid]) { 97 | continue; 98 | } 99 | let state = usb_device.state(); 100 | if state == UsbDeviceState::Configured { 101 | break; 102 | } 103 | } 104 | 105 | // usb_device.bus().configure(); 106 | 107 | // 108 | // 109 | 110 | disp.clear(); 111 | 112 | //let sys_freq = clocks.system_clock.freq().integer(); 113 | let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo); 114 | let cores = mc.cores(); 115 | let core1 = &mut cores[1]; 116 | let _test = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { 117 | core1::core1_task(rotary, keys) 118 | }); 119 | 120 | let mut application = ApplicationLoop::new( 121 | disp, 122 | &mut led_pin, 123 | &mut neopixels, 124 | sio.fifo, 125 | &mut usb_device, 126 | &mut keyboard_hid, 127 | &mut mouse_hid, 128 | ); 129 | 130 | loop { 131 | let usec = timer.get_counter(); 132 | application.one_pass((usec / 1000) as u32); 133 | let _ = application.display_painter.disp.flush(); 134 | //delay.delay_ms(1); 135 | } 136 | } 137 | 138 | struct MissionModes { 139 | icarus_jog_100: IcarusJog, 140 | icarus_jog_60: IcarusJog, 141 | icarus_jog_70: IcarusJog, 142 | icarus_jog_0: IcarusJog, 143 | mouse1: MouseHold, 144 | hold_f: HoldKey, 145 | } 146 | 147 | impl MissionModes { 148 | /// super important: 149 | /// mapping from keypad indices to macros (missions) 150 | pub(crate) fn mission_for(&mut self, idx: u8) -> Option<&mut dyn MissionMode> { 151 | match idx { 152 | 0 => Some(&mut self.icarus_jog_100), 153 | 3 => Some(&mut self.icarus_jog_70), 154 | 6 => Some(&mut self.icarus_jog_60), 155 | 9 => Some(&mut self.icarus_jog_0), 156 | 157 | 1 => Some(&mut self.mouse1), 158 | 4 => Some(&mut self.hold_f), 159 | 160 | _ => None, 161 | } 162 | } 163 | } 164 | 165 | impl MissionModes { 166 | pub fn new() -> Self { 167 | MissionModes { 168 | icarus_jog_100: IcarusJog::new(1.0), 169 | icarus_jog_60: IcarusJog::new(0.7), 170 | icarus_jog_70: IcarusJog::new(0.6), 171 | icarus_jog_0: IcarusJog::new(0.0), 172 | mouse1: MouseHold::new(), 173 | hold_f: unsafe { HoldKey::lower_case_letter('f') }, 174 | } 175 | } 176 | } 177 | 178 | // 179 | 180 | #[derive(PartialEq)] 181 | pub enum MissionUpdate { 182 | Change(Option), 183 | Preserve, 184 | } 185 | 186 | impl MissionUpdate { 187 | pub fn should_change(&self, other: Option) -> Option> { 188 | match self { 189 | MissionUpdate::Change(future) => { 190 | if *future == other { 191 | None 192 | } else { 193 | Some(*future) 194 | } 195 | } 196 | MissionUpdate::Preserve => None, 197 | } 198 | } 199 | } 200 | 201 | impl ufmt::uDebug for MissionUpdate { 202 | fn fmt(&self, ufmt: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error> 203 | where 204 | W: uWrite + ?Sized, 205 | { 206 | match self { 207 | MissionUpdate::Change(x) => { 208 | ufmt.write_str("Change(")?; 209 | x.fmt(ufmt)?; 210 | ufmt.write_str(")") 211 | } 212 | MissionUpdate::Preserve => ufmt.write_str("Preserve"), 213 | } 214 | } 215 | } 216 | 217 | // 218 | 219 | struct UsbGenerator<'a> { 220 | modes: MissionModes, 221 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 222 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 223 | mouse_hid: &'a mut HIDClass<'a, UsbBus>, 224 | pushed_back: Option, 225 | active_mission: Option, 226 | new_mission: MissionUpdate, 227 | debug_msg: UfmtWrapper<200>, 228 | } 229 | 230 | impl<'a> UsbGenerator<'a> { 231 | pub fn new( 232 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 233 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 234 | mouse_hid: &'a mut HIDClass<'a, UsbBus>, 235 | ) -> Self { 236 | UsbGenerator { 237 | modes: MissionModes::new(), 238 | usb_device, 239 | keyboard_hid, 240 | mouse_hid, 241 | pushed_back: None, 242 | active_mission: None, 243 | new_mission: MissionUpdate::Preserve, 244 | debug_msg: UfmtWrapper::new(), 245 | } 246 | } 247 | 248 | fn curr(&mut self) -> Option<&mut dyn MissionMode> { 249 | self.active_mission 250 | .and_then(|idx| self.modes.mission_for(idx)) 251 | } 252 | 253 | pub fn response(&mut self, millis_elapsed: u32) -> Option { 254 | match self.new_mission.should_change(self.active_mission) { 255 | Some(new_mission) => { 256 | let delay_reboot = self.curr().and_then(|mission| mission.maybe_deactivate()); 257 | match delay_reboot { 258 | None => { 259 | self.active_mission = new_mission; 260 | self.new_mission = MissionUpdate::Preserve; 261 | if let Some(curr) = self.curr() { 262 | curr.reboot(); 263 | Some(curr.one_usb_pass(millis_elapsed)) 264 | } else { 265 | None 266 | } 267 | } 268 | Some(kr) => Some(kr), 269 | } 270 | } 271 | None => self 272 | .pushed_back 273 | .take() 274 | .or_else(|| self.curr().map(|curr| curr.one_usb_pass(millis_elapsed))), 275 | } 276 | } 277 | 278 | pub fn generate_usb_events(&mut self, fire_idx: Option, ticks: u32) { 279 | self.debug_msg.reset(); 280 | 281 | if let Some(idx) = fire_idx { 282 | self.new_mission = if self.active_mission == Some(idx) { 283 | let _ = uwrite!(&mut self.debug_msg, "D "); 284 | MissionUpdate::Change(None) 285 | } else { 286 | MissionUpdate::Change(Some(idx)) 287 | }; 288 | } 289 | if self.new_mission == MissionUpdate::Preserve { 290 | self.debug_msg.reset(); 291 | } else if false { 292 | let _ = uwrite!(&mut self.debug_msg, "{:?}", fire_idx); 293 | let _ = uwrite!(&mut self.debug_msg, "\n{:?}", self.new_mission); 294 | let _ = uwrite!(&mut self.debug_msg, " {:?}", self.active_mission); 295 | } 296 | 297 | self.usb_device 298 | .poll(&mut [self.keyboard_hid, self.mouse_hid]); 299 | 300 | let report = self.response(ticks); 301 | match report { 302 | Some(KeyboardOrMouse::Keyboard(report)) => { 303 | if let Err(UsbError::WouldBlock) = self.keyboard_hid.push_input(&report) { 304 | self.pushed_back = Some(KeyboardOrMouse::Keyboard(report)); 305 | } 306 | } 307 | Some(KeyboardOrMouse::Mouse(report)) => { 308 | if let Err(UsbError::WouldBlock) = self.mouse_hid.push_input(&report) { 309 | self.pushed_back = Some(KeyboardOrMouse::Mouse(report)); 310 | } 311 | } 312 | None => { 313 | let _ = self.keyboard_hid.push_input(&simple_kr1(0, 0)); 314 | let _ = self.mouse_hid.push_input(&MouseReport { 315 | buttons: 0, 316 | x: 0, 317 | y: 0, 318 | wheel: 0, 319 | pan: 0, 320 | }); 321 | } 322 | } 323 | } 324 | } 325 | 326 | // 327 | 328 | struct ApplicationLoop<'a, D, LED, NEOPIN, E> 329 | where 330 | D: embedded_graphics_core::draw_target::DrawTarget< 331 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 332 | Error = E, 333 | >, 334 | LED: PinId, 335 | NEOPIN: PinId, 336 | Function: ValidPinMode, 337 | { 338 | bright: u8, 339 | key_state: [bool; 12], 340 | old_key_state: ChangeDetector<[bool; 12]>, 341 | display_painter: DisplayPainter, 342 | led_pin: &'a mut Pin, 343 | neopixels: &'a mut Ws2812, NEOPIN>, 344 | fifo: SioFifo, 345 | generator: UsbGenerator<'a>, 346 | } 347 | 348 | impl<'a, D, LED, NEOPIN, E> ApplicationLoop<'a, D, LED, NEOPIN, E> 349 | where 350 | D: embedded_graphics_core::draw_target::DrawTarget< 351 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 352 | Error = E, 353 | >, 354 | LED: PinId, 355 | 356 | NEOPIN: PinId, 357 | Function: ValidPinMode, 358 | { 359 | pub fn new( 360 | disp: D, 361 | led_pin: &'a mut Pin, 362 | neopixels: &'a mut Ws2812, NEOPIN>, 363 | fifo: SioFifo, 364 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 365 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 366 | mouse_hid: &'a mut HIDClass<'a, UsbBus>, 367 | ) -> Self { 368 | ApplicationLoop { 369 | bright: 200, 370 | key_state: [false; 12], 371 | old_key_state: ChangeDetector::new([true; 12]), 372 | display_painter: DisplayPainter::new(disp), 373 | led_pin, 374 | neopixels, 375 | fifo, 376 | generator: UsbGenerator::new(usb_device, keyboard_hid, mouse_hid), 377 | } 378 | } 379 | 380 | pub fn one_pass(&mut self, epoch_millis: u32) { 381 | let phase = self.bright as i8; 382 | 383 | if epoch_millis & 0x100 == 0 { 384 | self.led_pin.set_high().unwrap(); 385 | } else { 386 | self.led_pin.set_low().unwrap(); 387 | } 388 | 389 | let _ = self.neopixels.write(lights_for( 390 | self.bright, 391 | epoch_millis, 392 | phase, 393 | self.generator.active_mission, 394 | )); 395 | 396 | let fire_idx = if let Some((rotary_delta, raw_fire_idx)) = poll_core1(&mut self.fifo) { 397 | self.bright = (self.bright as i32 + rotary_delta).clamp(0, 255) as u8; 398 | if raw_fire_idx < 0 { 399 | None 400 | } else { 401 | Some(raw_fire_idx as u8) 402 | } 403 | } else { 404 | None 405 | }; 406 | 407 | self.generator.generate_usb_events(fire_idx, epoch_millis); 408 | 409 | if false { 410 | let _ = self.display_painter.update_display( 411 | self.bright, 412 | self.key_state, 413 | self.generator.active_mission, 414 | self.generator.debug_msg.as_str(), 415 | ); 416 | self.generator.debug_msg.reset(); 417 | } else { 418 | let _ = self.display_painter.idle_display(); 419 | } 420 | 421 | self.old_key_state.changed(self.key_state); 422 | } 423 | } 424 | 425 | fn poll_core1(fifo: &mut SioFifo) -> Option<(i32, i32)> { 426 | if !fifo.is_write_ready() { 427 | return None; 428 | } 429 | 430 | fifo.write(0); 431 | 432 | let rotary_delta = fifo.read_blocking() as i32; 433 | let raw_fire_idx = fifo.read_blocking() as i32; 434 | Some((rotary_delta, raw_fire_idx)) 435 | } 436 | 437 | fn lights_for( 438 | bright: u8, 439 | ticks: u32, 440 | phase: i8, 441 | white_idx: Option, 442 | ) -> impl Iterator { 443 | let black = [(0, 0, 0); 3]; 444 | let rgb = [(bright, 0, 0), (0, bright, 0), (0, 0, bright)]; 445 | let cmy = [ 446 | (0, bright, bright), 447 | (bright, 0, bright), 448 | (bright, bright, 0), 449 | ]; 450 | 451 | wacky_lights( 452 | black, 453 | if ticks & 0x200 == 0 { cmy } else { rgb }, 454 | phase, 455 | white_idx.map(|idx| (idx, (bright, bright, bright))), 456 | ) 457 | } 458 | 459 | struct ChangeDetector { 460 | pub old: T, 461 | } 462 | 463 | impl ChangeDetector { 464 | pub fn new(first: T) -> Self { 465 | ChangeDetector { old: first } 466 | } 467 | 468 | pub fn changed(&mut self, new_val: T) -> bool { 469 | if new_val == self.old { 470 | false 471 | } else { 472 | self.old = new_val; 473 | true 474 | } 475 | } 476 | } 477 | 478 | // 479 | // 480 | 481 | struct UfmtWrapper { 482 | cursor: usize, 483 | buffer: [u8; N], 484 | } 485 | 486 | impl UfmtWrapper { 487 | pub fn new() -> Self { 488 | UfmtWrapper { 489 | cursor: 0, 490 | buffer: [0; N], 491 | } 492 | } 493 | 494 | pub fn as_str(&self) -> &str { 495 | unsafe { from_utf8_unchecked(&self.buffer[..self.cursor]) } 496 | } 497 | pub fn reset(&mut self) { 498 | self.cursor = 0; 499 | } 500 | } 501 | 502 | impl uWrite for UfmtWrapper { 503 | type Error = (); 504 | 505 | fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { 506 | let bytes = s.as_bytes(); 507 | self.buffer[self.cursor..(self.cursor + bytes.len())].copy_from_slice(bytes); 508 | self.cursor += bytes.len(); 509 | Ok(()) 510 | } 511 | } 512 | 513 | // 514 | 515 | fn wacky_lights( 516 | black: [(u8, u8, u8); 3], 517 | rgb: [(u8, u8, u8); 3], 518 | phase: i8, 519 | white_idx: Option<(u8, (u8, u8, u8))>, 520 | ) -> impl Iterator { 521 | let mut rval = [(0, 0, 0); 12]; 522 | for row in 0..4 { 523 | for col in 0..3 { 524 | let src = if (row as i16 - phase as i16) % 4 == 0 { 525 | &rgb 526 | } else { 527 | &black 528 | }; 529 | let idx = row * 3 + col; 530 | rval[idx] = white_idx 531 | .and_then(|(wi, white)| { 532 | if idx == wi as usize { 533 | Some(white) 534 | } else { 535 | None 536 | } 537 | }) 538 | .unwrap_or(src[col]); 539 | } 540 | } 541 | 542 | rval.into_iter() 543 | } 544 | -------------------------------------------------------------------------------- /gaming-pad/src/mission_modes.rs: -------------------------------------------------------------------------------- 1 | use usbd_hid::descriptor::{KeyboardReport, MouseReport}; 2 | 3 | pub fn simple_kr(modifier: u8, keycodes: [u8; 6]) -> KeyboardReport { 4 | KeyboardReport { 5 | modifier, 6 | reserved: 0, 7 | leds: 0, 8 | keycodes, 9 | } 10 | } 11 | 12 | pub fn simple_kr1(modifier: u8, key_code_1: u8) -> KeyboardReport { 13 | simple_kr(modifier, [key_code_1, 0, 0, 0, 0, 0]) 14 | } 15 | 16 | pub trait MissionMode { 17 | fn reboot(&mut self); 18 | 19 | fn one_usb_pass(&mut self, millis_elapsed: u32) -> T; 20 | 21 | fn maybe_deactivate(&mut self) -> Option; 22 | } 23 | 24 | // 25 | 26 | pub enum KeyboardOrMouse { 27 | Keyboard(KeyboardReport), 28 | Mouse(MouseReport), 29 | } 30 | 31 | // 32 | 33 | pub struct IcarusJog { 34 | sprint: bool, 35 | duty_cycle: f32, 36 | deactivated: bool, 37 | phase_millis: Option, 38 | } 39 | 40 | impl IcarusJog { 41 | pub fn new(duty_cycle: f32) -> IcarusJog { 42 | IcarusJog { 43 | sprint: false, 44 | duty_cycle, 45 | deactivated: false, 46 | phase_millis: None, 47 | } 48 | } 49 | } 50 | 51 | impl MissionMode for IcarusJog { 52 | fn reboot(&mut self) { 53 | self.sprint = false; 54 | self.phase_millis = None; 55 | } 56 | 57 | fn one_usb_pass(&mut self, millis_elapsed: u32) -> KeyboardOrMouse { 58 | let phase_millis = match self.phase_millis { 59 | None => { 60 | self.phase_millis = Some(millis_elapsed); 61 | millis_elapsed 62 | } 63 | Some(val) => val, 64 | }; 65 | let period = 6000; 66 | self.sprint = 67 | ((millis_elapsed - phase_millis) % period) < (period as f32 * self.duty_cycle) as u32; 68 | 69 | let keyboard_report = simple_kr1(if self.sprint { 2 } else { 0 }, b'w' - b'a' + 4); 70 | KeyboardOrMouse::Keyboard(keyboard_report) 71 | } 72 | 73 | fn maybe_deactivate(&mut self) -> Option { 74 | if self.deactivated { 75 | None 76 | } else { 77 | self.deactivated = true; 78 | Some(KeyboardOrMouse::Keyboard(simple_kr1(0, 0))) 79 | } 80 | } 81 | } 82 | 83 | // 84 | 85 | pub struct MouseHold { 86 | deactivated: bool, 87 | } 88 | 89 | impl MouseHold { 90 | pub fn new() -> Self { 91 | MouseHold { deactivated: false } 92 | } 93 | } 94 | 95 | impl MissionMode for MouseHold { 96 | fn reboot(&mut self) { 97 | self.deactivated = false; 98 | } 99 | 100 | fn one_usb_pass(&mut self, _millis_elapsed: u32) -> KeyboardOrMouse { 101 | KeyboardOrMouse::Mouse(MouseReport { 102 | buttons: 1, 103 | x: 0, 104 | y: 0, 105 | wheel: 0, 106 | pan: 0, 107 | }) 108 | } 109 | 110 | fn maybe_deactivate(&mut self) -> Option { 111 | if self.deactivated { 112 | None 113 | } else { 114 | self.deactivated = true; 115 | Some(KeyboardOrMouse::Mouse(MouseReport { 116 | buttons: 0, 117 | x: 0, 118 | y: 0, 119 | wheel: 0, 120 | pan: 0, 121 | })) 122 | } 123 | } 124 | } 125 | 126 | // 127 | 128 | pub struct HoldKey { 129 | deactivated: bool, 130 | /// not the character, the key code. 131 | usb_key_code: u8, 132 | } 133 | 134 | impl HoldKey { 135 | /// # Safety 136 | /// `lower_case_letter` must be in the range 'a'-'z' or this will not do what you expect. 137 | pub unsafe fn lower_case_letter(lower_case_letter: char) -> Self { 138 | Self { 139 | deactivated: false, 140 | usb_key_code: lower_case_letter as u8 - b'a' + 4, 141 | } 142 | } 143 | } 144 | 145 | impl MissionMode for HoldKey { 146 | fn reboot(&mut self) {} 147 | 148 | fn one_usb_pass(&mut self, _millis_elapsed: u32) -> KeyboardOrMouse { 149 | let keyboard_report = simple_kr1(0, self.usb_key_code); 150 | KeyboardOrMouse::Keyboard(keyboard_report) 151 | } 152 | 153 | fn maybe_deactivate(&mut self) -> Option { 154 | if self.deactivated { 155 | None 156 | } else { 157 | self.deactivated = true; 158 | Some(KeyboardOrMouse::Keyboard(simple_kr1(0, 0))) 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /gaming-pad/src/painter.rs: -------------------------------------------------------------------------------- 1 | use crate::{ChangeDetector, UfmtWrapper}; 2 | use bitmap_font::tamzen::FONT_8x15; 3 | use bitmap_font::TextStyle; 4 | use embedded_graphics::mono_font::MonoTextStyle; 5 | use embedded_graphics::pixelcolor::BinaryColor; 6 | use embedded_graphics::prelude::{DrawTarget, Point, Size}; 7 | use embedded_graphics::primitives::Rectangle; 8 | use embedded_graphics::text::renderer::TextRenderer; 9 | use embedded_graphics::text::Text; 10 | use embedded_graphics::Drawable; 11 | use embedded_vintage_fonts::FONT_6X8; 12 | use ufmt::uwrite; 13 | 14 | pub fn easy_text_at( 15 | msg: &str, 16 | x: i32, 17 | y: i32, 18 | disp: &mut D, 19 | style: S, 20 | ) -> Result 21 | where 22 | D: DrawTarget, 23 | S: TextRenderer, 24 | { 25 | Text::new(msg, embedded_graphics::geometry::Point::new(x, y), style).draw( 26 | disp, // &mut DTWrapper { inner: disp } 27 | ) 28 | } 29 | 30 | fn paint_multiline_text( 31 | x: i32, 32 | mut y: i32, 33 | mut msg: &str, 34 | fg: embedded_graphics::pixelcolor::BinaryColor, 35 | bg: BinaryColor, 36 | disp: &mut D, 37 | ) -> Result<(), E> 38 | where 39 | D: embedded_graphics_core::draw_target::DrawTarget< 40 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 41 | Error = E, 42 | >, 43 | { 44 | loop { 45 | let ab = msg.split_once('\n'); 46 | let (submessage, more) = match ab { 47 | Some((a, b)) => (a, Some(b)), 48 | None => (msg, None), 49 | }; 50 | const DISPLAY_WIDTH: i32 = 128; 51 | disp.fill_solid( 52 | &Rectangle::new(Point::new(x, y), Size::new((DISPLAY_WIDTH - x) as u32, 10)), 53 | bg, 54 | )?; 55 | 56 | easy_text_at( 57 | submessage, 58 | x, 59 | y + 1, 60 | disp, 61 | MonoTextStyle::new(&FONT_6X8, fg), 62 | )?; 63 | match more { 64 | None => { 65 | break; 66 | } 67 | Some(more) => { 68 | msg = more; 69 | y += 9; 70 | } 71 | } 72 | } 73 | Ok(()) 74 | } 75 | 76 | // 77 | 78 | pub struct DisplayPainter 79 | where 80 | D: embedded_graphics_core::draw_target::DrawTarget< 81 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 82 | Error = E, 83 | >, 84 | { 85 | pub dirty: bool, 86 | pub disp: D, 87 | old_brightness: ChangeDetector, 88 | old_key_state: ChangeDetector<[bool; 12]>, 89 | } 90 | 91 | impl DisplayPainter 92 | where 93 | D: embedded_graphics_core::draw_target::DrawTarget< 94 | Color = embedded_graphics_core::pixelcolor::BinaryColor, 95 | Error = E, 96 | >, 97 | { 98 | pub fn new(disp: D) -> Self { 99 | DisplayPainter { 100 | dirty: true, 101 | disp, 102 | old_brightness: ChangeDetector::new(0), 103 | old_key_state: ChangeDetector::new([true; 12]), 104 | } 105 | } 106 | 107 | pub fn idle_display(&mut self) -> Result<(), E> { 108 | if !self.dirty { 109 | return Ok(()); 110 | } 111 | 112 | const LABELS: [[&str; 3]; 4] = [ 113 | ["sprint", "mine", "-"], 114 | ["jog 70%", "f", "-"], 115 | ["jog 60%", "-", "-"], 116 | ["walk", "-", "-"], 117 | ]; 118 | self.disp 119 | .clear(embedded_graphics_core::pixelcolor::BinaryColor::Off)?; 120 | 121 | easy_text_at( 122 | "Bob's Macro Pad", 123 | 1, 124 | 0, 125 | &mut self.disp, 126 | TextStyle::new( 127 | &FONT_8x15, 128 | embedded_graphics_core::pixelcolor::BinaryColor::On, 129 | ), 130 | )?; 131 | 132 | for (row, labels) in LABELS.iter().enumerate() { 133 | for (col, label) in labels.iter().enumerate() { 134 | let x = (128 + 1) * col / 3 + 21 - label.len() * 3; 135 | let y = 10 * row + 25; 136 | easy_text_at( 137 | label, 138 | x as i32, 139 | y as i32, 140 | &mut self.disp, 141 | MonoTextStyle::new( 142 | &FONT_6X8, 143 | embedded_graphics_core::pixelcolor::BinaryColor::On, 144 | ), 145 | )?; 146 | } 147 | } 148 | self.dirty = false; 149 | Ok(()) 150 | } 151 | 152 | pub fn update_display( 153 | &mut self, 154 | bright: u8, 155 | key_state: [bool; 12], 156 | active_mission: Option, 157 | debug_msg: &str, 158 | ) -> Result<(), E> { 159 | if self.old_brightness.changed(bright) { 160 | self.paint_brightness()?; 161 | } 162 | 163 | if self.old_key_state.changed(key_state) { 164 | self.paint_key0_state(key_state)?; 165 | } 166 | 167 | if true { 168 | return Ok(()); 169 | } 170 | 171 | self.paint_key_grid(active_mission)?; 172 | 173 | if !debug_msg.is_empty() { 174 | paint_multiline_text( 175 | 0, 176 | 10, 177 | debug_msg, 178 | embedded_graphics::pixelcolor::BinaryColor::On, 179 | BinaryColor::Off, 180 | &mut self.disp, 181 | )?; 182 | } 183 | 184 | Ok(()) 185 | } 186 | 187 | fn paint_key_grid(&mut self, active_mission: Option) -> Result<(), E> { 188 | let diam = 5; 189 | for row in 0..4 { 190 | for col in 0..3 { 191 | let idx = row * 3 + col; 192 | self.disp.fill_solid( 193 | &Rectangle::new( 194 | Point::new(col * diam, row * diam), 195 | Size::new(diam as u32, diam as u32), 196 | ), 197 | if active_mission == Some(idx as u8) { 198 | BinaryColor::On 199 | } else { 200 | BinaryColor::Off 201 | }, 202 | )?; 203 | } 204 | } 205 | Ok(()) 206 | } 207 | 208 | fn paint_key0_state(&mut self, key_state: [bool; 12]) -> Result { 209 | let p1 = Point::new(20, 1); 210 | self.disp 211 | .fill_solid(&Rectangle::new(p1, Size::new(100, 10)), BinaryColor::Off)?; 212 | easy_text_at( 213 | if key_state[0] { "0down" } else { "0up" }, 214 | p1.x + 1, 215 | p1.y + 1, 216 | &mut self.disp, 217 | MonoTextStyle::new( 218 | &FONT_6X8, 219 | embedded_graphics_core::pixelcolor::BinaryColor::On, 220 | ), 221 | ) 222 | } 223 | 224 | fn paint_brightness(&mut self) -> Result { 225 | let p1 = Point::new(20, 40); 226 | self.disp 227 | .fill_solid(&Rectangle::new(p1, Size::new(100, 60)), BinaryColor::On)?; 228 | 229 | let mut fmt_buffer = UfmtWrapper::<80>::new(); 230 | 231 | let bright = self.old_brightness.old; 232 | // fmt_buffer.write_str("bright"); 233 | uwrite!(&mut fmt_buffer, "brightness={}", bright).unwrap(); 234 | 235 | easy_text_at( 236 | fmt_buffer.as_str(), 237 | // "brightness", 238 | p1.x + 1, 239 | p1.y + 1, 240 | &mut self.disp, 241 | MonoTextStyle::new( 242 | &FONT_6X8, 243 | embedded_graphics_core::pixelcolor::BinaryColor::On, 244 | ), 245 | ) 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /kbd-exp1/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] 2 | # Choose a default "cargo run" tool: 3 | # - probe-run provides flashing and defmt via a hardware debugger 4 | # - cargo embed offers flashing, rtt, defmt and a gdb server via a hardware debugger 5 | # it is configured via the Embed.toml in the root of this project 6 | # - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode 7 | # runner = "probe-run --chip RP2040" 8 | # runner = "cargo embed" 9 | runner = "elf2uf2-rs -d" 10 | 11 | rustflags = [ 12 | "-C", "linker=flip-link", 13 | "-C", "link-arg=--nmagic", 14 | "-C", "link-arg=-Tlink.x", 15 | "-C", "link-arg=-Tdefmt.x", 16 | 17 | # Code-size optimizations. 18 | # trap unreachable can save a lot of space, but requires nightly compiler. 19 | # uncomment the next line if you wish to enable it 20 | # "-Z", "trap-unreachable=no", 21 | "-C", "inline-threshold=5", 22 | "-C", "no-vectorize-loops", 23 | ] 24 | 25 | [build] 26 | target = "thumbv6m-none-eabi" 27 | 28 | [env] 29 | DEFMT_LOG = "debug" 30 | -------------------------------------------------------------------------------- /kbd-exp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "keyboard-exp-1" 4 | version = "0.1.0" 5 | 6 | [dependencies] 7 | cortex-m = "0.7" 8 | cortex-m-rt = "0.7" 9 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 10 | embedded-time = "0.12" 11 | 12 | defmt = "0.3" 13 | defmt-rtt = "0.3" 14 | panic-probe = { version = "0.3", features = ["print-defmt"] } 15 | 16 | 17 | adafruit-macropad = "*" 18 | ws2812-pio = "0.3.0" 19 | smart-leds-trait = "*" 20 | embedded-graphics-core = "*" 21 | embedded-graphics = "*" 22 | embedded-vintage-fonts = "*" 23 | sh1106="*" 24 | 25 | rotary-encoder-hal = "*" 26 | ufmt="*" 27 | usbd-hid="*" 28 | usb-device="*" 29 | 30 | adafruit-macropad-macros = { path="../adafruit-macropad-macros"} 31 | 32 | # We're using a Pico by default on this template 33 | rp-pico = "0.4" 34 | # but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead 35 | # sparkfun-pro-micro-rp2040 = "0.3" 36 | 37 | # If you're not going to use a Board Support Package you'll need these: 38 | # rp2040-hal = { version="0.5", features=["rt"] } 39 | # rp2040-boot2 = "0.2" 40 | 41 | 42 | #[dependencies.sh1107] 43 | #git="https://github.com/aaron-hardin/sh1107.git" 44 | 45 | [dependencies.either] 46 | version = "*" 47 | default-features = false 48 | 49 | 50 | # cargo build/run 51 | [profile.dev] 52 | codegen-units = 1 53 | debug = 2 54 | debug-assertions = true 55 | incremental = false 56 | opt-level = 3 57 | overflow-checks = true 58 | 59 | # cargo build/run --release 60 | [profile.release] 61 | codegen-units = 1 62 | debug = 2 63 | debug-assertions = false 64 | incremental = false 65 | lto = 'fat' 66 | opt-level = 3 67 | overflow-checks = false 68 | 69 | # do not optimize proc-macro crates = faster builds from scratch 70 | [profile.dev.build-override] 71 | codegen-units = 8 72 | debug = false 73 | debug-assertions = false 74 | opt-level = 0 75 | overflow-checks = false 76 | 77 | [profile.release.build-override] 78 | codegen-units = 8 79 | debug = false 80 | debug-assertions = false 81 | opt-level = 0 82 | overflow-checks = false 83 | 84 | # cargo test 85 | [profile.test] 86 | codegen-units = 1 87 | debug = 2 88 | debug-assertions = true 89 | incremental = false 90 | opt-level = 3 91 | overflow-checks = true 92 | 93 | # cargo test --release 94 | [profile.bench] 95 | codegen-units = 1 96 | debug = 2 97 | debug-assertions = false 98 | incremental = false 99 | lto = 'fat' 100 | opt-level = 3 101 | -------------------------------------------------------------------------------- /kbd-exp1/Embed.toml: -------------------------------------------------------------------------------- 1 | [default.probe] 2 | protocol = "Swd" 3 | speed = 20000 4 | # If you only have one probe cargo embed will pick automatically 5 | # Otherwise: add your probe's VID/PID/serial to filter 6 | 7 | ## rust-dap 8 | # usb_vid = "6666" 9 | # usb_pid = "4444" 10 | # serial = "test" 11 | 12 | 13 | [default.flashing] 14 | enabled = true 15 | 16 | [default.reset] 17 | enabled = true 18 | halt_afterwards = false 19 | 20 | [default.general] 21 | chip = "RP2040" 22 | log_level = "WARN" 23 | # RP2040 does not support connect_under_reset 24 | connect_under_reset = false 25 | 26 | [default.rtt] 27 | enabled = true 28 | up_mode = "NoBlockSkip" 29 | channels = [ 30 | { up = 0, down = 0, name = "name", up_mode = "NoBlockSkip", format = "Defmt" }, 31 | ] 32 | timeout = 3000 33 | show_timestamps = true 34 | log_enabled = false 35 | log_path = "./logs" 36 | 37 | [default.gdb] 38 | enabled = false 39 | gdb_connection_string = "127.0.0.1:2345" 40 | -------------------------------------------------------------------------------- /kbd-exp1/build.rs: -------------------------------------------------------------------------------- 1 | //! This build script copies the `memory.x` file from the crate root into 2 | //! a directory where the linker can always find it at build time. 3 | //! For many projects this is optional, as the linker always searches the 4 | //! project root directory -- wherever `Cargo.toml` is. However, if you 5 | //! are using a workspace or have a more complicated build setup, this 6 | //! build script becomes required. Additionally, by requesting that 7 | //! Cargo re-run the build script whenever `memory.x` is changed, 8 | //! updating `memory.x` ensures a rebuild of the application with the 9 | //! new memory settings. 10 | 11 | use std::env; 12 | use std::fs::File; 13 | use std::io::Write; 14 | use std::path::PathBuf; 15 | 16 | fn main() { 17 | // Put `memory.x` in our output directory and ensure it's 18 | // on the linker search path. 19 | let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 20 | File::create(out.join("memory.x")) 21 | .unwrap() 22 | .write_all(include_bytes!("memory.x")) 23 | .unwrap(); 24 | println!("cargo:rustc-link-search={}", out.display()); 25 | 26 | // By default, Cargo will re-run a build script whenever 27 | // any file in the project changes. By specifying `memory.x` 28 | // here, we ensure the build script is only re-run when 29 | // `memory.x` is changed. 30 | println!("cargo:rerun-if-changed=memory.x"); 31 | } 32 | -------------------------------------------------------------------------------- /kbd-exp1/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; -------------------------------------------------------------------------------- /kbd-exp1/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Blinks the LED on a Pico board 2 | //! 3 | //! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. 4 | #![no_std] 5 | #![no_main] 6 | 7 | use core::str::from_utf8_unchecked; 8 | // Provide an alias for our BSP so we can switch targets quickly. 9 | // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. 10 | use rp_pico as bsp; 11 | // use sparkfun_pro_micro_rp2040 as bsp; 12 | 13 | use crate::pac::PIO0; 14 | use adafruit_macropad::hal::gpio::{Function, Pin, PinId, PushPullOutput, ValidPinMode}; 15 | use adafruit_macropad::hal::pio::{PIOExt, SM0}; 16 | use adafruit_macropad::hal::timer::CountDown; 17 | use adafruit_macropad::hal::usb::UsbBus; 18 | use adafruit_macropad::hal::Timer; 19 | use adafruit_macropad_macros::{ 20 | macropad_clocks, macropad_keypad, macropad_neopixels, macropad_oled, macropad_pins, 21 | macropad_rotary_encoder, KeysTwelve, 22 | }; 23 | use bsp::entry; 24 | use bsp::hal::{clocks::Clock, pac, watchdog::Watchdog}; 25 | use defmt::*; 26 | use defmt_rtt as _; 27 | use embedded_graphics::mono_font::MonoTextStyle; 28 | use embedded_graphics::text::renderer::TextRenderer; 29 | use embedded_graphics::text::Text; 30 | use embedded_graphics_core::draw_target::{DrawTarget as DT_, DrawTarget}; 31 | use embedded_graphics_core::geometry::{Point, Size}; 32 | use embedded_graphics_core::pixelcolor::BinaryColor; 33 | use embedded_graphics_core::primitives::Rectangle; 34 | use embedded_graphics_core::Drawable; 35 | use embedded_hal::digital::v2::{InputPin, OutputPin}; 36 | use embedded_time::fixed_point::FixedPoint; 37 | use embedded_vintage_fonts::FONT_6X8; 38 | use panic_probe as _; 39 | use rotary_encoder_hal::{Direction, Rotary}; 40 | use smart_leds_trait::SmartLedsWrite; 41 | use ufmt::{uWrite, uwrite}; 42 | use usb_device::bus::UsbBusAllocator; 43 | use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbDeviceState, UsbVidPid}; 44 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 45 | use usbd_hid::hid_class::HIDClass; 46 | use ws2812_pio::Ws2812; 47 | 48 | #[entry] 49 | fn main() -> ! { 50 | info!("Program start"); 51 | let mut pac = pac::Peripherals::take().unwrap(); 52 | let core = pac::CorePeripherals::take().unwrap(); 53 | 54 | let mut watchdog = Watchdog::new(pac.WATCHDOG); 55 | 56 | let clocks = macropad_clocks!(pac, watchdog); 57 | 58 | let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); 59 | 60 | let pins = macropad_pins!(pac); 61 | 62 | let timer = Timer::new(pac.TIMER, &mut pac.RESETS); 63 | 64 | // 65 | 66 | let mut disp = macropad_oled!(pins, clocks, delay, pac); 67 | 68 | let mut led_pin = pins.led.into_push_pull_output(); 69 | 70 | let mut neopixels = macropad_neopixels!(pins, clocks, timer, pac); 71 | 72 | // 73 | 74 | let mut rotary = macropad_rotary_encoder!(pins); 75 | 76 | let keys = macropad_keypad!(pins); 77 | 78 | let usb_bus = UsbBusAllocator::new(adafruit_macropad::hal::usb::UsbBus::new( 79 | pac.USBCTRL_REGS, 80 | pac.USBCTRL_DPRAM, 81 | clocks.usb_clock, 82 | true, 83 | &mut pac.RESETS, 84 | )); 85 | let mut keyboard_hid = HIDClass::new(&usb_bus, KeyboardReport::desc(), 10); 86 | let mut usb_device = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x239a, 0xbeef)) 87 | .product("macropad-usbd") 88 | .manufacturer("Bob's mad science") 89 | .build(); 90 | 91 | loop { 92 | //support::poll_logger(); 93 | if !usb_device.poll(&mut [&mut keyboard_hid]) { 94 | continue; 95 | } 96 | let state = usb_device.state(); 97 | if state == UsbDeviceState::Configured { 98 | break; 99 | } 100 | } 101 | 102 | // usb_device.bus().configure(); 103 | 104 | // 105 | // 106 | 107 | disp.clear(); 108 | 109 | let _ = disp.draw_iter((0..10).flat_map(move |y| { 110 | (70..90).map(move |x| { 111 | embedded_graphics_core::Pixel( 112 | Point::new(x, y), 113 | if 0 == 1 & (x + y) { 114 | BinaryColor::On 115 | } else { 116 | BinaryColor::Off 117 | }, 118 | ) 119 | }) 120 | })); 121 | 122 | let _ = disp.flush(); 123 | 124 | let mut application = ApplicationLoop::new( 125 | &mut disp, 126 | &mut led_pin, 127 | &mut neopixels, 128 | &mut rotary, 129 | &keys, 130 | &mut usb_device, 131 | &mut keyboard_hid, 132 | ); 133 | loop { 134 | application.one_pass(); 135 | let _ = application.disp.flush(); 136 | delay.delay_ms(1); 137 | } 138 | } 139 | 140 | struct ApplicationLoop<'a, D, LED, NEOPIN, RA, RB, E> 141 | where 142 | D: DrawTarget, 143 | LED: PinId, 144 | RA: InputPin, 145 | RB: InputPin, 146 | NEOPIN: PinId, 147 | Function: ValidPinMode, 148 | { 149 | bright: u8, 150 | old_brightness: ChangeDetector, 151 | ticks: u32, 152 | key_state: [bool; 12], 153 | old_key_state: ChangeDetector<[bool; 12]>, 154 | state_of_toggle: [bool; 12], 155 | disp: &'a mut D, 156 | led_pin: &'a mut Pin, 157 | neopixels: &'a mut Ws2812, NEOPIN>, 158 | rotary: &'a mut Rotary, 159 | keys: &'a KeysTwelve, 160 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 161 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 162 | } 163 | 164 | impl<'a, D, LED, NEOPIN, RA, RB, E> ApplicationLoop<'a, D, LED, NEOPIN, RA, RB, E> 165 | where 166 | D: DrawTarget, 167 | LED: PinId, 168 | RA: InputPin, 169 | RB: InputPin, 170 | NEOPIN: PinId, 171 | Function: ValidPinMode, 172 | { 173 | pub fn new( 174 | disp: &'a mut D, 175 | led_pin: &'a mut Pin, 176 | neopixels: &'a mut Ws2812, NEOPIN>, 177 | rotary: &'a mut Rotary, 178 | keys: &'a KeysTwelve, 179 | usb_device: &'a mut UsbDevice<'a, UsbBus>, 180 | keyboard_hid: &'a mut HIDClass<'a, UsbBus>, 181 | ) -> Self { 182 | ApplicationLoop { 183 | bright: 200, 184 | old_brightness: ChangeDetector::new(0), 185 | ticks: 0, 186 | key_state: [false; 12], 187 | old_key_state: ChangeDetector::new([true; 12]), 188 | state_of_toggle: [false; 12], 189 | disp, 190 | led_pin, 191 | neopixels, 192 | rotary, 193 | keys, 194 | keyboard_hid, 195 | usb_device, 196 | } 197 | } 198 | 199 | pub fn one_pass(&mut self) { 200 | let phase = self.bright as i8; 201 | 202 | if self.ticks & 0x200 == 0 { 203 | self.led_pin.set_high().unwrap(); 204 | } else { 205 | self.led_pin.set_low().unwrap(); 206 | } 207 | 208 | let _ = self.neopixels.write(lights_for( 209 | self.bright, 210 | self.ticks, 211 | phase, 212 | if self.state_of_toggle[0] { 213 | Some(0) 214 | } else { 215 | None 216 | }, 217 | )); 218 | 219 | match self.rotary.update() { 220 | Ok(Direction::Clockwise) => { 221 | self.bright = (self.bright as u16 + 1).min(255) as u8; 222 | } 223 | Ok(Direction::CounterClockwise) => { 224 | self.bright = (self.bright as i16 - 1).max(0) as u8; 225 | } 226 | Ok(Direction::None) => {} 227 | Err(_) => { 228 | // don't care 229 | } 230 | } 231 | 232 | let keys_array = self.keys.array_0based(); 233 | for (idx, state) in self.key_state.iter_mut().enumerate() { 234 | let pressed = keys_array[idx].is_low().unwrap(); 235 | if !self.old_key_state.old[idx] && pressed { 236 | self.state_of_toggle[idx] = !self.state_of_toggle[idx]; 237 | } 238 | *state = pressed; 239 | } 240 | 241 | self.usb_device.poll(&mut [self.keyboard_hid]); 242 | if self.state_of_toggle[0] { 243 | let _ = self 244 | .keyboard_hid 245 | .push_input(&simple_kr1(0, b'w' - b'a' + 4)); 246 | } else { 247 | let _ = self.keyboard_hid.push_input(&simple_kr1(0, 0)); 248 | } 249 | 250 | let _ = self.update_display(); 251 | 252 | self.ticks = self.ticks.wrapping_add(1); 253 | } 254 | 255 | fn update_display(&mut self) -> Result<(), E> { 256 | if self.old_brightness.changed(self.bright) { 257 | let p1 = Point::new(20, 40); 258 | self.disp 259 | .fill_solid(&Rectangle::new(p1, Size::new(100, 60)), BinaryColor::On)?; 260 | 261 | let mut fmt_buffer = UfmtWrapper::<80>::new(); 262 | 263 | // fmt_buffer.write_str("bright"); 264 | uwrite!(&mut fmt_buffer, "brightness={}", self.bright).unwrap(); 265 | 266 | easy_text_at( 267 | fmt_buffer.as_str(), 268 | // "brightness", 269 | p1.x + 1, 270 | p1.y + 1, 271 | self.disp, 272 | MonoTextStyle::new(&FONT_6X8, BinaryColor::Off), 273 | )?; 274 | } 275 | 276 | if self.old_key_state.changed(self.key_state) { 277 | let p1 = Point::new(20, 1); 278 | self.disp 279 | .fill_solid(&Rectangle::new(p1, Size::new(100, 10)), BinaryColor::Off)?; 280 | easy_text_at( 281 | if self.key_state[0] { "0down" } else { "0up" }, 282 | p1.x + 1, 283 | p1.y + 1, 284 | self.disp, 285 | MonoTextStyle::new(&FONT_6X8, BinaryColor::Off), 286 | )?; 287 | } 288 | 289 | let diam = 5; 290 | for row in 0..4 { 291 | for col in 0..3 { 292 | let idx = row * 3 + col; 293 | self.disp.fill_solid( 294 | &Rectangle::new( 295 | Point::new(col * diam, row * diam), 296 | Size::new(diam as u32, diam as u32), 297 | ), 298 | if self.state_of_toggle[idx as usize] { 299 | BinaryColor::On 300 | } else { 301 | BinaryColor::Off 302 | }, 303 | )?; 304 | } 305 | } 306 | Ok(()) 307 | } 308 | } 309 | 310 | fn simple_kr1(modifier: u8, key_code_1: u8) -> KeyboardReport { 311 | KeyboardReport { 312 | modifier, 313 | reserved: 0, 314 | leds: 0, 315 | keycodes: [key_code_1, 0, 0, 0, 0, 0], 316 | } 317 | } 318 | 319 | fn lights_for( 320 | bright: u8, 321 | ticks: u32, 322 | phase: i8, 323 | white_idx: Option, 324 | ) -> impl Iterator { 325 | let black = [(0, 0, 0); 3]; 326 | let rgb = [(bright, 0, 0), (0, bright, 0), (0, 0, bright)]; 327 | let cmy = [ 328 | (0, bright, bright), 329 | (bright, 0, bright), 330 | (bright, bright, 0), 331 | ]; 332 | 333 | wacky_lights( 334 | black, 335 | if ticks & 0x200 == 0 { cmy } else { rgb }, 336 | phase, 337 | white_idx.map(|idx| (idx, (bright, bright, bright))), 338 | ) 339 | } 340 | 341 | pub fn easy_text_at( 342 | msg: &str, 343 | x: i32, 344 | y: i32, 345 | disp: &mut D, 346 | style: S, 347 | ) -> Result 348 | where 349 | D: DrawTarget, 350 | S: TextRenderer, 351 | { 352 | Text::new(msg, Point::new(x, y), style).draw( 353 | disp, // &mut DTWrapper { inner: disp } 354 | ) 355 | } 356 | 357 | struct ChangeDetector { 358 | pub old: T, 359 | } 360 | 361 | impl ChangeDetector { 362 | pub fn new(first: T) -> Self { 363 | ChangeDetector { old: first } 364 | } 365 | 366 | pub fn changed(&mut self, new_val: T) -> bool { 367 | if new_val == self.old { 368 | false 369 | } else { 370 | self.old = new_val; 371 | true 372 | } 373 | } 374 | } 375 | 376 | struct UfmtWrapper { 377 | cursor: usize, 378 | buffer: [u8; N], 379 | } 380 | 381 | impl UfmtWrapper { 382 | pub fn new() -> Self { 383 | UfmtWrapper { 384 | cursor: 0, 385 | buffer: [0; N], 386 | } 387 | } 388 | 389 | pub fn as_str(&self) -> &str { 390 | unsafe { from_utf8_unchecked(&self.buffer[..self.cursor]) } 391 | } 392 | } 393 | 394 | impl uWrite for UfmtWrapper { 395 | type Error = (); 396 | 397 | fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { 398 | let bytes = s.as_bytes(); 399 | self.buffer[self.cursor..(self.cursor + bytes.len())].copy_from_slice(bytes); 400 | self.cursor += bytes.len(); 401 | Ok(()) 402 | } 403 | } 404 | 405 | fn wacky_lights( 406 | black: [(u8, u8, u8); 3], 407 | rgb: [(u8, u8, u8); 3], 408 | phase: i8, 409 | white_idx: Option<(u8, (u8, u8, u8))>, 410 | ) -> impl Iterator { 411 | let mut rval = [(0, 0, 0); 12]; 412 | for row in 0..4 { 413 | for col in 0..3 { 414 | let src = if (row as i16 - phase as i16) % 4 == 0 { 415 | &rgb 416 | } else { 417 | &black 418 | }; 419 | let idx = row * 3 + col; 420 | rval[idx] = white_idx 421 | .and_then(|(wi, white)| { 422 | if idx == wi as usize { 423 | Some(white) 424 | } else { 425 | None 426 | } 427 | }) 428 | .unwrap_or(src[col]); 429 | } 430 | } 431 | 432 | rval.into_iter() 433 | } 434 | -------------------------------------------------------------------------------- /macropad-helpers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macropad-helpers" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | embedded-graphics = "*" 10 | embedded-graphics-core = "*" 11 | -------------------------------------------------------------------------------- /macropad-helpers/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | -------------------------------------------------------------------------------- /multicore-exp1/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Cargo Configuration for the https://github.com/rp-rs/rp-hal.git repository. 3 | # 4 | # Copyright (c) The RP-RS Developers, 2021 5 | # 6 | # You might want to make a similar file in your own repository if you are 7 | # writing programs for Raspberry Silicon microcontrollers. 8 | # 9 | # This file is MIT or Apache-2.0 as per the repository README.md file 10 | # 11 | 12 | [build] 13 | # Set the default target to match the Cortex-M0+ in the RP2040 14 | target = "thumbv6m-none-eabi" 15 | 16 | # Target specific options 17 | [target.thumbv6m-none-eabi] 18 | # Pass some extra options to rustc, some of which get passed on to the linker. 19 | # 20 | # * linker argument --nmagic turns off page alignment of sections (which saves 21 | # flash space) 22 | # * linker argument -Tlink.x tells the linker to use link.x as the linker 23 | # script. This is usually provided by the cortex-m-rt crate, and by default 24 | # the version in that crate will include a file called `memory.x` which 25 | # describes the particular memory layout for your specific chip. 26 | # * inline-threshold=5 makes the compiler more aggressive and inlining functions 27 | # * no-vectorize-loops turns off the loop vectorizer (seeing as the M0+ doesn't 28 | # have SIMD) 29 | rustflags = [ 30 | "-C", "link-arg=--nmagic", 31 | "-C", "link-arg=-Tlink.x", 32 | "-C", "inline-threshold=5", 33 | "-C", "no-vectorize-loops", 34 | ] 35 | 36 | # This runner will make a UF2 file and then copy it to a mounted RP2040 in USB 37 | # Bootloader mode: 38 | runner = "elf2uf2-rs -d" 39 | 40 | # This runner will find a supported SWD debug probe and flash your RP2040 over 41 | # SWD: 42 | # runner = "probe-run --chip RP2040" 43 | -------------------------------------------------------------------------------- /multicore-exp1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adafruit-feather-rp2040" 7 | version = "0.3.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3d730cb4f223a09f8151776f363f0a9ec9c4b008f52db3329301d08ac90439dc" 10 | dependencies = [ 11 | "cortex-m", 12 | "cortex-m-rt", 13 | "embedded-time", 14 | "rp2040-boot2", 15 | "rp2040-hal", 16 | ] 17 | 18 | [[package]] 19 | name = "aho-corasick" 20 | version = "0.7.18" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 23 | dependencies = [ 24 | "memchr", 25 | ] 26 | 27 | [[package]] 28 | name = "arrayvec" 29 | version = "0.7.2" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 32 | 33 | [[package]] 34 | name = "autocfg" 35 | version = "1.1.0" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 38 | 39 | [[package]] 40 | name = "bare-metal" 41 | version = "0.2.5" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" 44 | dependencies = [ 45 | "rustc_version", 46 | ] 47 | 48 | [[package]] 49 | name = "bare-metal" 50 | version = "1.0.0" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" 53 | 54 | [[package]] 55 | name = "bit_field" 56 | version = "0.10.1" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" 59 | 60 | [[package]] 61 | name = "bitfield" 62 | version = "0.13.2" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" 65 | 66 | [[package]] 67 | name = "cfg-if" 68 | version = "1.0.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 71 | 72 | [[package]] 73 | name = "cortex-m" 74 | version = "0.7.5" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" 77 | dependencies = [ 78 | "bare-metal 0.2.5", 79 | "bitfield", 80 | "embedded-hal", 81 | "volatile-register", 82 | ] 83 | 84 | [[package]] 85 | name = "cortex-m-rt" 86 | version = "0.7.1" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7" 89 | dependencies = [ 90 | "cortex-m-rt-macros", 91 | ] 92 | 93 | [[package]] 94 | name = "cortex-m-rt-macros" 95 | version = "0.7.0" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7" 98 | dependencies = [ 99 | "proc-macro2", 100 | "quote", 101 | "syn", 102 | ] 103 | 104 | [[package]] 105 | name = "crc-any" 106 | version = "2.4.3" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "774646b687f63643eb0f4bf13dc263cb581c8c9e57973b6ddf78bda3994d88df" 109 | dependencies = [ 110 | "debug-helper", 111 | ] 112 | 113 | [[package]] 114 | name = "critical-section" 115 | version = "0.2.7" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" 118 | dependencies = [ 119 | "bare-metal 1.0.0", 120 | "cfg-if", 121 | "cortex-m", 122 | "riscv", 123 | ] 124 | 125 | [[package]] 126 | name = "debug-helper" 127 | version = "0.3.13" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" 130 | 131 | [[package]] 132 | name = "either" 133 | version = "1.7.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" 136 | 137 | [[package]] 138 | name = "embedded-hal" 139 | version = "0.2.7" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" 142 | dependencies = [ 143 | "nb 0.1.3", 144 | "void", 145 | ] 146 | 147 | [[package]] 148 | name = "embedded-time" 149 | version = "0.12.1" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" 152 | dependencies = [ 153 | "num", 154 | ] 155 | 156 | [[package]] 157 | name = "itertools" 158 | version = "0.10.3" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" 161 | dependencies = [ 162 | "either", 163 | ] 164 | 165 | [[package]] 166 | name = "lazy_static" 167 | version = "1.4.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 170 | 171 | [[package]] 172 | name = "memchr" 173 | version = "2.5.0" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 176 | 177 | [[package]] 178 | name = "multicore-exp1" 179 | version = "0.1.0" 180 | dependencies = [ 181 | "adafruit-feather-rp2040", 182 | "cortex-m", 183 | "cortex-m-rt", 184 | "embedded-hal", 185 | "embedded-time", 186 | "panic-probe", 187 | ] 188 | 189 | [[package]] 190 | name = "nb" 191 | version = "0.1.3" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" 194 | dependencies = [ 195 | "nb 1.0.0", 196 | ] 197 | 198 | [[package]] 199 | name = "nb" 200 | version = "1.0.0" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" 203 | 204 | [[package]] 205 | name = "num" 206 | version = "0.3.1" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" 209 | dependencies = [ 210 | "num-complex", 211 | "num-integer", 212 | "num-iter", 213 | "num-rational", 214 | "num-traits", 215 | ] 216 | 217 | [[package]] 218 | name = "num-complex" 219 | version = "0.3.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 222 | dependencies = [ 223 | "num-traits", 224 | ] 225 | 226 | [[package]] 227 | name = "num-integer" 228 | version = "0.1.45" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 231 | dependencies = [ 232 | "autocfg", 233 | "num-traits", 234 | ] 235 | 236 | [[package]] 237 | name = "num-iter" 238 | version = "0.1.43" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 241 | dependencies = [ 242 | "autocfg", 243 | "num-integer", 244 | "num-traits", 245 | ] 246 | 247 | [[package]] 248 | name = "num-rational" 249 | version = "0.3.2" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 252 | dependencies = [ 253 | "autocfg", 254 | "num-integer", 255 | "num-traits", 256 | ] 257 | 258 | [[package]] 259 | name = "num-traits" 260 | version = "0.2.15" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 263 | dependencies = [ 264 | "autocfg", 265 | ] 266 | 267 | [[package]] 268 | name = "num_enum" 269 | version = "0.5.7" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" 272 | dependencies = [ 273 | "num_enum_derive", 274 | ] 275 | 276 | [[package]] 277 | name = "num_enum_derive" 278 | version = "0.5.7" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" 281 | dependencies = [ 282 | "proc-macro2", 283 | "quote", 284 | "syn", 285 | ] 286 | 287 | [[package]] 288 | name = "panic-probe" 289 | version = "0.3.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "3ab1f00eac22bd18f8e5cae9555f2820b3a0c166b5b556ee3e203746ea6dcf3a" 292 | dependencies = [ 293 | "cortex-m", 294 | ] 295 | 296 | [[package]] 297 | name = "paste" 298 | version = "1.0.7" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" 301 | 302 | [[package]] 303 | name = "pio" 304 | version = "0.2.0" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "0fd642eada42517e6589cd7f5e830630324aec628fb4aa719000f8801e40c0a2" 307 | dependencies = [ 308 | "arrayvec", 309 | "num_enum", 310 | "paste", 311 | ] 312 | 313 | [[package]] 314 | name = "proc-macro2" 315 | version = "1.0.40" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" 318 | dependencies = [ 319 | "unicode-ident", 320 | ] 321 | 322 | [[package]] 323 | name = "quote" 324 | version = "1.0.20" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" 327 | dependencies = [ 328 | "proc-macro2", 329 | ] 330 | 331 | [[package]] 332 | name = "rand_core" 333 | version = "0.6.3" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 336 | 337 | [[package]] 338 | name = "regex" 339 | version = "1.6.0" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 342 | dependencies = [ 343 | "aho-corasick", 344 | "memchr", 345 | "regex-syntax", 346 | ] 347 | 348 | [[package]] 349 | name = "regex-syntax" 350 | version = "0.6.27" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 353 | 354 | [[package]] 355 | name = "riscv" 356 | version = "0.7.0" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" 359 | dependencies = [ 360 | "bare-metal 1.0.0", 361 | "bit_field", 362 | "riscv-target", 363 | ] 364 | 365 | [[package]] 366 | name = "riscv-target" 367 | version = "0.1.2" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" 370 | dependencies = [ 371 | "lazy_static", 372 | "regex", 373 | ] 374 | 375 | [[package]] 376 | name = "rp2040-boot2" 377 | version = "0.2.0" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "8b480fe63133f0d639f82ce5a027fee7cac7ac92f67ef1896ee036a6f9737128" 380 | dependencies = [ 381 | "crc-any", 382 | ] 383 | 384 | [[package]] 385 | name = "rp2040-hal" 386 | version = "0.5.0" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "0de1bc8bf092f5da649a417ad9f18c9705b6226afe3521a469f15d1d2bcb7f66" 389 | dependencies = [ 390 | "cortex-m", 391 | "cortex-m-rt", 392 | "critical-section", 393 | "embedded-hal", 394 | "embedded-time", 395 | "itertools", 396 | "nb 1.0.0", 397 | "paste", 398 | "pio", 399 | "rand_core", 400 | "rp2040-hal-macros", 401 | "rp2040-pac", 402 | "usb-device", 403 | "vcell", 404 | "void", 405 | ] 406 | 407 | [[package]] 408 | name = "rp2040-hal-macros" 409 | version = "0.1.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e" 412 | dependencies = [ 413 | "cortex-m-rt", 414 | "proc-macro2", 415 | "quote", 416 | "syn", 417 | ] 418 | 419 | [[package]] 420 | name = "rp2040-pac" 421 | version = "0.3.0" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "13a6106d5db01c7171a39c1f7696780912db9b42fe7ac722db60069c8904ea7c" 424 | dependencies = [ 425 | "cortex-m", 426 | "cortex-m-rt", 427 | "vcell", 428 | ] 429 | 430 | [[package]] 431 | name = "rustc_version" 432 | version = "0.2.3" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 435 | dependencies = [ 436 | "semver", 437 | ] 438 | 439 | [[package]] 440 | name = "semver" 441 | version = "0.9.0" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 444 | dependencies = [ 445 | "semver-parser", 446 | ] 447 | 448 | [[package]] 449 | name = "semver-parser" 450 | version = "0.7.0" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 453 | 454 | [[package]] 455 | name = "syn" 456 | version = "1.0.98" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" 459 | dependencies = [ 460 | "proc-macro2", 461 | "quote", 462 | "unicode-ident", 463 | ] 464 | 465 | [[package]] 466 | name = "unicode-ident" 467 | version = "1.0.2" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" 470 | 471 | [[package]] 472 | name = "usb-device" 473 | version = "0.2.8" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245" 476 | 477 | [[package]] 478 | name = "vcell" 479 | version = "0.1.3" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" 482 | 483 | [[package]] 484 | name = "void" 485 | version = "1.0.2" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 488 | 489 | [[package]] 490 | name = "volatile-register" 491 | version = "0.2.1" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" 494 | dependencies = [ 495 | "vcell", 496 | ] 497 | -------------------------------------------------------------------------------- /multicore-exp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | #resolver="2" 2 | 3 | [package] 4 | name = "multicore-exp1" 5 | version = "0.1.0" 6 | edition = "2018" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | cortex-m = "0.7.2" 12 | cortex-m-rt = ">=0.6.15,<0.8" 13 | embedded-hal = { version = "0.2.5", features = ["unproven"] } 14 | embedded-time = "0.12.0" 15 | adafruit-feather-rp2040 = "*" 16 | panic-probe = "*" 17 | -------------------------------------------------------------------------------- /multicore-exp1/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 3 | FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 4 | RAM : ORIGIN = 0x20000000, LENGTH = 256K 5 | } 6 | 7 | EXTERN(BOOT2_FIRMWARE) 8 | 9 | SECTIONS { 10 | /* ### Boot loader */ 11 | .boot2 ORIGIN(BOOT2) : 12 | { 13 | KEEP(*(.boot2)); 14 | } > BOOT2 15 | } INSERT BEFORE .text; -------------------------------------------------------------------------------- /multicore-exp1/src/main.rs: -------------------------------------------------------------------------------- 1 | //! # Multicore Blinking Example 2 | //! 3 | //! This application blinks two LEDs on GPIOs 2 and 3 at different rates (3Hz 4 | //! and 4Hz respectively.) 5 | //! 6 | //! See the `Cargo.toml` file for Copyright and licence details. 7 | 8 | #![no_std] 9 | #![no_main] 10 | 11 | use cortex_m::delay::Delay; 12 | // The macro for our start-up function 13 | use cortex_m_rt::entry; 14 | 15 | use embedded_time::fixed_point::FixedPoint; 16 | use hal::clocks::Clock; 17 | use hal::gpio::Pins; 18 | use hal::multicore::{Multicore, Stack}; 19 | use hal::sio::Sio; 20 | use panic_probe as _; 21 | 22 | // Alias for our HAL crate 23 | use adafruit_feather_rp2040::hal as hal; 24 | 25 | // A shorter alias for the Peripheral Access Crate, which provides low-level 26 | // register access 27 | use hal::pac; 28 | 29 | // Some traits we need 30 | use embedded_hal::digital::v2::ToggleableOutputPin; 31 | 32 | /// The linker will place this boot block at the start of our program image. We 33 | /// need this to help the ROM bootloader get our code up and running. 34 | /*#[link_section = ".boot2"] 35 | #[used] 36 | pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;*/ 37 | 38 | /// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust 39 | /// if your board has a different frequency 40 | const XTAL_FREQ_HZ: u32 = 12_000_000u32; 41 | 42 | /// The frequency at which core 0 will blink its LED (Hz). 43 | const CORE0_FREQ: u32 = 3; 44 | /// The frequency at which core 1 will blink its LED (Hz). 45 | const CORE1_FREQ: u32 = 4; 46 | /// The delay between each toggle of core 0's LED (us). 47 | const CORE0_DELAY: u32 = 1_000_000 / CORE0_FREQ; 48 | /// The delay between each toggle of core 1's LED (us). 49 | const CORE1_DELAY: u32 = 1_000_000 / CORE1_FREQ; 50 | 51 | /// Stack for core 1 52 | /// 53 | /// Core 0 gets its stack via the normal route - any memory not used by static 54 | /// values is reserved for stack and initialised by cortex-m-rt. 55 | /// To get the same for Core 1, we would need to compile everything seperately 56 | /// and modify the linker file for both programs, and that's quite annoying. 57 | /// So instead, core1.spawn takes a [usize] which gets used for the stack. 58 | /// NOTE: We use the `Stack` struct here to ensure that it has 32-byte 59 | /// alignment, which allows the stack guard to take up the least amount of 60 | /// usable RAM. 61 | static mut CORE1_STACK: Stack<4096> = Stack::new(); 62 | 63 | /// Entry point to our bare-metal application. 64 | /// 65 | /// The `#[entry]` macro ensures the Cortex-M start-up code calls this function 66 | /// as soon as all global variables are initialised. 67 | #[entry] 68 | fn main() -> ! { 69 | // Grab our singleton objects 70 | let mut pac = pac::Peripherals::take().unwrap(); 71 | let core = pac::CorePeripherals::take().unwrap(); 72 | 73 | // Set up the watchdog driver - needed by the clock setup code 74 | let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG); 75 | 76 | // Configure the clocks 77 | let clocks = hal::clocks::init_clocks_and_plls( 78 | XTAL_FREQ_HZ, 79 | pac.XOSC, 80 | pac.CLOCKS, 81 | pac.PLL_SYS, 82 | pac.PLL_USB, 83 | &mut pac.RESETS, 84 | &mut watchdog, 85 | ) 86 | .ok() 87 | .unwrap(); 88 | 89 | // Set up the GPIO pins 90 | let mut sio = Sio::new(pac.SIO); 91 | let pins = Pins::new( 92 | pac.IO_BANK0, 93 | pac.PADS_BANK0, 94 | sio.gpio_bank0, 95 | &mut pac.RESETS, 96 | ); 97 | let mut led1 = pins.gpio2.into_push_pull_output(); 98 | let mut led2 = pins.gpio13.into_push_pull_output();/* 99 | embedded_hal::digital::v2::OutputPin::set_high(&mut led1); 100 | embedded_hal::digital::v2::OutputPin::set_high(&mut led2);*/ 101 | 102 | // Set up the delay for the first core. 103 | let sys_freq = clocks.system_clock.freq().integer(); 104 | let mut delay = Delay::new(core.SYST, sys_freq); 105 | 106 | // Start up the second core to blink the second LED 107 | let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo); 108 | let cores = mc.cores(); 109 | let core1 = &mut cores[1]; 110 | core1 111 | .spawn(unsafe { &mut CORE1_STACK.mem }, move || { 112 | // Get the second core's copy of the `CorePeripherals`, which are per-core. 113 | // Unfortunately, `cortex-m` doesn't support this properly right now, 114 | // so we have to use `steal`. 115 | let core = unsafe { pac::CorePeripherals::steal() }; 116 | // Set up the delay for the second core. 117 | let mut delay = Delay::new(core.SYST, sys_freq); 118 | // Blink the second LED. 119 | loop { 120 | led2.toggle().unwrap(); 121 | delay.delay_us(CORE1_DELAY) 122 | } 123 | }) 124 | .unwrap(); 125 | 126 | // Blink the first LED. 127 | loop { 128 | led1.toggle().unwrap(); 129 | delay.delay_us(CORE0_DELAY) 130 | } 131 | } 132 | 133 | // End of file 134 | --------------------------------------------------------------------------------