Code
This commit is contained in:
parent
7967ceb623
commit
308b6d708c
@ -14,11 +14,12 @@ embedded-hal ="0.2.5"
|
|||||||
fugit = "0.3.5"
|
fugit = "0.3.5"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
smart-leds = "0.3.0"
|
smart-leds = "0.3.0"
|
||||||
|
smart-leds-trait = "0.2.1"
|
||||||
ws2812-pio = "0.6.0"
|
ws2812-pio = "0.6.0"
|
||||||
usbd-human-interface-device = "0.4.2"
|
usbd-human-interface-device = "0.4.2"
|
||||||
usb-device = "0.2"
|
usb-device = "0.2"
|
||||||
packed_struct = { version = "0.10", default-features = false }
|
packed_struct = { version = "0.10", default-features = false }
|
||||||
keypad = "0.2.2"
|
pio = "0.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# This is the set of features we enable by default
|
# This is the set of features we enable by default
|
||||||
|
|||||||
98
rp2040/src/button_matrix.rs
Normal file
98
rp2040/src/button_matrix.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
use core::convert::Infallible;
|
||||||
|
use cortex_m::delay::Delay;
|
||||||
|
use embedded_hal::digital::v2::*;
|
||||||
|
|
||||||
|
pub const DEBOUNCE_COUNT: u8 = 5;
|
||||||
|
|
||||||
|
pub struct ButtonMatrix<'a, const R: usize, const C: usize, const N: usize> {
|
||||||
|
rows: &'a [&'a dyn InputPin<Error = Infallible>; R],
|
||||||
|
cols: &'a mut [&'a mut dyn OutputPin<Error = Infallible>; C],
|
||||||
|
delay: &'a mut Delay,
|
||||||
|
state: [bool; N],
|
||||||
|
state_raw: [bool; N],
|
||||||
|
debounce_counter: [u8; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, const R: usize, const C: usize, const N: usize> ButtonMatrix<'a, R, C, N> {
|
||||||
|
pub fn new(
|
||||||
|
rows: &'a [&'a dyn InputPin<Error = Infallible>; R],
|
||||||
|
cols: &'a mut [&'a mut dyn OutputPin<Error = Infallible>; C],
|
||||||
|
delay: &'a mut Delay,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
rows,
|
||||||
|
cols,
|
||||||
|
delay,
|
||||||
|
state: [false; N],
|
||||||
|
state_raw: [false; N],
|
||||||
|
debounce_counter: [0; N],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_pins(&mut self) {
|
||||||
|
for col in self.cols.iter_mut() {
|
||||||
|
col.set_high().unwrap();
|
||||||
|
}
|
||||||
|
self.delay.delay_us(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scan_matrix(&mut self) {
|
||||||
|
for col_index in 0..self.cols.len() {
|
||||||
|
self.cols[col_index].set_low().unwrap();
|
||||||
|
self.delay.delay_us(10);
|
||||||
|
self.process_column(col_index);
|
||||||
|
self.cols[col_index].set_high().unwrap();
|
||||||
|
self.delay.delay_us(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_column(&mut self, col_index: usize) {
|
||||||
|
for row_index in 0..self.rows.len() {
|
||||||
|
let button_index: usize = col_index + (row_index * C);
|
||||||
|
let current_state = self.rows[row_index].is_low().unwrap();
|
||||||
|
self.state_raw[button_index] = current_state;
|
||||||
|
|
||||||
|
if current_state == self.state[button_index] {
|
||||||
|
self.debounce_counter[button_index] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.debounce_counter[button_index] += 1;
|
||||||
|
if self.debounce_counter[button_index] >= DEBOUNCE_COUNT {
|
||||||
|
self.state[button_index] = current_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn scan_matrix(&mut self) {
|
||||||
|
// for (col_index, col) in self.cols.iter_mut().enumerate() {
|
||||||
|
// col.set_low().unwrap();
|
||||||
|
// self.delay.delay_us(10);
|
||||||
|
//
|
||||||
|
// for (row_index, row) in self.rows.iter().enumerate() {
|
||||||
|
// let button_index: usize = col_index + (row_index * C);
|
||||||
|
// let current_state = row.is_low().unwrap();
|
||||||
|
// self.state_raw[button_index] = current_state;
|
||||||
|
//
|
||||||
|
// if current_state == self.state[button_index] {
|
||||||
|
// self.debounce_counter[button_index] = 0;
|
||||||
|
// } else {
|
||||||
|
// self.debounce_counter[button_index] += 1;
|
||||||
|
// if self.debounce_counter[button_index] >= DEBOUNCE_COUNT {
|
||||||
|
// self.state[button_index] = current_state;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// col.set_high().unwrap();
|
||||||
|
// self.delay.delay_us(10);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn get_button_state(&mut self) -> [bool; N] {
|
||||||
|
self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_button_state_raw(&mut self) -> [bool; N] {
|
||||||
|
self.state_raw
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,8 @@
|
|||||||
// | 0 | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | 11 |
|
// | 0 | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | 11 |
|
||||||
// | 12 | 13 | 14 | 15 | 16 | 17 | | 18 | 19 | 20 | 21 | 22 | 23 |
|
// | 12 | 13 | 14 | 15 | 16 | 17 | | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||||
// | 24 | 25 | 26 | 27 | 28 | 29 | | 30 | 31 | 32 | 33 | 34 | 35 |
|
// | 24 | 25 | 26 | 27 | 28 | 29 | | 30 | 31 | 32 | 33 | 34 | 35 |
|
||||||
// ------------------| 36 | 37 | 38 | | 39 | 40 | 41 |------------------
|
// ------------------| 39 | 40 | 41 | | 42 | 43 | 44 |------------------
|
||||||
// ------------------- -------------------
|
// 36 37 38 ------------------- ------------------- 45 46 47
|
||||||
//
|
//
|
||||||
// Swedish keymap conversion table:
|
// Swedish keymap conversion table:
|
||||||
// US Swedish
|
// US Swedish
|
||||||
@ -26,13 +26,15 @@ use crate::NUMBER_OF_KEYS;
|
|||||||
use usbd_human_interface_device::page::Keyboard;
|
use usbd_human_interface_device::page::Keyboard;
|
||||||
|
|
||||||
// Function (Fn) buttons index (need two buttons)
|
// Function (Fn) buttons index (need two buttons)
|
||||||
pub const FN_BUTTONS: [u8; 3] = [37, 40, 41];
|
// Button 41 are used both as Fn and RightAlt (AltGr) for better ergonomics.
|
||||||
|
// This means that RightAlt is only available on layer 1 keys.
|
||||||
|
pub const FN_BUTTONS: [u8; 3] = [40, 43, 44];
|
||||||
// Button map to HID key (three Function layers)
|
// Button map to HID key (three Function layers)
|
||||||
pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||||
[
|
[
|
||||||
// Function layer 0
|
// Function layer 0
|
||||||
// HID Key // Button Index
|
// HID Key // Button Index
|
||||||
|
// -----------------------------------------
|
||||||
Keyboard::Tab, // 0
|
Keyboard::Tab, // 0
|
||||||
Keyboard::Q, // 1
|
Keyboard::Q, // 1
|
||||||
Keyboard::W, // 2
|
Keyboard::W, // 2
|
||||||
@ -44,7 +46,7 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
|||||||
Keyboard::I, // 8
|
Keyboard::I, // 8
|
||||||
Keyboard::O, // 9
|
Keyboard::O, // 9
|
||||||
Keyboard::P, // 10
|
Keyboard::P, // 10
|
||||||
Keyboard::LeftBrace, // 11 // Å
|
Keyboard::LeftBrace, // 11 å
|
||||||
Keyboard::LeftControl, // 12
|
Keyboard::LeftControl, // 12
|
||||||
Keyboard::A, // 13
|
Keyboard::A, // 13
|
||||||
Keyboard::S, // 14
|
Keyboard::S, // 14
|
||||||
@ -55,8 +57,8 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
|||||||
Keyboard::J, // 19
|
Keyboard::J, // 19
|
||||||
Keyboard::K, // 20
|
Keyboard::K, // 20
|
||||||
Keyboard::L, // 21
|
Keyboard::L, // 21
|
||||||
Keyboard::Semicolon, // 22 // Ö
|
Keyboard::Semicolon, // 22 ö
|
||||||
Keyboard::Apostrophe, // 23 // Ä
|
Keyboard::Apostrophe, // 23 ä
|
||||||
Keyboard::LeftShift, // 24
|
Keyboard::LeftShift, // 24
|
||||||
Keyboard::Z, // 25
|
Keyboard::Z, // 25
|
||||||
Keyboard::X, // 26
|
Keyboard::X, // 26
|
||||||
@ -67,18 +69,25 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
|||||||
Keyboard::M, // 31
|
Keyboard::M, // 31
|
||||||
Keyboard::Comma, // 32
|
Keyboard::Comma, // 32
|
||||||
Keyboard::Dot, // 33
|
Keyboard::Dot, // 33
|
||||||
Keyboard::ForwardSlash, // 34 // -
|
Keyboard::ForwardSlash, // 34 -
|
||||||
Keyboard::RightShift, // 35
|
Keyboard::RightShift, // 35
|
||||||
Keyboard::LeftAlt, // 36
|
Keyboard::NoEventIndicated, // 36 no button connected
|
||||||
Keyboard::NoEventIndicated, // 37 // Fn
|
Keyboard::NoEventIndicated, // 37 no button connected
|
||||||
Keyboard::Space, // 38
|
Keyboard::NoEventIndicated, // 38 no button connected
|
||||||
Keyboard::ReturnEnter, // 39
|
Keyboard::LeftAlt, // 39
|
||||||
Keyboard::NoEventIndicated, // 40 // Fn
|
Keyboard::NoEventIndicated, // 40 Fn (= will never trigg this layer)
|
||||||
Keyboard::RightAlt, // 41
|
Keyboard::Space, // 41
|
||||||
|
Keyboard::ReturnEnter, // 42
|
||||||
|
Keyboard::NoEventIndicated, // 43 Fn (= will never trigg this layer)
|
||||||
|
Keyboard::NoEventIndicated, // 44 Fn (= will never trigg this layer)
|
||||||
|
Keyboard::NoEventIndicated, // 45 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 46 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 47 no button connected
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
// Function layer 1
|
// Function layer 1
|
||||||
// HID Key // Button Index
|
// HID Key // Button Index
|
||||||
|
// -----------------------------------------
|
||||||
Keyboard::Escape, // 0
|
Keyboard::Escape, // 0
|
||||||
Keyboard::F1, // 1
|
Keyboard::F1, // 1
|
||||||
Keyboard::F2, // 2
|
Keyboard::F2, // 2
|
||||||
@ -109,29 +118,36 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
|||||||
Keyboard::Keyboard8, // 27
|
Keyboard::Keyboard8, // 27
|
||||||
Keyboard::Keyboard9, // 28
|
Keyboard::Keyboard9, // 28
|
||||||
Keyboard::Keyboard0, // 29
|
Keyboard::Keyboard0, // 29
|
||||||
Keyboard::NonUSBackslash, // 30 // <
|
Keyboard::NonUSBackslash, // 30 <
|
||||||
Keyboard::Equal, // 31 // ´
|
Keyboard::Equal, // 31 ´
|
||||||
Keyboard::Backslash, // 32 // '
|
Keyboard::Backslash, // 32 '
|
||||||
Keyboard::RightBrace, // 33 // ^
|
Keyboard::RightBrace, // 33 ^
|
||||||
Keyboard::Minus, // 34 // +
|
Keyboard::Minus, // 34 +
|
||||||
Keyboard::RightShift, // 35
|
Keyboard::RightShift, // 35
|
||||||
Keyboard::LeftAlt, // 36
|
Keyboard::NoEventIndicated, // 36 no button connected
|
||||||
Keyboard::NoEventIndicated, // 37 // Fn
|
Keyboard::NoEventIndicated, // 37 no button connected
|
||||||
Keyboard::DeleteBackspace, // 38
|
Keyboard::NoEventIndicated, // 38 no button connected
|
||||||
Keyboard::ReturnEnter, // 39
|
Keyboard::LeftAlt, // 39
|
||||||
Keyboard::NoEventIndicated, // 40// Fn
|
Keyboard::NoEventIndicated, // 40 Fn
|
||||||
Keyboard::RightAlt, // 41
|
Keyboard::DeleteBackspace, // 41
|
||||||
|
Keyboard::ReturnEnter, // 42
|
||||||
|
Keyboard::NoEventIndicated, // 43 Fn
|
||||||
|
Keyboard::RightAlt, // 44 Fn
|
||||||
|
Keyboard::NoEventIndicated, // 45 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 46 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 47 no button connected
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
// Function layer 2
|
// Function layer 2
|
||||||
// HID Key // Button Index
|
// HID Key // Button Index
|
||||||
|
// -----------------------------------------
|
||||||
Keyboard::F11, // 0
|
Keyboard::F11, // 0
|
||||||
Keyboard::F12, // 1
|
Keyboard::F12, // 1
|
||||||
Keyboard::F13, // 2
|
Keyboard::F13, // 2
|
||||||
Keyboard::F14, // 3
|
Keyboard::F14, // 3
|
||||||
Keyboard::F15, // 4
|
Keyboard::F15, // 4
|
||||||
Keyboard::F16, // 5
|
Keyboard::F16, // 5
|
||||||
Keyboard::Grave, // 6 // §
|
Keyboard::Grave, // 6 §
|
||||||
Keyboard::NoEventIndicated, // 7
|
Keyboard::NoEventIndicated, // 7
|
||||||
Keyboard::LeftGUI, // 8
|
Keyboard::LeftGUI, // 8
|
||||||
Keyboard::NoEventIndicated, // 9
|
Keyboard::NoEventIndicated, // 9
|
||||||
@ -161,11 +177,17 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
|||||||
Keyboard::End, // 33
|
Keyboard::End, // 33
|
||||||
Keyboard::Insert, // 34
|
Keyboard::Insert, // 34
|
||||||
Keyboard::RightShift, // 35
|
Keyboard::RightShift, // 35
|
||||||
Keyboard::LeftAlt, // 36
|
Keyboard::NoEventIndicated, // 36 no button connected
|
||||||
Keyboard::NoEventIndicated, // 37 // Fn
|
Keyboard::NoEventIndicated, // 37 no button connected
|
||||||
Keyboard::LeftGUI, // 38
|
Keyboard::NoEventIndicated, // 38 no button connected
|
||||||
Keyboard::ReturnEnter, // 39
|
Keyboard::LeftAlt, // 39
|
||||||
Keyboard::NoEventIndicated, // 40 // Fn
|
Keyboard::NoEventIndicated, // 40 Fn
|
||||||
Keyboard::RightAlt, // 41
|
Keyboard::LeftGUI, // 41
|
||||||
|
Keyboard::ReturnEnter, // 42
|
||||||
|
Keyboard::NoEventIndicated, // 43 Fn
|
||||||
|
Keyboard::NoEventIndicated, // 44 Fn
|
||||||
|
Keyboard::NoEventIndicated, // 45 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 46 no button connected
|
||||||
|
Keyboard::NoEventIndicated, // 47 no button connected
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@ -5,13 +5,21 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
mod button_matrix;
|
||||||
|
mod layout;
|
||||||
|
mod status_led;
|
||||||
|
|
||||||
|
use crate::status_led::{StatusMode, Ws2812StatusLed};
|
||||||
|
use button_matrix::ButtonMatrix;
|
||||||
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;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use smart_leds::{SmartLedsWrite, RGB8};
|
use rp2040_hal::{
|
||||||
|
gpio::{Function, FunctionConfig, PinId, ValidPinMode},
|
||||||
|
pio::StateMachineIndex,
|
||||||
|
};
|
||||||
use usb_device::class_prelude::*;
|
use usb_device::class_prelude::*;
|
||||||
use usb_device::prelude::*;
|
use usb_device::prelude::*;
|
||||||
use usbd_human_interface_device::page::Keyboard;
|
use usbd_human_interface_device::page::Keyboard;
|
||||||
@ -28,23 +36,20 @@ use waveshare_rp2040_zero::{
|
|||||||
},
|
},
|
||||||
Pins, XOSC_CRYSTAL_FREQ,
|
Pins, XOSC_CRYSTAL_FREQ,
|
||||||
};
|
};
|
||||||
use ws2812_pio::Ws2812;
|
|
||||||
|
|
||||||
mod layout;
|
|
||||||
|
|
||||||
pub const KEY_ROWS: usize = 4;
|
pub const KEY_ROWS: usize = 4;
|
||||||
pub const KEY_COLS: usize = 12;
|
pub const KEY_COLS: usize = 12;
|
||||||
pub const NUMBER_OF_KEYS: usize = 42;
|
pub const NUMBER_OF_KEYS: usize = KEY_ROWS * KEY_COLS;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct ButtonMatrix {
|
pub struct KeyboardButton {
|
||||||
current_state: bool,
|
pub current_state: bool,
|
||||||
previous_state: bool,
|
pub previous_state: bool,
|
||||||
fn_mode: u8,
|
pub fn_mode: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ButtonMatrix {
|
impl KeyboardButton {
|
||||||
fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_state: false,
|
current_state: false,
|
||||||
previous_state: false,
|
previous_state: false,
|
||||||
@ -104,17 +109,13 @@ fn main() -> ! {
|
|||||||
|
|
||||||
// Configure the status 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 status_led = Ws2812::new(
|
let mut status_led = Ws2812StatusLed::new(
|
||||||
pins.neopixel.into_mode(),
|
pins.neopixel.into_mode(),
|
||||||
&mut pio,
|
&mut pio,
|
||||||
sm0,
|
sm0,
|
||||||
clocks.peripheral_clock.freq(),
|
clocks.peripheral_clock.freq(),
|
||||||
timer.count_down(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut button_matrix: [ButtonMatrix; NUMBER_OF_KEYS] =
|
|
||||||
[ButtonMatrix::default(); NUMBER_OF_KEYS];
|
|
||||||
|
|
||||||
let button_matrix_row_pins: &[&dyn InputPin<Error = Infallible>; KEY_ROWS] = &[
|
let button_matrix_row_pins: &[&dyn InputPin<Error = Infallible>; KEY_ROWS] = &[
|
||||||
&pins.gp0.into_pull_up_input(),
|
&pins.gp0.into_pull_up_input(),
|
||||||
&pins.gp1.into_pull_up_input(),
|
&pins.gp1.into_pull_up_input(),
|
||||||
@ -137,6 +138,11 @@ fn main() -> ! {
|
|||||||
&mut pins.gp11.into_push_pull_output(),
|
&mut pins.gp11.into_push_pull_output(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut button_matrix: ButtonMatrix<KEY_ROWS, KEY_COLS, NUMBER_OF_KEYS> =
|
||||||
|
ButtonMatrix::new(button_matrix_row_pins, button_matrix_col_pins, &mut delay);
|
||||||
|
|
||||||
|
let mut buttons: [KeyboardButton; NUMBER_OF_KEYS] = [KeyboardButton::default(); NUMBER_OF_KEYS];
|
||||||
|
|
||||||
let mut report_count_down = timer.count_down();
|
let mut report_count_down = timer.count_down();
|
||||||
report_count_down.start(10.millis());
|
report_count_down.start(10.millis());
|
||||||
|
|
||||||
@ -146,79 +152,44 @@ fn main() -> ! {
|
|||||||
let mut indicator_count_down = timer.count_down();
|
let mut indicator_count_down = timer.count_down();
|
||||||
indicator_count_down.start(250.millis());
|
indicator_count_down.start(250.millis());
|
||||||
|
|
||||||
let mut status_led_onoff: bool = false;
|
|
||||||
let mut caps_lock_active: bool = false;
|
let mut caps_lock_active: bool = false;
|
||||||
let mut fn_mode: u8 = 0;
|
let mut fn_mode: u8 = 0;
|
||||||
|
|
||||||
let status_led_colors: [RGB8; 6] = [
|
|
||||||
(0, 0, 0).into(), // Off
|
|
||||||
(10, 7, 0).into(), // Green
|
|
||||||
(10, 4, 10).into(), // Blue
|
|
||||||
(5, 10, 0).into(), // Orange
|
|
||||||
(2, 20, 0).into(), // Red
|
|
||||||
(0, 10, 10).into(), // Purple
|
|
||||||
];
|
|
||||||
|
|
||||||
// Set all column pins to output and high
|
// Set all column pins to output and high
|
||||||
init_button_matrix_pins(button_matrix_col_pins, &mut delay);
|
button_matrix.init_pins();
|
||||||
|
|
||||||
|
// Check if esc pressed while power on. If yes then enter bootloader
|
||||||
|
button_matrix.scan_matrix();
|
||||||
|
if button_matrix.get_button_state_raw()[0] == true {
|
||||||
|
status_led.update(StatusMode::BOOTLOADER);
|
||||||
|
let gpio_activity_pin_mask = 0;
|
||||||
|
let disable_interface_mask = 0;
|
||||||
|
rp2040_hal::rom_data::reset_to_usb_boot(gpio_activity_pin_mask, disable_interface_mask);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if indicator_count_down.wait().is_ok() {
|
if indicator_count_down.wait().is_ok() {
|
||||||
// Set status LED colour based on function layer and capslock
|
update_status_led(&mut status_led, fn_mode, caps_lock_active);
|
||||||
// 0 = green, 1 = blue, 2 = orange, capslock active = flashing.
|
|
||||||
if caps_lock_active == true && status_led_onoff == true {
|
|
||||||
status_led
|
|
||||||
.write([status_led_colors[0]].iter().copied())
|
|
||||||
.unwrap();
|
|
||||||
status_led_onoff = false;
|
|
||||||
} else {
|
|
||||||
status_led
|
|
||||||
.write([status_led_colors[usize::from(fn_mode) + 1]].iter().copied())
|
|
||||||
.unwrap();
|
|
||||||
status_led_onoff = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if report_count_down.wait().is_ok() {
|
if report_count_down.wait().is_ok() {
|
||||||
// Scan keyboard matrix
|
// Scan keyboard matrix
|
||||||
let pressed_keys =
|
let pressed_keys = button_matrix.get_button_state();
|
||||||
get_pressed_buttons(button_matrix_row_pins, button_matrix_col_pins, &mut delay);
|
|
||||||
|
|
||||||
// Check if all four corners are pressed, if so, reset to USB boot mode
|
|
||||||
if pressed_keys[0] == true
|
|
||||||
&& pressed_keys[11] == true
|
|
||||||
&& pressed_keys[24] == true
|
|
||||||
&& pressed_keys[35] == true
|
|
||||||
{
|
|
||||||
status_led
|
|
||||||
.write([status_led_colors[5]].iter().copied())
|
|
||||||
.unwrap();
|
|
||||||
delay.delay_us(100);
|
|
||||||
let gpio_activity_pin_mask = 0;
|
|
||||||
let disable_interface_mask = 0;
|
|
||||||
rp2040_hal::rom_data::reset_to_usb_boot(
|
|
||||||
gpio_activity_pin_mask,
|
|
||||||
disable_interface_mask,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Get current function layer
|
// Get current function layer
|
||||||
fn_mode = get_fn_mode(pressed_keys);
|
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 {
|
if caps_lock_active == false {
|
||||||
status_led
|
update_status_led(&mut status_led, fn_mode, caps_lock_active);
|
||||||
.write([status_led_colors[usize::from(fn_mode) + 1]].iter().copied())
|
|
||||||
.unwrap();
|
|
||||||
status_led_onoff = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy result from scanned keys to matrix struct
|
// Copy result from scanned keys to matrix struct
|
||||||
for (index, key) in pressed_keys.iter().enumerate() {
|
for (index, key) in pressed_keys.iter().enumerate() {
|
||||||
button_matrix[index].current_state = *key;
|
buttons[index].current_state = *key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate keyboard report
|
// Generate keyboard report
|
||||||
let keyboard_report = get_keyboard_report(&mut button_matrix, layout::MAP, fn_mode);
|
let keyboard_report = get_keyboard_report(&mut buttons, layout::MAP, fn_mode);
|
||||||
|
|
||||||
match keyboard.device().write_report(keyboard_report) {
|
match keyboard.device().write_report(keyboard_report) {
|
||||||
Err(UsbHidError::WouldBlock) => {}
|
Err(UsbHidError::WouldBlock) => {}
|
||||||
@ -232,6 +203,8 @@ fn main() -> ! {
|
|||||||
|
|
||||||
//Tick once per ms
|
//Tick once per ms
|
||||||
if tick_count_down.wait().is_ok() {
|
if tick_count_down.wait().is_ok() {
|
||||||
|
button_matrix.scan_matrix();
|
||||||
|
|
||||||
match keyboard.tick() {
|
match keyboard.tick() {
|
||||||
Err(UsbHidError::WouldBlock) => {}
|
Err(UsbHidError::WouldBlock) => {}
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -261,54 +234,36 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise keyboard matrix pins
|
// Set status LED colour based on function layer and capslock
|
||||||
fn init_button_matrix_pins(cols: &mut [&mut dyn OutputPin<Error = Infallible>], delay: &mut Delay) {
|
// 0 = green, 1 = blue, 2 = orange, capslock active = flashing red.
|
||||||
for col in cols.iter_mut() {
|
fn update_status_led<P, SM, I>(
|
||||||
col.set_high().unwrap();
|
status_led: &mut Ws2812StatusLed<P, SM, I>,
|
||||||
}
|
fn_mode: u8,
|
||||||
delay.delay_us(10);
|
caps_lock_active: bool,
|
||||||
}
|
) where
|
||||||
|
P: PIOExt + FunctionConfig,
|
||||||
// Scan keyboard matrix for pressed keys and return a bool array
|
I: PinId,
|
||||||
// representing the state of each key (true = pressed)
|
Function<P>: ValidPinMode<I>,
|
||||||
fn get_pressed_buttons(
|
SM: StateMachineIndex,
|
||||||
rows: &[&dyn InputPin<Error = Infallible>],
|
{
|
||||||
cols: &mut [&mut dyn OutputPin<Error = Infallible>],
|
if caps_lock_active == true {
|
||||||
delay: &mut Delay,
|
status_led.update(StatusMode::WARNING);
|
||||||
) -> [bool; NUMBER_OF_KEYS] {
|
} else {
|
||||||
// Scan keyboard matrix for pressed keys
|
match fn_mode {
|
||||||
let mut pressed_keys: [bool; NUMBER_OF_KEYS] = [false; NUMBER_OF_KEYS];
|
0 => status_led.update(StatusMode::OK),
|
||||||
for (col_index, col) in cols.iter_mut().enumerate() {
|
1 => status_led.update(StatusMode::ACTIVE1),
|
||||||
// Activate column
|
2 => status_led.update(StatusMode::ACTIVE2),
|
||||||
col.set_low().unwrap();
|
_ => status_led.update(StatusMode::ERROR),
|
||||||
delay.delay_us(10);
|
|
||||||
|
|
||||||
// Read rows
|
|
||||||
for (row_index, row) in rows.iter().enumerate() {
|
|
||||||
// Do not check unconnected keys in the matrix
|
|
||||||
if row_index == 3 && (col_index < 3 || col_index > 8) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if row_index < 3 && row.is_low().unwrap() {
|
|
||||||
pressed_keys[col_index + (row_index * KEY_COLS)] = true;
|
|
||||||
} else if row.is_low().unwrap() {
|
|
||||||
// Correct index for unconnected keys
|
|
||||||
pressed_keys[col_index + (row_index * KEY_COLS) - 3] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
col.set_high().unwrap();
|
|
||||||
delay.delay_us(10);
|
|
||||||
}
|
}
|
||||||
// Return scan result
|
|
||||||
pressed_keys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current Fn mode (0, 1 or 2)
|
// Get current Fn mode (0, 1 or 2)
|
||||||
fn get_fn_mode(pressed_keys: [bool; NUMBER_OF_KEYS]) -> u8 {
|
fn get_fn_mode(pressed_keys: [bool; NUMBER_OF_KEYS]) -> u8 {
|
||||||
// Check Fn mode
|
// Check Fn mode
|
||||||
let mut fn_mode: u8 = 0;
|
let mut fn_mode: u8 = 0;
|
||||||
for button_id in layout::FN_BUTTONS.iter() {
|
for button_id in crate::layout::FN_BUTTONS.iter() {
|
||||||
if pressed_keys[usize::from(*button_id)] == true {
|
if pressed_keys[*button_id as usize] == true {
|
||||||
fn_mode += 1;
|
fn_mode += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +275,7 @@ fn get_fn_mode(pressed_keys: [bool; NUMBER_OF_KEYS]) -> u8 {
|
|||||||
|
|
||||||
// Generate keyboard report based on pressed keys and Fn mode (0, 1 or 2)
|
// Generate keyboard report based on pressed keys and Fn mode (0, 1 or 2)
|
||||||
fn get_keyboard_report(
|
fn get_keyboard_report(
|
||||||
matrix_keys: &mut [ButtonMatrix; NUMBER_OF_KEYS],
|
matrix_keys: &mut [KeyboardButton; NUMBER_OF_KEYS],
|
||||||
layout_map: [[Keyboard; NUMBER_OF_KEYS]; 3],
|
layout_map: [[Keyboard; NUMBER_OF_KEYS]; 3],
|
||||||
fn_mode: u8,
|
fn_mode: u8,
|
||||||
) -> [Keyboard; NUMBER_OF_KEYS] {
|
) -> [Keyboard; NUMBER_OF_KEYS] {
|
||||||
@ -335,7 +290,7 @@ fn get_keyboard_report(
|
|||||||
key.previous_state = key.current_state;
|
key.previous_state = key.current_state;
|
||||||
|
|
||||||
if key.current_state == true {
|
if key.current_state == true {
|
||||||
keyboard_report[index] = layout_map[usize::from(key.fn_mode)][index];
|
keyboard_report[index] = layout_map[key.fn_mode as usize][index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return report
|
// Return report
|
||||||
|
|||||||
81
rp2040/src/status_led.rs
Normal file
81
rp2040/src/status_led.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use rp2040_hal::{
|
||||||
|
gpio::{Function, FunctionConfig, Pin, PinId, ValidPinMode},
|
||||||
|
pio::{PIOExt, StateMachineIndex, UninitStateMachine, PIO},
|
||||||
|
};
|
||||||
|
use smart_leds::{SmartLedsWrite, RGB8};
|
||||||
|
use ws2812_pio::Ws2812Direct;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub enum StatusMode {
|
||||||
|
OFF = 0,
|
||||||
|
OK = 1,
|
||||||
|
ACTIVE1 = 2,
|
||||||
|
ACTIVE2 = 3,
|
||||||
|
WARNING = 4,
|
||||||
|
ERROR = 5,
|
||||||
|
BOOTLOADER = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Ws2812StatusLed<P, SM, I>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
P: PIOExt + FunctionConfig,
|
||||||
|
Function<P>: ValidPinMode<I>,
|
||||||
|
SM: StateMachineIndex,
|
||||||
|
{
|
||||||
|
ws2812_direct: Ws2812Direct<P, SM, I>,
|
||||||
|
state: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P, SM, I> Ws2812StatusLed<P, SM, I>
|
||||||
|
where
|
||||||
|
I: PinId,
|
||||||
|
P: PIOExt + FunctionConfig,
|
||||||
|
Function<P>: ValidPinMode<I>,
|
||||||
|
SM: StateMachineIndex,
|
||||||
|
{
|
||||||
|
/// Creates a new instance of this driver.
|
||||||
|
pub fn new(
|
||||||
|
pin: Pin<I, Function<P>>,
|
||||||
|
pio: &mut PIO<P>,
|
||||||
|
sm: UninitStateMachine<(P, SM)>,
|
||||||
|
clock_freq: fugit::HertzU32,
|
||||||
|
) -> Self {
|
||||||
|
// prepare the PIO program
|
||||||
|
let ws2812_direct = Ws2812Direct::new(pin, pio, sm, clock_freq);
|
||||||
|
let state = false;
|
||||||
|
Self {
|
||||||
|
ws2812_direct,
|
||||||
|
state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, mode: StatusMode) {
|
||||||
|
let colors: [RGB8; 7] = [
|
||||||
|
(0, 0, 0).into(), // Off
|
||||||
|
(10, 7, 0).into(), // Green
|
||||||
|
(10, 4, 10).into(), // Blue
|
||||||
|
(5, 10, 0).into(), // Orange
|
||||||
|
(2, 20, 0).into(), // Red
|
||||||
|
(2, 20, 0).into(), // Red
|
||||||
|
(0, 10, 10).into(), // Purple
|
||||||
|
];
|
||||||
|
|
||||||
|
if mode == StatusMode::WARNING && self.state == false {
|
||||||
|
self.ws2812_direct
|
||||||
|
.write([colors[mode as usize]].iter().copied())
|
||||||
|
.unwrap();
|
||||||
|
self.state = true;
|
||||||
|
} else if mode == StatusMode::WARNING || mode == StatusMode::OFF {
|
||||||
|
self.ws2812_direct
|
||||||
|
.write([colors[0]].iter().copied())
|
||||||
|
.unwrap();
|
||||||
|
self.state = false;
|
||||||
|
} else {
|
||||||
|
self.ws2812_direct
|
||||||
|
.write([colors[mode as usize]].iter().copied())
|
||||||
|
.unwrap();
|
||||||
|
self.state = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user