diff --git a/src/display.rs b/src/display.rs index 60d4653..9ae1926 100644 --- a/src/display.rs +++ b/src/display.rs @@ -36,7 +36,7 @@ pub fn init_display(bus: I2c<'static, embassy_rp::peripherals::I2C0, embassy_rp: /// Temp function which updates the display with currently pressed keys pub fn update_display( display: &mut Option, - pressed_keys: &[(usize, usize, crate::keymap::KeyCode)], + pressed_keys: &[(usize, usize, crate::keymap::Action)], ) -> Option<()> { if let Some(display) = display { display.clear(BinaryColor::Off).ok()?; @@ -54,7 +54,7 @@ pub fn update_display( let mut y_pos = 0; for (row_idx, col_idx, keycode) in pressed_keys.iter().take(3) { let mut msg = heapless::String::<32>::new(); - write!(&mut msg, "R{}C{}: 0x{:02X}", row_idx, col_idx, keycode.as_u8()).ok(); + write!(&mut msg, "R{}C{}: 0x{:?}", row_idx, col_idx, keycode).ok(); Text::with_baseline(&msg, Point::new(0, y_pos), text_style, Baseline::Top) .draw(display) diff --git a/src/keymap.rs b/src/keymap.rs index 37eb94b..69a79f5 100644 --- a/src/keymap.rs +++ b/src/keymap.rs @@ -2,11 +2,27 @@ /// Reference: https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf /// Section 10: Keyboard/Keypad Page (0x07) -#[allow(dead_code)] +static N_LAYERS: usize = 4; +static COLS: usize = 12; +static ROWS: usize = 4; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Action { + Key(HidKey), // normal key press + Layer(LayerOperation), // layer modifier key press + None, // do nothing + Trans, // fall back to the default keymap +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LayerOperation { + MO(usize) // momentary (hold to switch to the layer) +} + +#[allow(dead_code)] #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum KeyCode { +pub enum HidKey { No = 0x00, // Letters @@ -108,65 +124,142 @@ pub enum KeyCode { RightMeta = 0xE7, } -impl KeyCode { +impl HidKey { pub const fn as_u8(self) -> u8 { self as u8 } pub const fn is_modifier(self) -> bool { matches!(self, - KeyCode::LeftCtrl | KeyCode::LeftShift | KeyCode::LeftAlt | KeyCode::LeftMeta | - KeyCode::RightCtrl | KeyCode::RightShift | KeyCode::RightAlt | KeyCode::RightMeta + HidKey::LeftCtrl | HidKey::LeftShift | HidKey::LeftAlt | HidKey::LeftMeta | + HidKey::RightCtrl | HidKey::RightShift | HidKey::RightAlt | HidKey::RightMeta ) } pub const fn modifier_bit(self) -> u8 { match self { - KeyCode::LeftCtrl => 0x01, - KeyCode::LeftShift => 0x02, - KeyCode::LeftAlt => 0x04, - KeyCode::LeftMeta => 0x08, - KeyCode::RightCtrl => 0x10, - KeyCode::RightShift => 0x20, - KeyCode::RightAlt => 0x40, // AltGr - KeyCode::RightMeta => 0x80, + HidKey::LeftCtrl => 0x01, + HidKey::LeftShift => 0x02, + HidKey::LeftAlt => 0x04, + HidKey::LeftMeta => 0x08, + HidKey::RightCtrl => 0x10, + HidKey::RightShift => 0x20, + HidKey::RightAlt => 0x40, // AltGr + HidKey::RightMeta => 0x80, _ => 0, } } } /// Keymap for my 4x12 ortholinear keyboard -/// Each position [row][col] maps to a USB HID scancode -pub const KEYMAP: [[KeyCode; 12]; 4] = [ +/// Each position [row][col] on each layer maps to an action +pub const KEYMAPS: [[[Action; COLS]; ROWS]; N_LAYERS] = [ [ - KeyCode::Escape, KeyCode::Q, KeyCode::W, KeyCode::E, - KeyCode::R, KeyCode::T, KeyCode::Y, KeyCode::U, - KeyCode::I, KeyCode::O, KeyCode::P, KeyCode::Backspace, + // base layer + [ + Action::Key(HidKey::Escape), Action::Key(HidKey::Q), Action::Key(HidKey::W), Action::Key(HidKey::E), + Action::Key(HidKey::R), Action::Key(HidKey::T), Action::Key(HidKey::Y), Action::Key(HidKey::U), + Action::Key(HidKey::I), Action::Key(HidKey::O), Action::Key(HidKey::P), Action::Key(HidKey::Backspace), + ], + [ + Action::Key(HidKey::Tab), Action::Key(HidKey::A), Action::Key(HidKey::S), Action::Key(HidKey::D), + Action::Key(HidKey::F), Action::Key(HidKey::G), Action::Key(HidKey::H), Action::Key(HidKey::J), + Action::Key(HidKey::K), Action::Key(HidKey::L), Action::Key(HidKey::Semicolon), Action::Key(HidKey::Enter), + ], + [ + Action::Key(HidKey::LeftShift), Action::Key(HidKey::Z), Action::Key(HidKey::X), Action::Key(HidKey::C), + Action::Key(HidKey::V), Action::Key(HidKey::B), Action::Key(HidKey::N), Action::Key(HidKey::M), + Action::Key(HidKey::Comma), Action::Key(HidKey::Dot), Action::Key(HidKey::Up), Action::Key(HidKey::Slash), + ], + [ + Action::Key(HidKey::LeftCtrl), Action::Layer(LayerOperation::MO(3)), Action::Key(HidKey::LeftMeta), Action::Key(HidKey::LeftAlt), + Action::Layer(LayerOperation::MO(1)), Action::Key(HidKey::Space), Action::Key(HidKey::No), Action::Layer(LayerOperation::MO(2)), + Action::Key(HidKey::RightAlt), Action::Key(HidKey::Left), Action::Key(HidKey::Down), Action::Key(HidKey::Right), + ], ], + // layer 1 (numbers mostly) [ - KeyCode::Tab, KeyCode::A, KeyCode::S, KeyCode::D, - KeyCode::F, KeyCode::G, KeyCode::H, KeyCode::J, - KeyCode::K, KeyCode::L, KeyCode::Semicolon, KeyCode::Enter, + [ + Action::Key(HidKey::Grave), Action::Key(HidKey::Kb1), Action::Key(HidKey::Kb2), Action::Key(HidKey::Kb3), + Action::Key(HidKey::Kb4), Action::Key(HidKey::Kb5), Action::Key(HidKey::Kb6), Action::Key(HidKey::Kb7), + Action::Key(HidKey::Kb8), Action::Key(HidKey::Kb9), Action::Key(HidKey::Kb0), Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Key(HidKey::RightShift), + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + ], ], + // layer 2 (additional keys missing from the kb) [ - KeyCode::LeftShift, KeyCode::Z, KeyCode::X, KeyCode::C, - KeyCode::V, KeyCode::B, KeyCode::N, KeyCode::M, - KeyCode::Comma, KeyCode::Dot, KeyCode::Up, KeyCode::Slash, + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Key(HidKey::LeftBracket), Action::Key(HidKey::RightBracket), Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Key(HidKey::Minus), Action::Key(HidKey::Equal), Action::Key(HidKey::Quote), Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Key(HidKey::RightShift), + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + ], ], + // layer 3 (fn key layer, with f* keys and home/end/pgup/pgdown) [ - KeyCode::LeftCtrl, KeyCode::No, KeyCode::LeftMeta, KeyCode::LeftAlt, - KeyCode::No, KeyCode::Space, KeyCode::No, KeyCode::No, - KeyCode::RightAlt, KeyCode::Left, KeyCode::Down, KeyCode::Right, + [ + Action::Key(HidKey::F1), Action::Key(HidKey::F2), Action::Key(HidKey::F3), Action::Key(HidKey::F4), + Action::Key(HidKey::F5), Action::Key(HidKey::F6), Action::Key(HidKey::F7), Action::Key(HidKey::F8), + Action::Key(HidKey::F9), Action::Key(HidKey::F10), Action::Key(HidKey::F11), Action::Key(HidKey::F12), + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Key(HidKey::PageUp), Action::Trans, + ], + [ + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Trans, Action::Trans, Action::Trans, + Action::Trans, Action::Key(HidKey::Home), Action::Key(HidKey::PageDown), Action::Key(HidKey::End), + ], ], ]; -/// Get keycode from given row and column -pub fn get_keycode(row: usize, col: usize) -> Option { - if row < 4 && col < 12 { - let keycode = KEYMAP[row][col]; - if keycode != KeyCode::No { - return Some(keycode); +/// Get action from given row and column +pub fn get_action(row: usize, col: usize, layer: usize) -> Action { + if row < ROWS && col < COLS && layer < N_LAYERS { + let action = KEYMAPS[layer][row][col]; + + // handle transparent keys, in this case it should fall down to the first layer without transparent key + if matches!(action, Action::Trans) && layer > 0 { + return get_action(row, col, layer - 1); } + + action + } else { + Action::None } - None } diff --git a/src/main.rs b/src/main.rs index cd5207c..deb5fea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,9 +17,9 @@ use embassy_rp::{ }; use embassy_time::{Duration, Timer}; use usbd_hid::descriptor::KeyboardReport; -use {defmt_rtt as _, panic_probe as _}; +use crate::keymap::{Action, LayerOperation, get_action}; -use keymap::get_keycode; +use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { I2C0_IRQ => I2cInterruptHandler; @@ -68,18 +68,45 @@ async fn main(_spawner: Spawner) -> () { let in_fut = async { let mut previous_keycodes: [u8; 6] = [0; 6]; let mut previous_modifier: u8 = 0; + let mut active_layer: usize = 0; loop { let scan_result = matrix.scan().await; - // Collect all pressed keys and their scancodes - let mut pressed_keys: heapless::Vec<(usize, usize, keymap::KeyCode), 48> = heapless::Vec::new(); + // first pass to check if the layer keys are active + let mut layer_active = false; for (row_idx, row) in scan_result.iter().enumerate() { for (col_idx, &is_pressed) in row.iter().enumerate() { if is_pressed { - if let Some(keycode) = get_keycode(row_idx, col_idx) { - let _ = pressed_keys.push((row_idx, col_idx, keycode)); + // try to find if any of the pressed keys on the 0th layer is a layer modify key + let action = get_action(row_idx, col_idx, 0); + if let Action::Layer(LayerOperation::MO(layer)) = action { + layer_active = true; + active_layer = layer; + break; + } + } + } + // break the loop early if layer key is pressed + if layer_active { + break; + } + } + + if !layer_active { + active_layer = 0; + } + + // Collect all pressed keys and their scancodes + let mut pressed_keys: heapless::Vec<(usize, usize, keymap::Action), 48> = heapless::Vec::new(); + + for (row_idx, row) in scan_result.iter().enumerate() { + for (col_idx, &is_pressed) in row.iter().enumerate() { + if is_pressed { + let action = get_action(row_idx, col_idx, active_layer); + if !matches!(action, Action::None | Action::Layer(_)) { + let _ = pressed_keys.push((row_idx, col_idx, action)); } } } @@ -90,14 +117,16 @@ async fn main(_spawner: Spawner) -> () { let mut keycodes = [0u8; 6]; let mut keycode_index = 0; - for (_, _, keycode) in pressed_keys.iter() { - if keycode.is_modifier() { - // Add to modifier byte - modifier |= keycode.modifier_bit(); - } else if keycode_index < 6 { - // Add to keycodes array (max 6 regular keys) - keycodes[keycode_index] = keycode.as_u8(); - keycode_index += 1; + for (_, _, action) in pressed_keys.iter() { + if let Action::Key(hid_key) = action { + if hid_key.is_modifier() { + // Add to modifier byte + modifier |= hid_key.modifier_bit(); + } else if keycode_index < 6 { + // Add to keycodes array (max 6 regular keys) + keycodes[keycode_index] = hid_key.as_u8(); + keycode_index += 1; + } } }