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.
|
||||
|
||||
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 rp2040_hal::{
|
||||
gpio::AnyPin,
|
||||
@ -11,7 +13,7 @@ use usbd_human_interface_device::page::Keyboard;
|
||||
/// Returns true when the runtime bootloader chord is held.
|
||||
///
|
||||
/// 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)
|
||||
|| !modifier_pressed(pressed_keys, Keyboard::RightShift)
|
||||
{
|
||||
@ -30,7 +32,7 @@ pub fn chord_requested(pressed_keys: &[bool; NUMBER_OF_KEYS]) -> bool {
|
||||
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]
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
||||
@ -126,19 +126,10 @@ where
|
||||
};
|
||||
|
||||
if self.debounce_counter[button_index] >= threshold {
|
||||
if current_state {
|
||||
let elapsed = self
|
||||
.scan_counter
|
||||
.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.pressed[button_index] = match current_state {
|
||||
true => self.should_register_press(button_index),
|
||||
false => false,
|
||||
};
|
||||
self.debounce_counter[button_index] = 0;
|
||||
}
|
||||
}
|
||||
@ -148,6 +139,17 @@ where
|
||||
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"))]
|
||||
pub(crate) fn set_scan_counter(&mut self, value: u32) {
|
||||
self.scan_counter = value;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! Keyboard state management and HID report generation.
|
||||
|
||||
use crate::NUMBER_OF_KEYS;
|
||||
use crate::{NUMBER_OF_KEYS, KeyMatrix, KeyReport};
|
||||
use crate::layout;
|
||||
use crate::status::StatusSummary;
|
||||
use usbd_human_interface_device::page::Keyboard;
|
||||
@ -50,8 +50,8 @@ impl KeyboardState {
|
||||
|
||||
pub fn process_scan(
|
||||
&mut self,
|
||||
pressed_keys: [bool; NUMBER_OF_KEYS],
|
||||
) -> [Keyboard; NUMBER_OF_KEYS] {
|
||||
pressed_keys: KeyMatrix,
|
||||
) -> KeyReport {
|
||||
let fn_mode = Self::fn_mode(&pressed_keys);
|
||||
|
||||
for (index, pressed) in pressed_keys.iter().enumerate() {
|
||||
@ -85,6 +85,16 @@ impl KeyboardState {
|
||||
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(
|
||||
&self,
|
||||
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 sticky_toggle_requested = false;
|
||||
|
||||
for (index, button) in self.buttons.iter_mut().enumerate() {
|
||||
let changed = button.pressed != button.previous_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 {
|
||||
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];
|
||||
@ -151,13 +154,17 @@ impl KeyboardState {
|
||||
button.previous_pressed = button.pressed;
|
||||
}
|
||||
|
||||
if sticky_toggle_requested {
|
||||
self.toggle_sticky_state();
|
||||
}
|
||||
|
||||
const STICKY_REPORT_INDEX: usize = 46;
|
||||
report[STICKY_REPORT_INDEX] = self.sticky_key;
|
||||
|
||||
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
|
||||
.iter()
|
||||
.filter(|key_index| pressed_keys[**key_index as usize])
|
||||
|
||||
@ -24,6 +24,10 @@ pub use hardware::{
|
||||
pub use keyboard::{KeyboardState, StickyState};
|
||||
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")]
|
||||
#[unsafe(no_mangle)]
|
||||
static mut __bi_entries_start: u8 = 0;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#![no_main]
|
||||
|
||||
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 fugit::ExtU32;
|
||||
use panic_halt as _;
|
||||
@ -25,6 +25,31 @@ use usbd_human_interface_device::prelude::*;
|
||||
#[used]
|
||||
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]
|
||||
fn main() -> ! {
|
||||
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;
|
||||
unsafe {
|
||||
SUSPENDED_SCAN_COUNTER = (SUSPENDED_SCAN_COUNTER + 1) % 20;
|
||||
SUSPENDED_SCAN_COUNTER == 0
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if usb_tick.wait().is_ok() && should_scan {
|
||||
@ -102,9 +125,8 @@ fn main() -> ! {
|
||||
|
||||
if bootloader::chord_requested(&pressed_keys) {
|
||||
if !usb_suspended {
|
||||
let mut attempts: u8 = 0;
|
||||
while attempts < 3 {
|
||||
let clear_report = [Keyboard::NoEventIndicated; hardware::NUMBER_OF_KEYS];
|
||||
for _ in 0..3 {
|
||||
let clear_report: KeyReport = [Keyboard::NoEventIndicated; hardware::NUMBER_OF_KEYS];
|
||||
match keyboard.device().write_report(clear_report) {
|
||||
Ok(_) => break,
|
||||
Err(UsbHidError::WouldBlock) | Err(UsbHidError::Duplicate) => {
|
||||
@ -112,7 +134,6 @@ fn main() -> ! {
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
attempts = attempts.saturating_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,17 +188,12 @@ fn main() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
let usb_state = usb_dev.state();
|
||||
let was_suspended = usb_suspended;
|
||||
usb_suspended = usb_state == UsbDeviceState::Suspend;
|
||||
|
||||
if was_suspended && !usb_suspended {
|
||||
last_activity_ms = status_time_ms;
|
||||
wake_on_input = false;
|
||||
}
|
||||
|
||||
if !was_suspended && usb_suspended {
|
||||
wake_on_input = true;
|
||||
}
|
||||
handle_usb_state_changes(
|
||||
&usb_dev,
|
||||
&mut usb_suspended,
|
||||
&mut wake_on_input,
|
||||
&mut last_activity_ms,
|
||||
status_time_ms,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,18 +166,17 @@ fn breathe(color: RGB8, elapsed_ms: u32, period_ms: u32) -> RGB8 {
|
||||
if period_ms == 0 {
|
||||
return color;
|
||||
}
|
||||
|
||||
let period = period_ms.max(1);
|
||||
let time_in_period = (elapsed_ms % period) as f32;
|
||||
let period_f = period as f32;
|
||||
let phase = time_in_period / period_f;
|
||||
let phase = (elapsed_ms % period) as f32 / period as f32;
|
||||
let brightness = if phase < 0.5 {
|
||||
1.0 - (phase * 2.0)
|
||||
} else {
|
||||
(phase - 0.5) * 2.0
|
||||
};
|
||||
let clamped = brightness.max(0.0).min(1.0);
|
||||
let ramp = (clamped * 255.0 + 0.5) as u8;
|
||||
scale_color(color, ramp)
|
||||
let brightness_factor = ((brightness.clamp(0.0, 1.0) * 255.0) + 0.5) as u8;
|
||||
|
||||
scale_color(color, brightness_factor)
|
||||
}
|
||||
|
||||
fn scale_color(color: RGB8, factor: u8) -> RGB8 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user