Code
This commit is contained in:
parent
7967ceb623
commit
308b6d708c
@ -14,11 +14,12 @@ embedded-hal ="0.2.5"
|
||||
fugit = "0.3.5"
|
||||
nb = "1.0.0"
|
||||
smart-leds = "0.3.0"
|
||||
smart-leds-trait = "0.2.1"
|
||||
ws2812-pio = "0.6.0"
|
||||
usbd-human-interface-device = "0.4.2"
|
||||
usb-device = "0.2"
|
||||
packed_struct = { version = "0.10", default-features = false }
|
||||
keypad = "0.2.2"
|
||||
pio = "0.2.0"
|
||||
|
||||
[features]
|
||||
# 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 |
|
||||
// | 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 |------------------
|
||||
// ------------------- -------------------
|
||||
// ------------------| 39 | 40 | 41 | | 42 | 43 | 44 |------------------
|
||||
// 36 37 38 ------------------- ------------------- 45 46 47
|
||||
//
|
||||
// Swedish keymap conversion table:
|
||||
// US Swedish
|
||||
@ -26,13 +26,15 @@ use crate::NUMBER_OF_KEYS;
|
||||
use usbd_human_interface_device::page::Keyboard;
|
||||
|
||||
// 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)
|
||||
pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
[
|
||||
// Function layer 0
|
||||
// HID Key // Button Index
|
||||
// -----------------------------------------
|
||||
Keyboard::Tab, // 0
|
||||
Keyboard::Q, // 1
|
||||
Keyboard::W, // 2
|
||||
@ -44,7 +46,7 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
Keyboard::I, // 8
|
||||
Keyboard::O, // 9
|
||||
Keyboard::P, // 10
|
||||
Keyboard::LeftBrace, // 11 // Å
|
||||
Keyboard::LeftBrace, // 11 å
|
||||
Keyboard::LeftControl, // 12
|
||||
Keyboard::A, // 13
|
||||
Keyboard::S, // 14
|
||||
@ -55,8 +57,8 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
Keyboard::J, // 19
|
||||
Keyboard::K, // 20
|
||||
Keyboard::L, // 21
|
||||
Keyboard::Semicolon, // 22 // Ö
|
||||
Keyboard::Apostrophe, // 23 // Ä
|
||||
Keyboard::Semicolon, // 22 ö
|
||||
Keyboard::Apostrophe, // 23 ä
|
||||
Keyboard::LeftShift, // 24
|
||||
Keyboard::Z, // 25
|
||||
Keyboard::X, // 26
|
||||
@ -67,18 +69,25 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
Keyboard::M, // 31
|
||||
Keyboard::Comma, // 32
|
||||
Keyboard::Dot, // 33
|
||||
Keyboard::ForwardSlash, // 34 // -
|
||||
Keyboard::ForwardSlash, // 34 -
|
||||
Keyboard::RightShift, // 35
|
||||
Keyboard::LeftAlt, // 36
|
||||
Keyboard::NoEventIndicated, // 37 // Fn
|
||||
Keyboard::Space, // 38
|
||||
Keyboard::ReturnEnter, // 39
|
||||
Keyboard::NoEventIndicated, // 40 // Fn
|
||||
Keyboard::RightAlt, // 41
|
||||
Keyboard::NoEventIndicated, // 36 no button connected
|
||||
Keyboard::NoEventIndicated, // 37 no button connected
|
||||
Keyboard::NoEventIndicated, // 38 no button connected
|
||||
Keyboard::LeftAlt, // 39
|
||||
Keyboard::NoEventIndicated, // 40 Fn (= will never trigg this layer)
|
||||
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
|
||||
// HID Key // Button Index
|
||||
// -----------------------------------------
|
||||
Keyboard::Escape, // 0
|
||||
Keyboard::F1, // 1
|
||||
Keyboard::F2, // 2
|
||||
@ -109,29 +118,36 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
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::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::ReturnEnter, // 39
|
||||
Keyboard::NoEventIndicated, // 40// Fn
|
||||
Keyboard::RightAlt, // 41
|
||||
Keyboard::NoEventIndicated, // 36 no button connected
|
||||
Keyboard::NoEventIndicated, // 37 no button connected
|
||||
Keyboard::NoEventIndicated, // 38 no button connected
|
||||
Keyboard::LeftAlt, // 39
|
||||
Keyboard::NoEventIndicated, // 40 Fn
|
||||
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
|
||||
// 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::Grave, // 6 §
|
||||
Keyboard::NoEventIndicated, // 7
|
||||
Keyboard::LeftGUI, // 8
|
||||
Keyboard::NoEventIndicated, // 9
|
||||
@ -161,11 +177,17 @@ pub const MAP: [[Keyboard; NUMBER_OF_KEYS]; 3] = [
|
||||
Keyboard::End, // 33
|
||||
Keyboard::Insert, // 34
|
||||
Keyboard::RightShift, // 35
|
||||
Keyboard::LeftAlt, // 36
|
||||
Keyboard::NoEventIndicated, // 37 // Fn
|
||||
Keyboard::LeftGUI, // 38
|
||||
Keyboard::ReturnEnter, // 39
|
||||
Keyboard::NoEventIndicated, // 40 // Fn
|
||||
Keyboard::RightAlt, // 41
|
||||
Keyboard::NoEventIndicated, // 36 no button connected
|
||||
Keyboard::NoEventIndicated, // 37 no button connected
|
||||
Keyboard::NoEventIndicated, // 38 no button connected
|
||||
Keyboard::LeftAlt, // 39
|
||||
Keyboard::NoEventIndicated, // 40 Fn
|
||||
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_main]
|
||||
|
||||
mod button_matrix;
|
||||
mod layout;
|
||||
mod status_led;
|
||||
|
||||
use crate::status_led::{StatusMode, Ws2812StatusLed};
|
||||
use button_matrix::ButtonMatrix;
|
||||
use core::convert::Infallible;
|
||||
use cortex_m::delay::Delay;
|
||||
use embedded_hal::digital::v2::*;
|
||||
use embedded_hal::timer::CountDown;
|
||||
use fugit::ExtU32;
|
||||
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::prelude::*;
|
||||
use usbd_human_interface_device::page::Keyboard;
|
||||
@ -28,23 +36,20 @@ use waveshare_rp2040_zero::{
|
||||
},
|
||||
Pins, XOSC_CRYSTAL_FREQ,
|
||||
};
|
||||
use ws2812_pio::Ws2812;
|
||||
|
||||
mod layout;
|
||||
|
||||
pub const KEY_ROWS: usize = 4;
|
||||
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)]
|
||||
struct ButtonMatrix {
|
||||
current_state: bool,
|
||||
previous_state: bool,
|
||||
fn_mode: u8,
|
||||
pub struct KeyboardButton {
|
||||
pub current_state: bool,
|
||||
pub previous_state: bool,
|
||||
pub fn_mode: u8,
|
||||
}
|
||||
|
||||
impl ButtonMatrix {
|
||||
fn default() -> Self {
|
||||
impl KeyboardButton {
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
current_state: false,
|
||||
previous_state: false,
|
||||
@ -104,17 +109,13 @@ fn main() -> ! {
|
||||
|
||||
// Configure the status LED
|
||||
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(),
|
||||
&mut pio,
|
||||
sm0,
|
||||
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] = &[
|
||||
&pins.gp0.into_pull_up_input(),
|
||||
&pins.gp1.into_pull_up_input(),
|
||||
@ -137,6 +138,11 @@ fn main() -> ! {
|
||||
&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();
|
||||
report_count_down.start(10.millis());
|
||||
|
||||
@ -146,79 +152,44 @@ fn main() -> ! {
|
||||
let mut indicator_count_down = timer.count_down();
|
||||
indicator_count_down.start(250.millis());
|
||||
|
||||
let mut status_led_onoff: bool = false;
|
||||
let mut caps_lock_active: bool = false;
|
||||
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
|
||||
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 {
|
||||
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 = 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;
|
||||
}
|
||||
update_status_led(&mut status_led, fn_mode, caps_lock_active);
|
||||
}
|
||||
|
||||
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);
|
||||
let pressed_keys = button_matrix.get_button_state();
|
||||
|
||||
// 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
|
||||
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_colors[usize::from(fn_mode) + 1]].iter().copied())
|
||||
.unwrap();
|
||||
status_led_onoff = true;
|
||||
update_status_led(&mut status_led, fn_mode, caps_lock_active);
|
||||
}
|
||||
|
||||
// Copy result from scanned keys to matrix struct
|
||||
for (index, key) in pressed_keys.iter().enumerate() {
|
||||
button_matrix[index].current_state = *key;
|
||||
buttons[index].current_state = *key;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Err(UsbHidError::WouldBlock) => {}
|
||||
@ -232,6 +203,8 @@ fn main() -> ! {
|
||||
|
||||
//Tick once per ms
|
||||
if tick_count_down.wait().is_ok() {
|
||||
button_matrix.scan_matrix();
|
||||
|
||||
match keyboard.tick() {
|
||||
Err(UsbHidError::WouldBlock) => {}
|
||||
Ok(_) => {}
|
||||
@ -261,54 +234,36 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise keyboard matrix pins
|
||||
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();
|
||||
}
|
||||
delay.delay_us(10);
|
||||
}
|
||||
|
||||
// Scan keyboard matrix for pressed keys and return a bool array
|
||||
// representing the state of each key (true = pressed)
|
||||
fn get_pressed_buttons(
|
||||
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];
|
||||
for (col_index, col) in cols.iter_mut().enumerate() {
|
||||
// Activate column
|
||||
col.set_low().unwrap();
|
||||
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;
|
||||
}
|
||||
// Set status LED colour based on function layer and capslock
|
||||
// 0 = green, 1 = blue, 2 = orange, capslock active = flashing red.
|
||||
fn update_status_led<P, SM, I>(
|
||||
status_led: &mut Ws2812StatusLed<P, SM, I>,
|
||||
fn_mode: u8,
|
||||
caps_lock_active: bool,
|
||||
) where
|
||||
P: PIOExt + FunctionConfig,
|
||||
I: PinId,
|
||||
Function<P>: ValidPinMode<I>,
|
||||
SM: StateMachineIndex,
|
||||
{
|
||||
if caps_lock_active == true {
|
||||
status_led.update(StatusMode::WARNING);
|
||||
} else {
|
||||
match fn_mode {
|
||||
0 => status_led.update(StatusMode::OK),
|
||||
1 => status_led.update(StatusMode::ACTIVE1),
|
||||
2 => status_led.update(StatusMode::ACTIVE2),
|
||||
_ => status_led.update(StatusMode::ERROR),
|
||||
}
|
||||
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;
|
||||
for button_id in layout::FN_BUTTONS.iter() {
|
||||
if pressed_keys[usize::from(*button_id)] == true {
|
||||
for button_id in crate::layout::FN_BUTTONS.iter() {
|
||||
if pressed_keys[*button_id as usize] == true {
|
||||
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)
|
||||
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],
|
||||
fn_mode: u8,
|
||||
) -> [Keyboard; NUMBER_OF_KEYS] {
|
||||
@ -335,7 +290,7 @@ fn get_keyboard_report(
|
||||
key.previous_state = key.current_state;
|
||||
|
||||
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
|
||||
|
||||
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