From 24de6a5109a656d0cf8b1a556854e126f3f7e132 Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Mon, 19 Jun 2023 22:43:59 +0200 Subject: [PATCH] Splitted out layout file --- rp2040/src/layout.rs | 171 +++++++++++++++++++++++++++++ rp2040/src/main.rs | 250 ++++++++++--------------------------------- 2 files changed, 229 insertions(+), 192 deletions(-) create mode 100644 rp2040/src/layout.rs diff --git a/rp2040/src/layout.rs b/rp2040/src/layout.rs new file mode 100644 index 0000000..72db05c --- /dev/null +++ b/rp2040/src/layout.rs @@ -0,0 +1,171 @@ +// Button index map: +// ------------------------------------- ------------------------------------- +// | 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 |------------------ +// ------------------- ------------------- +// +// Swedish keymap conversion table: +// US Swedish +// -------------------------- +// Grave § +// Semicolon ö +// Apostrophe ä +// LeftBrace å +// ForwardSlash - +// NonUSBackslash < +// Equal ´ +// Backslash ' +// RightBrace ^ +// Minus + +// LeftAlt Alt +// RightAlt AltGr + +use crate::NUMBER_OF_KEYS; +use usbd_human_interface_device::page::Keyboard; + +// Function (Fn) buttons index (need two buttons) +pub const FN_BUTTONS: [u8; 2] = [37, 40]; + +// Button map to HID key (three Function layers) +pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [ + [ + // Function layer 0 + // HID Key // Button Index + Keyboard::Tab, // 0 + Keyboard::Q, // 1 + Keyboard::W, // 2 + Keyboard::E, // 3 + Keyboard::R, // 4 + Keyboard::T, // 5 + Keyboard::Y, // 6 + Keyboard::U, // 7 + Keyboard::I, // 8 + Keyboard::O, // 9 + Keyboard::P, // 10 + Keyboard::LeftBrace, // 11 // Å + Keyboard::LeftControl, // 12 + Keyboard::A, // 13 + Keyboard::S, // 14 + Keyboard::D, // 15 + Keyboard::F, // 16 + Keyboard::G, // 17 + Keyboard::H, // 18 + Keyboard::J, // 19 + Keyboard::K, // 20 + Keyboard::L, // 21 + Keyboard::Semicolon, // 22 // Ö + Keyboard::Apostrophe, // 23 // Ä + Keyboard::LeftShift, // 24 + Keyboard::Z, // 25 + Keyboard::X, // 26 + Keyboard::C, // 27 + Keyboard::V, // 28 + Keyboard::B, // 29 + Keyboard::N, // 30 + Keyboard::M, // 31 + Keyboard::Comma, // 32 + Keyboard::Dot, // 33 + Keyboard::ForwardSlash, // 34 // - + Keyboard::RightShift, // 35 + Keyboard::LeftAlt, // 36 + Keyboard::NoEventIndicated, // 37 // Fn + Keyboard::Space, // 38 + Keyboard::Space, // 39 + Keyboard::NoEventIndicated, // 40 // Fn + Keyboard::RightAlt, // 41 + ], + [ + // Function layer 1 + // HID Key // Button Index + Keyboard::Escape, // 0 + Keyboard::F1, // 1 + Keyboard::F2, // 2 + Keyboard::F3, // 3 + Keyboard::F4, // 4 + Keyboard::F5, // 5 + Keyboard::F6, // 6 + Keyboard::F7, // 7 + Keyboard::F8, // 8 + Keyboard::F9, // 9 + Keyboard::F10, // 10 + Keyboard::DeleteBackspace, // 11 + Keyboard::LeftControl, // 12 + Keyboard::Keyboard1, // 13 + Keyboard::Keyboard2, // 14 + Keyboard::Keyboard3, // 15 + Keyboard::Keyboard4, // 16 + Keyboard::Keyboard5, // 17 + Keyboard::Keyboard6, // 18 + Keyboard::Keyboard7, // 19 + Keyboard::Keyboard8, // 20 + Keyboard::Keyboard9, // 21 + Keyboard::Keyboard0, // 22 + Keyboard::ReturnEnter, // 23 + Keyboard::LeftShift, // 24 + Keyboard::Keyboard6, // 25 + Keyboard::Keyboard7, // 26 + Keyboard::Keyboard8, // 27 + Keyboard::Keyboard9, // 28 + Keyboard::Keyboard0, // 29 + Keyboard::NonUSBackslash, // 30 // < + Keyboard::Equal, // 31 // ´ + Keyboard::Backslash, // 32 // ' + Keyboard::RightBrace, // 33 // ^ + Keyboard::Minus, // 34 // + + Keyboard::RightShift, // 35 + Keyboard::LeftAlt, // 36 + Keyboard::NoEventIndicated, // 37 // Fn + Keyboard::DeleteBackspace, // 38 + Keyboard::DeleteBackspace, // 39 + Keyboard::NoEventIndicated, // 40// Fn + Keyboard::RightAlt, // 41 + ], + [ + // Function layer 2 + // HID Key // Button Index + Keyboard::F11, // 0 + Keyboard::F12, // 1 + Keyboard::F13, // 2 + Keyboard::F14, // 3 + Keyboard::F15, // 4 + Keyboard::F16, // 5 + Keyboard::Grave, // 6 // § + Keyboard::NoEventIndicated, // 7 + Keyboard::LeftGUI, // 8 + Keyboard::NoEventIndicated, // 9 + Keyboard::CapsLock, // 10 + Keyboard::DeleteBackspace, // 11 + Keyboard::LeftControl, // 12 + Keyboard::NoEventIndicated, // 13 + Keyboard::NoEventIndicated, // 14 + Keyboard::F17, // 15 + Keyboard::F18, // 16 + Keyboard::F19, // 17 + Keyboard::LeftArrow, // 18 + Keyboard::DownArrow, // 19 + Keyboard::UpArrow, // 20 + Keyboard::RightArrow, // 21 + Keyboard::DeleteForward, // 22 + Keyboard::ReturnEnter, // 23 + Keyboard::LeftShift, // 24 + Keyboard::F20, // 25 + Keyboard::F21, // 26 + Keyboard::F22, // 27 + Keyboard::F23, // 28 + Keyboard::F24, // 29 + Keyboard::Home, // 30 + Keyboard::PageDown, // 31 + Keyboard::PageUp, // 32 + Keyboard::End, // 33 + Keyboard::Insert, // 34 + Keyboard::RightShift, // 35 + Keyboard::LeftAlt, // 36 + Keyboard::NoEventIndicated, // 37 // Fn + Keyboard::LeftGUI, // 38 + Keyboard::DeleteBackspace, // 39 + Keyboard::NoEventIndicated, // 40 // Fn + Keyboard::RightAlt, // 41 + ], +]; diff --git a/rp2040/src/main.rs b/rp2040/src/main.rs index aa4f73e..77e205a 100644 --- a/rp2040/src/main.rs +++ b/rp2040/src/main.rs @@ -1,6 +1,12 @@ +// TODO: Add license header +// TODO: Add documentation header +// TODO: GUI lock button support + #![no_std] #![no_main] +mod layout; + use core::convert::Infallible; use cortex_m::delay::Delay; use embedded_hal::digital::v2::*; @@ -31,13 +37,13 @@ pub const KEY_COLS: usize = 12; pub const NUMBER_OF_KEYS: usize = 42; #[derive(Copy, Clone)] -struct MatrixKey { +struct ButtonMatrix { current_state: bool, previous_state: bool, fn_mode: u8, } -impl MatrixKey { +impl ButtonMatrix { fn default() -> Self { Self { current_state: false, @@ -106,16 +112,17 @@ fn main() -> ! { timer.count_down(), ); - let mut matrix_keys: [MatrixKey; NUMBER_OF_KEYS] = [MatrixKey::default(); NUMBER_OF_KEYS]; + let mut button_matrix: [ButtonMatrix; NUMBER_OF_KEYS] = + [ButtonMatrix::default(); NUMBER_OF_KEYS]; - let matrix_rows: &[&dyn InputPin] = &[ + let button_matrix_row_pins: &[&dyn InputPin] = &[ &pins.gp0.into_pull_up_input(), &pins.gp1.into_pull_up_input(), &pins.gp29.into_pull_up_input(), &pins.gp28.into_pull_up_input(), ]; - let matrix_cols: &mut [&mut dyn OutputPin] = &mut [ + let button_matrix_col_pins: &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(), @@ -130,169 +137,16 @@ fn main() -> ! { &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(); - input_count_down.start(10.millis()); + let mut report_count_down = timer.count_down(); + report_count_down.start(10.millis()); let mut tick_count_down = timer.count_down(); tick_count_down.start(1.millis()); + let mut indicator_count_down = timer.count_down(); + indicator_count_down.start(250.millis()); + + let mut status_led_onoff: bool = false; let status_led_color: [RGB8; 5] = [ (0, 0, 0).into(), // Off (10, 7, 0).into(), // Green @@ -301,38 +155,52 @@ fn main() -> ! { (2, 20, 0).into(), // Red ]; - let mut caps_lock_active = false; + let mut caps_lock_active: bool = false; + let mut fn_mode: u8 = 0; - init_keyboard_matrix_pins(matrix_cols, &mut delay); + // Set all column pins to output and high + init_button_matrix_pins(button_matrix_col_pins, &mut delay); - // Infinite colour wheel loop loop { - if input_count_down.wait().is_ok() { - // 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); - + if indicator_count_down.wait().is_ok() { // Set status LED colour based on function layer and capslock - // 0 = green, 1 = blue, 2 = orange, capslock active = red. - if caps_lock_active == true { + // 0 = green, 1 = blue, 2 = orange, capslock active = flashing. + if caps_lock_active == true && status_led_onoff == true { status_led - .write([status_led_color[4]].iter().copied()) + .write([status_led_color[0]].iter().copied()) .unwrap(); + status_led_onoff = false; } else { status_led .write([status_led_color[usize::from(fn_mode) + 1]].iter().copied()) .unwrap(); + status_led_onoff = true; } + } + if report_count_down.wait().is_ok() { + // Scan keyboard matrix + let pressed_keys = + get_pressed_buttons(button_matrix_row_pins, button_matrix_col_pins, &mut delay); + + // Get current function layer + fn_mode = get_fn_mode(pressed_keys); + + // Set status LED colour based on function layer and capslock + // 0 = green, 1 = blue, 2 = orange, capslock active = flashing. + if caps_lock_active == false { + status_led + .write([status_led_color[usize::from(fn_mode) + 1]].iter().copied()) + .unwrap(); + status_led_onoff = true; + } // Copy result from scanned keys to matrix struct for (index, key) in pressed_keys.iter().enumerate() { - matrix_keys[index].current_state = *key; + button_matrix[index].current_state = *key; } // Generate keyboard report - let keyboard_report = get_keyboard_report(matrix_keys, layout, fn_mode); + let keyboard_report = get_keyboard_report(&mut button_matrix, layout::MAP, fn_mode); match keyboard.device().write_report(keyboard_report) { Err(UsbHidError::WouldBlock) => {} @@ -376,10 +244,7 @@ fn main() -> ! { } // Initialise keyboard matrix pins -fn init_keyboard_matrix_pins( - cols: &mut [&mut dyn OutputPin], - delay: &mut Delay, -) { +fn init_button_matrix_pins(cols: &mut [&mut dyn OutputPin], delay: &mut Delay) { for col in cols.iter_mut() { col.set_high().unwrap(); } @@ -389,7 +254,7 @@ fn init_keyboard_matrix_pins( // 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( +fn get_pressed_buttons( rows: &[&dyn InputPin], cols: &mut [&mut dyn OutputPin], delay: &mut Delay, @@ -425,18 +290,18 @@ fn get_pressed_keys( 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; + for button_id in layout::FN_BUTTONS.iter() { + if pressed_keys[usize::from(*button_id)] == 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], + matrix_keys: &mut [ButtonMatrix; NUMBER_OF_KEYS], + layout_map: [[Keyboard; NUMBER_OF_KEYS]; 3], fn_mode: u8, ) -> [Keyboard; NUMBER_OF_KEYS] { // Create default report @@ -445,11 +310,12 @@ fn get_keyboard_report( // 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.previous_state = key.current_state; key.fn_mode = fn_mode; } + key.previous_state = key.current_state; + if key.current_state == true { - keyboard_report[index] = layout[usize::from(key.fn_mode)][index]; + keyboard_report[index] = layout_map[usize::from(key.fn_mode)][index]; } } // Return report