Code refactor
This commit is contained in:
parent
6dbec2425e
commit
932d89e9ce
@ -1,6 +1,8 @@
|
|||||||
//! Bootloader entry helpers shared between power-on checks and runtime combos.
|
//! Bootloader entry helpers shared between power-on checks and runtime combos.
|
||||||
|
|
||||||
use crate::{NUMBER_OF_KEYS, StatusLed, layout, status::StatusMode};
|
use crate::{KeyMatrix, StatusLed, layout, status::StatusMode};
|
||||||
|
#[cfg(all(test, feature = "std"))]
|
||||||
|
use crate::NUMBER_OF_KEYS;
|
||||||
use cortex_m::asm;
|
use cortex_m::asm;
|
||||||
use rp2040_hal::{
|
use rp2040_hal::{
|
||||||
gpio::AnyPin,
|
gpio::AnyPin,
|
||||||
@ -11,7 +13,7 @@ use usbd_human_interface_device::page::Keyboard;
|
|||||||
/// Returns true when the runtime bootloader chord is held.
|
/// Returns true when the runtime bootloader chord is held.
|
||||||
///
|
///
|
||||||
/// The chord requires two Fn buttons, both Shift buttons and the primary Ctrl.
|
/// The chord requires two Fn buttons, both Shift buttons and the primary Ctrl.
|
||||||
pub fn chord_requested(pressed_keys: &[bool; NUMBER_OF_KEYS]) -> bool {
|
pub fn chord_requested(pressed_keys: &KeyMatrix) -> bool {
|
||||||
if !modifier_pressed(pressed_keys, Keyboard::LeftShift)
|
if !modifier_pressed(pressed_keys, Keyboard::LeftShift)
|
||||||
|| !modifier_pressed(pressed_keys, Keyboard::RightShift)
|
|| !modifier_pressed(pressed_keys, Keyboard::RightShift)
|
||||||
{
|
{
|
||||||
@ -30,7 +32,7 @@ pub fn chord_requested(pressed_keys: &[bool; NUMBER_OF_KEYS]) -> bool {
|
|||||||
active_fn >= 2
|
active_fn >= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modifier_pressed(pressed_keys: &[bool; NUMBER_OF_KEYS], key: Keyboard) -> bool {
|
fn modifier_pressed(pressed_keys: &KeyMatrix, key: Keyboard) -> bool {
|
||||||
layout::MAP[0]
|
layout::MAP[0]
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
|||||||
@ -126,19 +126,10 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.debounce_counter[button_index] >= threshold {
|
if self.debounce_counter[button_index] >= threshold {
|
||||||
if current_state {
|
self.pressed[button_index] = match current_state {
|
||||||
let elapsed = self
|
true => self.should_register_press(button_index),
|
||||||
.scan_counter
|
false => false,
|
||||||
.wrapping_sub(self.last_press_scan[button_index]);
|
};
|
||||||
if self.last_press_scan[button_index] == 0
|
|
||||||
|| elapsed >= self.min_press_gap_scans
|
|
||||||
{
|
|
||||||
self.pressed[button_index] = true;
|
|
||||||
self.last_press_scan[button_index] = self.scan_counter;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.pressed[button_index] = false;
|
|
||||||
}
|
|
||||||
self.debounce_counter[button_index] = 0;
|
self.debounce_counter[button_index] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,6 +139,17 @@ where
|
|||||||
self.pressed
|
self.pressed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_register_press(&mut self, button_index: usize) -> bool {
|
||||||
|
let elapsed = self.scan_counter.wrapping_sub(self.last_press_scan[button_index]);
|
||||||
|
let can_register = self.last_press_scan[button_index] == 0
|
||||||
|
|| elapsed >= self.min_press_gap_scans;
|
||||||
|
|
||||||
|
if can_register {
|
||||||
|
self.last_press_scan[button_index] = self.scan_counter;
|
||||||
|
}
|
||||||
|
can_register
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "std"))]
|
#[cfg(all(test, feature = "std"))]
|
||||||
pub(crate) fn set_scan_counter(&mut self, value: u32) {
|
pub(crate) fn set_scan_counter(&mut self, value: u32) {
|
||||||
self.scan_counter = value;
|
self.scan_counter = value;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//! Keyboard state management and HID report generation.
|
//! Keyboard state management and HID report generation.
|
||||||
|
|
||||||
use crate::NUMBER_OF_KEYS;
|
use crate::{NUMBER_OF_KEYS, KeyMatrix, KeyReport};
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
use crate::status::StatusSummary;
|
use crate::status::StatusSummary;
|
||||||
use usbd_human_interface_device::page::Keyboard;
|
use usbd_human_interface_device::page::Keyboard;
|
||||||
@ -50,8 +50,8 @@ impl KeyboardState {
|
|||||||
|
|
||||||
pub fn process_scan(
|
pub fn process_scan(
|
||||||
&mut self,
|
&mut self,
|
||||||
pressed_keys: [bool; NUMBER_OF_KEYS],
|
pressed_keys: KeyMatrix,
|
||||||
) -> [Keyboard; NUMBER_OF_KEYS] {
|
) -> KeyReport {
|
||||||
let fn_mode = Self::fn_mode(&pressed_keys);
|
let fn_mode = Self::fn_mode(&pressed_keys);
|
||||||
|
|
||||||
for (index, pressed) in pressed_keys.iter().enumerate() {
|
for (index, pressed) in pressed_keys.iter().enumerate() {
|
||||||
@ -85,6 +85,16 @@ impl KeyboardState {
|
|||||||
self.sticky_state
|
self.sticky_state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn toggle_sticky_state(&mut self) {
|
||||||
|
self.sticky_state = match self.sticky_state {
|
||||||
|
StickyState::Inactive => StickyState::Armed,
|
||||||
|
StickyState::Armed | StickyState::Latched => {
|
||||||
|
self.sticky_key = Keyboard::NoEventIndicated;
|
||||||
|
StickyState::Inactive
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn status_summary(
|
pub fn status_summary(
|
||||||
&self,
|
&self,
|
||||||
usb_initialized: bool,
|
usb_initialized: bool,
|
||||||
@ -103,34 +113,27 @@ impl KeyboardState {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_report(&mut self, fn_mode: u8) -> [Keyboard; NUMBER_OF_KEYS] {
|
fn build_report(&mut self, fn_mode: u8) -> KeyReport {
|
||||||
let mut report = [Keyboard::NoEventIndicated; NUMBER_OF_KEYS];
|
let mut report = [Keyboard::NoEventIndicated; NUMBER_OF_KEYS];
|
||||||
|
let mut sticky_toggle_requested = false;
|
||||||
|
|
||||||
for (index, button) in self.buttons.iter_mut().enumerate() {
|
for (index, button) in self.buttons.iter_mut().enumerate() {
|
||||||
let changed = button.pressed != button.previous_pressed;
|
let changed = button.pressed != button.previous_pressed;
|
||||||
let just_pressed = changed && button.pressed;
|
let just_pressed = changed && button.pressed;
|
||||||
|
|
||||||
if just_pressed
|
|
||||||
&& index as u8 == layout::STICKY_BUTTON[0]
|
|
||||||
&& fn_mode == layout::STICKY_BUTTON[1]
|
|
||||||
{
|
|
||||||
self.sticky_state = match self.sticky_state {
|
|
||||||
StickyState::Inactive => StickyState::Armed,
|
|
||||||
StickyState::Armed | StickyState::Latched => {
|
|
||||||
self.sticky_key = Keyboard::NoEventIndicated;
|
|
||||||
StickyState::Inactive
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else if just_pressed
|
|
||||||
&& index as u8 == layout::OS_LOCK_BUTTON[0]
|
|
||||||
&& fn_mode == layout::OS_LOCK_BUTTON[1]
|
|
||||||
{
|
|
||||||
report[36] = layout::OS_LOCK_BUTTON_KEYS[0];
|
|
||||||
report[37] = layout::OS_LOCK_BUTTON_KEYS[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if just_pressed {
|
if just_pressed {
|
||||||
button.fn_mode = fn_mode;
|
button.fn_mode = fn_mode;
|
||||||
|
|
||||||
|
match (index as u8, fn_mode) {
|
||||||
|
(idx, layer) if idx == layout::STICKY_BUTTON[0] && layer == layout::STICKY_BUTTON[1] => {
|
||||||
|
sticky_toggle_requested = true;
|
||||||
|
}
|
||||||
|
(idx, layer) if idx == layout::OS_LOCK_BUTTON[0] && layer == layout::OS_LOCK_BUTTON[1] => {
|
||||||
|
report[36] = layout::OS_LOCK_BUTTON_KEYS[0];
|
||||||
|
report[37] = layout::OS_LOCK_BUTTON_KEYS[1];
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let layer_key = layout::MAP[button.fn_mode as usize][index];
|
let layer_key = layout::MAP[button.fn_mode as usize][index];
|
||||||
@ -151,13 +154,17 @@ impl KeyboardState {
|
|||||||
button.previous_pressed = button.pressed;
|
button.previous_pressed = button.pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sticky_toggle_requested {
|
||||||
|
self.toggle_sticky_state();
|
||||||
|
}
|
||||||
|
|
||||||
const STICKY_REPORT_INDEX: usize = 46;
|
const STICKY_REPORT_INDEX: usize = 46;
|
||||||
report[STICKY_REPORT_INDEX] = self.sticky_key;
|
report[STICKY_REPORT_INDEX] = self.sticky_key;
|
||||||
|
|
||||||
report
|
report
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_mode(pressed_keys: &[bool; NUMBER_OF_KEYS]) -> u8 {
|
fn fn_mode(pressed_keys: &KeyMatrix) -> u8 {
|
||||||
let active_fn_keys = layout::FN_BUTTONS
|
let active_fn_keys = layout::FN_BUTTONS
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|key_index| pressed_keys[**key_index as usize])
|
.filter(|key_index| pressed_keys[**key_index as usize])
|
||||||
|
|||||||
@ -24,6 +24,10 @@ pub use hardware::{
|
|||||||
pub use keyboard::{KeyboardState, StickyState};
|
pub use keyboard::{KeyboardState, StickyState};
|
||||||
pub use status::{StatusLed, StatusMode, StatusSummary};
|
pub use status::{StatusLed, StatusMode, StatusSummary};
|
||||||
|
|
||||||
|
// Type aliases for better code readability
|
||||||
|
pub type KeyMatrix = [bool; NUMBER_OF_KEYS];
|
||||||
|
pub type KeyReport = [usbd_human_interface_device::page::Keyboard; NUMBER_OF_KEYS];
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
static mut __bi_entries_start: u8 = 0;
|
static mut __bi_entries_start: u8 = 0;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use cmdr_keyboard_42::hardware::{self, timers};
|
use cmdr_keyboard_42::hardware::{self, timers};
|
||||||
use cmdr_keyboard_42::{Board, BoardParts, KeyboardState, StatusMode, bootloader};
|
use cmdr_keyboard_42::{Board, BoardParts, KeyboardState, StatusMode, bootloader, KeyReport};
|
||||||
use embedded_hal_0_2::timer::CountDown;
|
use embedded_hal_0_2::timer::CountDown;
|
||||||
use fugit::ExtU32;
|
use fugit::ExtU32;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
@ -25,6 +25,31 @@ use usbd_human_interface_device::prelude::*;
|
|||||||
#[used]
|
#[used]
|
||||||
pub static BOOT2_FIRMWARE: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
pub static BOOT2_FIRMWARE: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||||
|
|
||||||
|
|
||||||
|
fn handle_usb_state_changes(
|
||||||
|
usb_dev: &UsbDevice<rp2040_hal::usb::UsbBus>,
|
||||||
|
usb_suspended: &mut bool,
|
||||||
|
wake_on_input: &mut bool,
|
||||||
|
last_activity_ms: &mut u32,
|
||||||
|
status_time_ms: u32,
|
||||||
|
) {
|
||||||
|
let current_suspended = usb_dev.state() == UsbDeviceState::Suspend;
|
||||||
|
let was_suspended = *usb_suspended;
|
||||||
|
|
||||||
|
match (was_suspended, current_suspended) {
|
||||||
|
(true, false) => {
|
||||||
|
*last_activity_ms = status_time_ms;
|
||||||
|
*wake_on_input = false;
|
||||||
|
}
|
||||||
|
(false, true) => {
|
||||||
|
*wake_on_input = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
*usb_suspended = current_suspended;
|
||||||
|
}
|
||||||
|
|
||||||
#[rp2040_hal::entry]
|
#[rp2040_hal::entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let BoardParts {
|
let BoardParts {
|
||||||
@ -86,14 +111,12 @@ fn main() -> ! {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let should_scan = if usb_suspended {
|
let should_scan = !usb_suspended || {
|
||||||
static mut SUSPENDED_SCAN_COUNTER: u8 = 0;
|
static mut SUSPENDED_SCAN_COUNTER: u8 = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
SUSPENDED_SCAN_COUNTER = (SUSPENDED_SCAN_COUNTER + 1) % 20;
|
SUSPENDED_SCAN_COUNTER = (SUSPENDED_SCAN_COUNTER + 1) % 20;
|
||||||
SUSPENDED_SCAN_COUNTER == 0
|
SUSPENDED_SCAN_COUNTER == 0
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if usb_tick.wait().is_ok() && should_scan {
|
if usb_tick.wait().is_ok() && should_scan {
|
||||||
@ -102,9 +125,8 @@ fn main() -> ! {
|
|||||||
|
|
||||||
if bootloader::chord_requested(&pressed_keys) {
|
if bootloader::chord_requested(&pressed_keys) {
|
||||||
if !usb_suspended {
|
if !usb_suspended {
|
||||||
let mut attempts: u8 = 0;
|
for _ in 0..3 {
|
||||||
while attempts < 3 {
|
let clear_report: KeyReport = [Keyboard::NoEventIndicated; hardware::NUMBER_OF_KEYS];
|
||||||
let clear_report = [Keyboard::NoEventIndicated; hardware::NUMBER_OF_KEYS];
|
|
||||||
match keyboard.device().write_report(clear_report) {
|
match keyboard.device().write_report(clear_report) {
|
||||||
Ok(_) => break,
|
Ok(_) => break,
|
||||||
Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) => {
|
Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) => {
|
||||||
@ -112,7 +134,6 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
attempts = attempts.saturating_add(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,17 +188,12 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let usb_state = usb_dev.state();
|
handle_usb_state_changes(
|
||||||
let was_suspended = usb_suspended;
|
&usb_dev,
|
||||||
usb_suspended = usb_state == UsbDeviceState::Suspend;
|
&mut usb_suspended,
|
||||||
|
&mut wake_on_input,
|
||||||
if was_suspended && !usb_suspended {
|
&mut last_activity_ms,
|
||||||
last_activity_ms = status_time_ms;
|
status_time_ms,
|
||||||
wake_on_input = false;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if !was_suspended && usb_suspended {
|
|
||||||
wake_on_input = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -166,18 +166,17 @@ fn breathe(color: RGB8, elapsed_ms: u32, period_ms: u32) -> RGB8 {
|
|||||||
if period_ms == 0 {
|
if period_ms == 0 {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
let period = period_ms.max(1);
|
let period = period_ms.max(1);
|
||||||
let time_in_period = (elapsed_ms % period) as f32;
|
let phase = (elapsed_ms % period) as f32 / period as f32;
|
||||||
let period_f = period as f32;
|
|
||||||
let phase = time_in_period / period_f;
|
|
||||||
let brightness = if phase < 0.5 {
|
let brightness = if phase < 0.5 {
|
||||||
1.0 - (phase * 2.0)
|
1.0 - (phase * 2.0)
|
||||||
} else {
|
} else {
|
||||||
(phase - 0.5) * 2.0
|
(phase - 0.5) * 2.0
|
||||||
};
|
};
|
||||||
let clamped = brightness.max(0.0).min(1.0);
|
let brightness_factor = ((brightness.clamp(0.0, 1.0) * 255.0) + 0.5) as u8;
|
||||||
let ramp = (clamped * 255.0 + 0.5) as u8;
|
|
||||||
scale_color(color, ramp)
|
scale_color(color, brightness_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scale_color(color: RGB8, factor: u8) -> RGB8 {
|
fn scale_color(color: RGB8, factor: u8) -> RGB8 {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user