From 63aefa717fd12b794acc5d87a69766a0cdf71170 Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Sun, 18 Jun 2023 20:21:58 +0200 Subject: [PATCH] First attemt on runnable code --- rp2040/src/main.rs | 329 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 301 insertions(+), 28 deletions(-) diff --git a/rp2040/src/main.rs b/rp2040/src/main.rs index 839a31c..1f1e7a5 100644 --- a/rp2040/src/main.rs +++ b/rp2040/src/main.rs @@ -2,6 +2,7 @@ #![no_main] use core::convert::Infallible; +use cortex_m::delay::Delay; use embedded_hal::digital::v2::*; use embedded_hal::timer::CountDown; use fugit::ExtU32; @@ -25,10 +26,29 @@ use waveshare_rp2040_zero::{ }; use ws2812_pio::Ws2812; +pub const NUMBER_OF_KEYS: usize = 42; + +#[derive(Copy, Clone)] +struct MatrixKey { + current_state: bool, + previous_state: bool, + fn_mode: u8, +} + +impl MatrixKey { + fn default() -> Self { + Self { + current_state: false, + previous_state: false, + fn_mode: 0, + } + } +} + #[entry] fn main() -> ! { let mut pac = pac::Peripherals::take().unwrap(); - + let core = pac::CorePeripherals::take().unwrap(); let mut watchdog = Watchdog::new(pac.WATCHDOG); let clocks = init_clocks_and_plls( @@ -72,11 +92,11 @@ fn main() -> ! { .build(); let timer = Timer::new(pac.TIMER, &mut pac.RESETS); + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); - // Configure the addressable LED + // Configure the status LED let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); - let mut ws = Ws2812::new( - // The onboard NeoPixel is attached to GPIO pin #16 on the Feather RP2040. + let mut status_led = Ws2812::new( pins.neopixel.into_mode(), &mut pio, sm0, @@ -84,26 +104,182 @@ fn main() -> ! { timer.count_down(), ); - let matrix_rows: &[&dyn InputPin] = &[ + let mut matrix_keys: [MatrixKey; NUMBER_OF_KEYS] = [MatrixKey::default(); NUMBER_OF_KEYS]; + + let matrix_rows: &[&dyn InputPin] = &[ &pins.gp0.into_pull_up_input(), &pins.gp1.into_pull_up_input(), - &pins.gp2.into_pull_up_input(), - &pins.gp3.into_pull_up_input(), + &pins.gp29.into_pull_up_input(), + &pins.gp28.into_pull_up_input(), ]; - let matrix_cols: &[&dyn OutputPin] = &[ - &pins.gp4.into_push_pull_output(), - &pins.gp5.into_push_pull_output(), - &pins.gp6.into_push_pull_output(), - &pins.gp7.into_push_pull_output(), - &pins.gp8.into_push_pull_output(), - &pins.gp9.into_push_pull_output(), - &pins.gp10.into_push_pull_output(), - &pins.gp11.into_push_pull_output(), - &pins.gp12.into_push_pull_output(), - &pins.gp13.into_push_pull_output(), - &pins.gp14.into_push_pull_output(), - &pins.gp15.into_push_pull_output(), + let matrix_cols: &mut [&mut dyn OutputPin] = &mut [ + &mut pins.gp12.into_push_pull_output(), + &mut pins.gp13.into_push_pull_output(), + &mut pins.gp14.into_push_pull_output(), + &mut pins.gp15.into_push_pull_output(), + &mut pins.gp26.into_push_pull_output(), + &mut pins.gp27.into_push_pull_output(), + &mut pins.gp7.into_push_pull_output(), + &mut pins.gp8.into_push_pull_output(), + &mut pins.gp6.into_push_pull_output(), + &mut pins.gp9.into_push_pull_output(), + &mut pins.gp10.into_push_pull_output(), + &mut pins.gp11.into_push_pull_output(), + ]; + + // ------------------------------------- ------------------------------------- + // | 0 | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | 11 | + // | 12 | 13 | 14 | 15 | 16 | 17 | | 18 | 19 | 20 | 21 | 22 | 23 | + // | 24 | 25 | 26 | 27 | 28 | 29 | | 30 | 31 | 32 | 33 | 34 | 35 | + // ------------------| 36 | 37 | 38 | | 39 | 40 | 41 |------------------ + // ------------------- ------------------- + // GRAVE = § + // SEMICOLON = ö + // APOSTROPHE = ä + // LEFT_BRACE = å + // FORWARDSLASH = - + // NON_US_BACKSLASH = < + // EQUAL = ´ + // BACKSLASH = ' + // RIGHT_BRACE = ^ + // MINUS = + + // LEFT_ALT = Alt + // RIGHT_ALT = AltGr + + let layout: [[Keyboard; NUMBER_OF_KEYS]; 3] = [ + [ // Function layer 0 + Keyboard::Tab, + Keyboard::Q, + Keyboard::W, + Keyboard::E, + Keyboard::R, + Keyboard::T, + Keyboard::Y, + Keyboard::U, + Keyboard::I, + Keyboard::O, + Keyboard::P, + Keyboard::LeftBrace, + Keyboard::LeftControl, + Keyboard::A, + Keyboard::S, + Keyboard::D, + Keyboard::F, + Keyboard::G, + Keyboard::H, + Keyboard::J, + Keyboard::K, + Keyboard::L, + Keyboard::Semicolon, + Keyboard::Apostrophe, + Keyboard::LeftShift, + Keyboard::Z, + Keyboard::X, + Keyboard::C, + Keyboard::V, + Keyboard::B, + Keyboard::N, + Keyboard::M, + Keyboard::Comma, + Keyboard::Dot, + Keyboard::ForwardSlash, + Keyboard::RightShift, + Keyboard::LeftAlt, + Keyboard::NoEventIndicated, + Keyboard::Space, + Keyboard::Space, + Keyboard::NoEventIndicated, + Keyboard::RightAlt, + ], + [ // Function layer 1 + Keyboard::Escape, + Keyboard::F1, + Keyboard::F2, + Keyboard::F3, + Keyboard::F4, + Keyboard::F5, + Keyboard::F6, + Keyboard::F7, + Keyboard::F8, + Keyboard::F9, + Keyboard::F10, + Keyboard::DeleteBackspace, + Keyboard::LeftControl, + Keyboard::Keyboard1, + Keyboard::Keyboard2, + Keyboard::Keyboard3, + Keyboard::Keyboard4, + Keyboard::Keyboard5, + Keyboard::Keyboard6, + Keyboard::Keyboard7, + Keyboard::Keyboard8, + Keyboard::Keyboard9, + Keyboard::Keyboard0, + Keyboard::ReturnEnter, + Keyboard::LeftShift, + Keyboard::Keyboard6, + Keyboard::Keyboard7, + Keyboard::Keyboard8, + Keyboard::Keyboard9, + Keyboard::Keyboard0, + Keyboard::NonUSBackslash, + Keyboard::Equal, + Keyboard::Backslash, + Keyboard::RightBrace, + Keyboard::Minus, + Keyboard::RightShift, + Keyboard::LeftAlt, + Keyboard::NoEventIndicated, + Keyboard::DeleteBackspace, + Keyboard::DeleteBackspace, + Keyboard::NoEventIndicated, + Keyboard::RightAlt, + ], + [ // Function layer 2 + Keyboard::F11, + Keyboard::F12, + Keyboard::F13, + Keyboard::F14, + Keyboard::F15, + Keyboard::F16, + Keyboard::Grave, + Keyboard::NoEventIndicated, + Keyboard::LeftGUI, + Keyboard::NoEventIndicated, + Keyboard::CapsLock, + Keyboard::DeleteBackspace, + Keyboard::LeftControl, + Keyboard::NoEventIndicated, + Keyboard::NoEventIndicated, + Keyboard::F17, + Keyboard::F18, + Keyboard::F19, + Keyboard::LeftArrow, + Keyboard::DownArrow, + Keyboard::UpArrow, + Keyboard::RightArrow, + Keyboard::DeleteForward, + Keyboard::ReturnEnter, + Keyboard::LeftShift, + Keyboard::F20, + Keyboard::F21, + Keyboard::F22, + Keyboard::F23, + Keyboard::F24, + Keyboard::Home, + Keyboard::PageDown, + Keyboard::PageUp, + Keyboard::End, + Keyboard::Insert, + Keyboard::RightShift, + Keyboard::LeftAlt, + Keyboard::NoEventIndicated, + Keyboard::LeftGUI, + Keyboard::DeleteBackspace, + Keyboard::NoEventIndicated, + Keyboard::RightAlt, + ], ]; let mut input_count_down = timer.count_down(); @@ -114,19 +290,34 @@ fn main() -> ! { let color_purple: RGB8 = (0, 10, 10).into(); let color_red: RGB8 = (0, 10, 0).into(); - // let color_green: RGB8 = (10, 0, 0).into(); - // let color_blue: RGB8 = (0, 0, 10).into(); let color_none: RGB8 = (0, 0, 0).into(); + init_keyboard_matrix_pins(matrix_cols, &mut delay); + // Infinite colour wheel loop loop { if input_count_down.wait().is_ok() { - match keyboard.device().write_report([Keyboard::NoEventIndicated; 12]) { + // Scan keyboard matrix + let pressed_keys = get_pressed_keys(matrix_rows, matrix_cols, &mut delay); + + // Get current function layer + let fn_mode = get_fn_mode(pressed_keys); + + // Copy result from scanned keys to matrix struct + for (index, key) in pressed_keys.iter().enumerate() { + matrix_keys[index].current_state = *key; + } + + // Generate keyboard report + let keyboard_report = + get_keyboard_report(matrix_keys, layout, fn_mode); + + match keyboard.device().write_report(keyboard_report) { Err(UsbHidError::WouldBlock) => {} Err(UsbHidError::Duplicate) => {} Ok(_) => {} Err(e) => { - ws.write([color_red].iter().copied()).unwrap(); + status_led.write([color_red].iter().copied()).unwrap(); core::panic!("Failed to write keyboard report: {:?}", e) } }; @@ -138,7 +329,7 @@ fn main() -> ! { Err(UsbHidError::WouldBlock) => {} Ok(_) => {} Err(e) => { - ws.write([color_red].iter().copied()).unwrap(); + status_led.write([color_red].iter().copied()).unwrap(); core::panic!("Failed to process keyboard tick: {:?}", e) } }; @@ -150,17 +341,99 @@ fn main() -> ! { //do nothing } Err(e) => { - ws.write([color_red].iter().copied()).unwrap(); + status_led.write([color_red].iter().copied()).unwrap(); core::panic!("Failed to read keyboard report: {:?}", e) } Ok(leds) => { if leds.caps_lock == true { - ws.write([color_purple].iter().copied()).unwrap(); + status_led.write([color_purple].iter().copied()).unwrap(); } else { - ws.write([color_none].iter().copied()).unwrap(); + status_led.write([color_none].iter().copied()).unwrap(); } } } } } } + +// Initialise keyboard matrix pins +fn init_keyboard_matrix_pins( + cols: &mut [&mut dyn OutputPin], + delay: &mut Delay, +) { + for col in cols.iter_mut() { + col.set_high().unwrap(); + } + delay.delay_us(10); +} + +// Scan keyboard matrix for pressed keys and return a bool array +// representing the state of each key (true = pressed) +// TODO: This is a bit of a mess, needs refactoring +fn get_pressed_keys( + rows: &[&dyn InputPin], + cols: &mut [&mut dyn OutputPin], + delay: &mut Delay, +) -> [bool; NUMBER_OF_KEYS] { + // Scan keyboard matrix for pressed keys + let mut pressed_keys: [bool; NUMBER_OF_KEYS] = [false; NUMBER_OF_KEYS]; + let mut key_index: usize = 0; + for (col_index, col) in cols.iter_mut().enumerate() { + col.set_low().unwrap(); + delay.delay_us(10); + for (row_index, row) in rows.iter().enumerate() { + if col_index == 3 + && (row_index == 0 + || row_index == 1 + || row_index == 2 + || row_index == 9 + || row_index == 10 + || row_index == 11) + { + continue; + } + if row.is_low().unwrap() { + pressed_keys[key_index] = true; + } + key_index += 1; + } + col.set_high().unwrap(); + delay.delay_us(10); + } + // Return scan result + pressed_keys +} + +// Get current Fn mode (0, 1 or 2) +fn get_fn_mode(pressed_keys: [bool; NUMBER_OF_KEYS]) -> u8 { + // Check Fn mode + let mut fn_mode: u8 = 0; + if pressed_keys[37] == true && pressed_keys[40] == true { + fn_mode = 2; + } else if pressed_keys[37] == true || pressed_keys[40] == true { + fn_mode = 1; + } + fn_mode +} + +// Generate keyboard report based on pressed keys and Fn mode (0, 1 or 2) +fn get_keyboard_report( + mut matrix_keys: [MatrixKey; NUMBER_OF_KEYS], + layout: [[Keyboard; NUMBER_OF_KEYS]; 3], + fn_mode: u8, +) -> [Keyboard; NUMBER_OF_KEYS] { + // Create default report + let mut keyboard_report: [Keyboard; NUMBER_OF_KEYS] = + [Keyboard::NoEventIndicated; NUMBER_OF_KEYS]; + // Filter report based on Fn mode and pressed keys + for (index, key) in matrix_keys.iter_mut().enumerate() { + if key.current_state != key.previous_state && key.current_state == true { + key.fn_mode = fn_mode; + } + if key.current_state == true { + keyboard_report[index] = layout[index][usize::from(key.fn_mode)]; + } + } + // Return report + keyboard_report +}