Skip to content

Commit

Permalink
Simplify the keymap definition (#56)
Browse files Browse the repository at this point in the history
* Use const generics for arrays holding the row and column pins

* Simplify the keymap definition
  • Loading branch information
bschwind authored Jun 21, 2024
1 parent 6ed6f73 commit b61d705
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 41 deletions.
49 changes: 18 additions & 31 deletions firmware/src/key_mapping.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
use crate::{key_codes::KeyCode, NUM_COLS, NUM_ROWS};
use crate::{
key_codes::KeyCode::{self, *},
NUM_COLS, NUM_ROWS,
};

#[rustfmt::skip]
pub const NORMAL_LAYER_MAPPING: [[KeyCode; NUM_ROWS]; NUM_COLS] = [
[KeyCode::Escape, KeyCode::Tilde, KeyCode::Tab, KeyCode::CapsLock, KeyCode::LeftShift, KeyCode::Fn],
[KeyCode::F1, KeyCode::Num1, KeyCode::Q, KeyCode::A, KeyCode::Empty, KeyCode::LeftCtrl],
[KeyCode::F2, KeyCode::Num2, KeyCode::W, KeyCode::S, KeyCode::Z, KeyCode::LeftAlt],
[KeyCode::F3, KeyCode::Num3, KeyCode::E, KeyCode::D, KeyCode::X, KeyCode::LeftCmd],
[KeyCode::F4, KeyCode::Num4, KeyCode::R, KeyCode::F, KeyCode::C, KeyCode::Empty],
[KeyCode::F5, KeyCode::Num5, KeyCode::T, KeyCode::G, KeyCode::V, KeyCode::Empty],
[KeyCode::Empty, KeyCode::Num6, KeyCode::Y, KeyCode::H, KeyCode::B, KeyCode::Space],
[KeyCode::F6, KeyCode::Num7, KeyCode::U, KeyCode::J, KeyCode::N, KeyCode::Empty],
[KeyCode::F7, KeyCode::Num8, KeyCode::I, KeyCode::K, KeyCode::M, KeyCode::Empty],
[KeyCode::F8, KeyCode::Num9, KeyCode::O, KeyCode::L, KeyCode::Comma, KeyCode::Empty],
[KeyCode::F9, KeyCode::Num0, KeyCode::P, KeyCode::Semicolon, KeyCode::Period, KeyCode::RightCmd],
[KeyCode::F10, KeyCode::Minus, KeyCode::LeftSquareBracket, KeyCode::SingleQuote, KeyCode::ForwardSlash, KeyCode::Left],
[KeyCode::F11, KeyCode::Equals, KeyCode::RightSquareBracket, KeyCode::Enter, KeyCode::Up, KeyCode::Down],
[KeyCode::F12, KeyCode::Backspace, KeyCode::BackSlash, KeyCode::Empty, KeyCode::Empty, KeyCode::Right],
pub const NORMAL_LAYER_MAPPING: [[KeyCode; NUM_COLS]; NUM_ROWS] = [
[Escape, F1, F2, F3, F4, F5, Empty, F6, F7, F8, F9, F10, F11, F12],
[Tilde, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, Minus, Equals, Backspace],
[Tab, Q, W, E, R, T, Y, U, I, O, P, LeftSquareBracket, RightSquareBracket, BackSlash],
[CapsLock, A, S, D, F, G, H, J, K, L, Semicolon, SingleQuote, Enter, Empty],
[LeftShift, Empty, Z, X, C, V, B, N, M, Comma, Period, ForwardSlash, Up, Empty],
[Fn, LeftCtrl, LeftAlt, LeftCmd, Empty, Empty, Space, Empty, Empty, Empty, RightCmd, Left, Down, Right],
];

#[rustfmt::skip]
pub const FN_LAYER_MAPPING: [[KeyCode; NUM_ROWS]; NUM_COLS] = [
[KeyCode::Escape, KeyCode::Tilde, KeyCode::Tab, KeyCode::CapsLock, KeyCode::LeftShift, KeyCode::Empty],
[KeyCode::F1, KeyCode::Num1, KeyCode::Q, KeyCode::A, KeyCode::Empty, KeyCode::LeftCtrl],
[KeyCode::F2, KeyCode::Num2, KeyCode::W, KeyCode::S, KeyCode::Z, KeyCode::LeftAlt],
[KeyCode::F3, KeyCode::Num3, KeyCode::E, KeyCode::D, KeyCode::X, KeyCode::LeftCmd],
[KeyCode::F4, KeyCode::Num4, KeyCode::R, KeyCode::F, KeyCode::C, KeyCode::Empty],
[KeyCode::F5, KeyCode::Num5, KeyCode::T, KeyCode::G, KeyCode::V, KeyCode::Empty],
[KeyCode::Empty, KeyCode::Num6, KeyCode::Y, KeyCode::H, KeyCode::B, KeyCode::Space],
[KeyCode::F6, KeyCode::Num7, KeyCode::U, KeyCode::J, KeyCode::N, KeyCode::Empty],
[KeyCode::F7, KeyCode::Num8, KeyCode::I, KeyCode::K, KeyCode::M, KeyCode::Empty],
[KeyCode::F8, KeyCode::Num9, KeyCode::O, KeyCode::L, KeyCode::Comma, KeyCode::Empty],
[KeyCode::F9, KeyCode::Num0, KeyCode::P, KeyCode::Semicolon, KeyCode::Period, KeyCode::RightCmd],
[KeyCode::VolumeMute, KeyCode::Minus, KeyCode::LeftSquareBracket, KeyCode::SingleQuote, KeyCode::ForwardSlash, KeyCode::Left],
[KeyCode::VolumeDown, KeyCode::Equals, KeyCode::RightSquareBracket, KeyCode::Enter, KeyCode::Up, KeyCode::Down],
[KeyCode::VolumeUp, KeyCode::Backspace, KeyCode::BackSlash, KeyCode::Empty, KeyCode::Empty, KeyCode::Right],
pub const FN_LAYER_MAPPING: [[KeyCode; NUM_COLS]; NUM_ROWS] = [
[Escape, F1, F2, F3, F4, F5, Empty, F6, F7, F8, F9, VolumeMute, VolumeDown, VolumeUp],
[Tilde, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, Minus, Equals, Backspace],
[Tab, Q, W, E, R, T, Y, U, I, O, P, LeftSquareBracket, RightSquareBracket, BackSlash],
[CapsLock, A, S, D, F, G, H, J, K, L, Semicolon, SingleQuote, Enter, Empty],
[LeftShift, Empty, Z, X, C, V, B, N, M, Comma, Period, ForwardSlash, Up, Empty],
[Empty, LeftCtrl, LeftAlt, LeftCmd, Empty, Empty, Space, Empty, Empty, Empty, RightCmd, Left, Down, Right],
];
42 changes: 37 additions & 5 deletions firmware/src/key_scan.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::{
key_mapping::{FN_LAYER_MAPPING, NORMAL_LAYER_MAPPING},
NUM_COLS, NUM_ROWS,
};
use core::{convert::Infallible, ops::Deref};

use cortex_m::delay::Delay;
use embedded_hal::digital::v2::InputPin;
use usbd_hid::descriptor::KeyboardReport;

use crate::{debounce::Debounce, key_codes::KeyCode, key_mapping};
use crate::{debounce::Debounce, key_codes::KeyCode};

#[derive(Clone, Copy)]
pub struct KeyScan<const NUM_ROWS: usize, const NUM_COLS: usize> {
Expand All @@ -21,8 +25,8 @@ impl<const NUM_ROWS: usize, const NUM_COLS: usize> Deref for KeyScan<NUM_ROWS, N

impl<const NUM_ROWS: usize, const NUM_COLS: usize> KeyScan<NUM_ROWS, NUM_COLS> {
pub fn scan(
rows: &[&dyn InputPin<Error = Infallible>],
columns: &mut [&mut dyn embedded_hal::digital::v2::OutputPin<Error = Infallible>],
rows: [&dyn InputPin<Error = Infallible>; NUM_ROWS],
columns: &mut [&mut dyn embedded_hal::digital::v2::OutputPin<Error = Infallible>; NUM_COLS],
delay: &mut Delay,
debounce: &mut Debounce<NUM_ROWS, NUM_COLS>,
) -> Self {
Expand Down Expand Up @@ -61,11 +65,11 @@ impl<const NUM_ROWS: usize, const NUM_COLS: usize> From<KeyScan<NUM_ROWS, NUM_CO
};

// First scan for any function keys being pressed
let mut layer_mapping = key_mapping::NORMAL_LAYER_MAPPING;
let mut layer_mapping = TRANSPOSED_NORMAL_LAYER_MAPPING;
for (matrix_column, mapping_column) in scan.matrix.iter().zip(layer_mapping) {
for (key_pressed, mapping_row) in matrix_column.iter().zip(mapping_column) {
if mapping_row == KeyCode::Fn && *key_pressed {
layer_mapping = key_mapping::FN_LAYER_MAPPING;
layer_mapping = TRANSPOSED_FN_LAYER_MAPPING;
}
}
}
Expand All @@ -86,3 +90,31 @@ impl<const NUM_ROWS: usize, const NUM_COLS: usize> From<KeyScan<NUM_ROWS, NUM_CO
KeyboardReport { modifier, reserved: 0, leds: 0, keycodes }
}
}

// We need the key mappings to be transposed because the key mapping is
// defined as [[KeyCode; NUM_COLS]; NUM_ROWS] but our scanning logic
// assumes [[KeyCode; NUM_ROWS]; NUM_COLS].
pub const TRANSPOSED_NORMAL_LAYER_MAPPING: [[KeyCode; NUM_ROWS]; NUM_COLS] =
transpose(NORMAL_LAYER_MAPPING);
pub const TRANSPOSED_FN_LAYER_MAPPING: [[KeyCode; NUM_ROWS]; NUM_COLS] =
transpose(FN_LAYER_MAPPING);

pub const fn transpose<const NUM_ROWS: usize, const NUM_COLS: usize>(
matrix: [[KeyCode; NUM_COLS]; NUM_ROWS],
) -> [[KeyCode; NUM_ROWS]; NUM_COLS] {
let mut new_matrix: [[KeyCode; NUM_ROWS]; NUM_COLS] = [[KeyCode::Empty; NUM_ROWS]; NUM_COLS];

let mut col = 0;

while col < NUM_COLS {
let mut row = 0;
while row < NUM_ROWS {
new_matrix[col][row] = matrix[row][col];
row += 1;
}

col += 1;
}

new_matrix
}
11 changes: 6 additions & 5 deletions firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![no_main]
#![no_std]

use crate::key_scan::TRANSPOSED_NORMAL_LAYER_MAPPING;
use usb_device::class::UsbClass;
mod debounce;
mod hid_descriptor;
Expand Down Expand Up @@ -102,7 +103,7 @@ fn main() -> ! {
rp2040_hal::gpio::Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);

// Set up keyboard matrix pins.
let rows: &[&dyn InputPin<Error = Infallible>] = &[
let rows: [&dyn InputPin<Error = Infallible>; NUM_ROWS] = [
&pins.gpio26.into_pull_down_input(),
&pins.gpio25.into_pull_down_input(),
&pins.gpio27.into_pull_down_input(),
Expand All @@ -111,7 +112,7 @@ fn main() -> ! {
&pins.gpio24.into_pull_down_input(),
];

let cols: &mut [&mut dyn OutputPin<Error = Infallible>] = &mut [
let mut cols: [&mut dyn OutputPin<Error = Infallible>; NUM_COLS] = [
&mut pins.gpio29.into_push_pull_output(),
&mut pins.gpio16.into_push_pull_output(),
&mut pins.gpio17.into_push_pull_output(),
Expand All @@ -132,7 +133,7 @@ fn main() -> ! {
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

let mut modifier_mask = [[false; NUM_ROWS]; NUM_COLS];
for (col, mapping_col) in modifier_mask.iter_mut().zip(key_mapping::NORMAL_LAYER_MAPPING) {
for (col, mapping_col) in modifier_mask.iter_mut().zip(TRANSPOSED_NORMAL_LAYER_MAPPING) {
for (key, mapping_key) in col.iter_mut().zip(mapping_col) {
*key = mapping_key.is_modifier();
}
Expand All @@ -142,7 +143,7 @@ fn main() -> ! {
let mut debounce: Debounce<NUM_ROWS, NUM_COLS> = Debounce::new(DEBOUNCE_TICKS, modifier_mask);

// Do an initial scan of the keys so that we immediately have something to report to the host when asked.
let scan = KeyScan::scan(rows, cols, &mut delay, &mut debounce);
let scan = KeyScan::scan(rows, &mut cols, &mut delay, &mut debounce);
critical_section::with(|cs| {
KEYBOARD_REPORT.replace(cs, scan.into());
});
Expand Down Expand Up @@ -203,7 +204,7 @@ fn main() -> ! {
}
info!("Entering main loop");
loop {
let scan = KeyScan::scan(rows, cols, &mut delay, &mut debounce);
let scan = KeyScan::scan(rows, &mut cols, &mut delay, &mut debounce);
critical_section::with(|cs| {
KEYBOARD_REPORT.replace(cs, scan.into());
});
Expand Down

0 comments on commit b61d705

Please sign in to comment.