Splitted out layout file

This commit is contained in:
Christoffer Martinsson 2023-06-19 22:43:59 +02:00
parent 5ae9e09667
commit 24de6a5109
2 changed files with 229 additions and 192 deletions

171
rp2040/src/layout.rs Normal file
View File

@ -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
],
];

View File

@ -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<Error = Infallible>] = &[
let button_matrix_row_pins: &[&dyn InputPin<Error = Infallible>] = &[
&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<Error = Infallible>] = &mut [
let button_matrix_col_pins: &mut [&mut dyn OutputPin<Error = Infallible>] = &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<Error = Infallible>],
delay: &mut Delay,
) {
fn init_button_matrix_pins(cols: &mut [&mut dyn OutputPin<Error = Infallible>], 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<Error = Infallible>],
cols: &mut [&mut dyn OutputPin<Error = Infallible>],
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