First attemt on runnable code
This commit is contained in:
parent
9d683b8850
commit
63aefa717f
@ -2,6 +2,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
use cortex_m::delay::Delay;
|
||||||
use embedded_hal::digital::v2::*;
|
use embedded_hal::digital::v2::*;
|
||||||
use embedded_hal::timer::CountDown;
|
use embedded_hal::timer::CountDown;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
@ -25,10 +26,29 @@ use waveshare_rp2040_zero::{
|
|||||||
};
|
};
|
||||||
use ws2812_pio::Ws2812;
|
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]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut pac = pac::Peripherals::take().unwrap();
|
let mut pac = pac::Peripherals::take().unwrap();
|
||||||
|
let core = pac::CorePeripherals::take().unwrap();
|
||||||
let mut watchdog = Watchdog::new(pac.WATCHDOG);
|
let mut watchdog = Watchdog::new(pac.WATCHDOG);
|
||||||
|
|
||||||
let clocks = init_clocks_and_plls(
|
let clocks = init_clocks_and_plls(
|
||||||
@ -72,11 +92,11 @@ fn main() -> ! {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
|
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 pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let mut ws = Ws2812::new(
|
let mut status_led = Ws2812::new(
|
||||||
// The onboard NeoPixel is attached to GPIO pin #16 on the Feather RP2040.
|
|
||||||
pins.neopixel.into_mode(),
|
pins.neopixel.into_mode(),
|
||||||
&mut pio,
|
&mut pio,
|
||||||
sm0,
|
sm0,
|
||||||
@ -84,26 +104,182 @@ fn main() -> ! {
|
|||||||
timer.count_down(),
|
timer.count_down(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let matrix_rows: &[&dyn InputPin<Error = core::convert::Infallible>] = &[
|
let mut matrix_keys: [MatrixKey; NUMBER_OF_KEYS] = [MatrixKey::default(); NUMBER_OF_KEYS];
|
||||||
|
|
||||||
|
let matrix_rows: &[&dyn InputPin<Error = Infallible>] = &[
|
||||||
&pins.gp0.into_pull_up_input(),
|
&pins.gp0.into_pull_up_input(),
|
||||||
&pins.gp1.into_pull_up_input(),
|
&pins.gp1.into_pull_up_input(),
|
||||||
&pins.gp2.into_pull_up_input(),
|
&pins.gp29.into_pull_up_input(),
|
||||||
&pins.gp3.into_pull_up_input(),
|
&pins.gp28.into_pull_up_input(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let matrix_cols: &[&dyn OutputPin<Error = core::convert::Infallible>] = &[
|
let matrix_cols: &mut [&mut dyn OutputPin<Error = Infallible>] = &mut [
|
||||||
&pins.gp4.into_push_pull_output(),
|
&mut pins.gp12.into_push_pull_output(),
|
||||||
&pins.gp5.into_push_pull_output(),
|
&mut pins.gp13.into_push_pull_output(),
|
||||||
&pins.gp6.into_push_pull_output(),
|
&mut pins.gp14.into_push_pull_output(),
|
||||||
&pins.gp7.into_push_pull_output(),
|
&mut pins.gp15.into_push_pull_output(),
|
||||||
&pins.gp8.into_push_pull_output(),
|
&mut pins.gp26.into_push_pull_output(),
|
||||||
&pins.gp9.into_push_pull_output(),
|
&mut pins.gp27.into_push_pull_output(),
|
||||||
&pins.gp10.into_push_pull_output(),
|
&mut pins.gp7.into_push_pull_output(),
|
||||||
&pins.gp11.into_push_pull_output(),
|
&mut pins.gp8.into_push_pull_output(),
|
||||||
&pins.gp12.into_push_pull_output(),
|
&mut pins.gp6.into_push_pull_output(),
|
||||||
&pins.gp13.into_push_pull_output(),
|
&mut pins.gp9.into_push_pull_output(),
|
||||||
&pins.gp14.into_push_pull_output(),
|
&mut pins.gp10.into_push_pull_output(),
|
||||||
&pins.gp15.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();
|
let mut input_count_down = timer.count_down();
|
||||||
@ -114,19 +290,34 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let color_purple: RGB8 = (0, 10, 10).into();
|
let color_purple: RGB8 = (0, 10, 10).into();
|
||||||
let color_red: RGB8 = (0, 10, 0).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();
|
let color_none: RGB8 = (0, 0, 0).into();
|
||||||
|
|
||||||
|
init_keyboard_matrix_pins(matrix_cols, &mut delay);
|
||||||
|
|
||||||
// Infinite colour wheel loop
|
// Infinite colour wheel loop
|
||||||
loop {
|
loop {
|
||||||
if input_count_down.wait().is_ok() {
|
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::WouldBlock) => {}
|
||||||
Err(UsbHidError::Duplicate) => {}
|
Err(UsbHidError::Duplicate) => {}
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
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)
|
core::panic!("Failed to write keyboard report: {:?}", e)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -138,7 +329,7 @@ fn main() -> ! {
|
|||||||
Err(UsbHidError::WouldBlock) => {}
|
Err(UsbHidError::WouldBlock) => {}
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
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)
|
core::panic!("Failed to process keyboard tick: {:?}", e)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -150,17 +341,99 @@ fn main() -> ! {
|
|||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
Err(e) => {
|
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)
|
core::panic!("Failed to read keyboard report: {:?}", e)
|
||||||
}
|
}
|
||||||
Ok(leds) => {
|
Ok(leds) => {
|
||||||
if leds.caps_lock == true {
|
if leds.caps_lock == true {
|
||||||
ws.write([color_purple].iter().copied()).unwrap();
|
status_led.write([color_purple].iter().copied()).unwrap();
|
||||||
} else {
|
} 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<Error = Infallible>],
|
||||||
|
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<Error = Infallible>],
|
||||||
|
cols: &mut [&mut dyn OutputPin<Error = Infallible>],
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user