From 483f295e570efa20ab7e53a7662fab60bda7b17e Mon Sep 17 00:00:00 2001 From: Danny August Ramaputra Date: Thu, 5 Sep 2024 22:53:15 +0900 Subject: [PATCH] add: basic status led peripheral --- src/keyboard/default/mod.rs | 1 + src/keyboard/kb_dev/mod.rs | 1 + src/keyboard/mod.rs | 2 + src/keyboard/quadax_rift/mod.rs | 15 ++++++- src/main.rs | 19 ++++++++- src/status.rs | 73 +++++++++++++++++++++++++++++++++ 6 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/status.rs diff --git a/src/keyboard/default/mod.rs b/src/keyboard/default/mod.rs index 765af57..c3e33be 100644 --- a/src/keyboard/default/mod.rs +++ b/src/keyboard/default/mod.rs @@ -99,6 +99,7 @@ impl Configurator for Keyboard { heartbeat_led, rgb_matrix, oled_display: None, + status_led: None, }, None, ) diff --git a/src/keyboard/kb_dev/mod.rs b/src/keyboard/kb_dev/mod.rs index cd6f1d5..4ea98bc 100644 --- a/src/keyboard/kb_dev/mod.rs +++ b/src/keyboard/kb_dev/mod.rs @@ -115,6 +115,7 @@ impl Configurator for Keyboard { heartbeat_led, rgb_matrix, oled_display: None, + status_led: None, }, None, ) diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 057730b..b51d3ba 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -14,6 +14,7 @@ use crate::{ processor::{events::rgb::RGBMatrix, mapper::InputMap}, remote::transport::uart::{UartReceiver, UartSender}, rotary::RotaryEncoder, + status::StatusLED, }; pub use selected_keyboard::Keyboard; @@ -74,6 +75,7 @@ pub struct Configuration { >, >, >, + pub status_led: Option, } impl Configuration { diff --git a/src/keyboard/quadax_rift/mod.rs b/src/keyboard/quadax_rift/mod.rs index 95221e9..638eee4 100644 --- a/src/keyboard/quadax_rift/mod.rs +++ b/src/keyboard/quadax_rift/mod.rs @@ -1,8 +1,7 @@ pub mod layout; -use core::cell::RefCell; - use alloc::{boxed::Box, rc::Rc}; +use core::cell::RefCell; use hal::{ fugit::{HertzU32, RateExtU32}, gpio, pac, pio, pwm, uart, @@ -20,6 +19,7 @@ use crate::{ remote::transport::uart::{UartReceiver, UartSender}, rotary::{Mode, RotaryEncoder}, split::{self, SideDetector}, + status::StatusLED, }; const ENABLE_HEARTBEAT_LED: bool = true; @@ -27,6 +27,7 @@ const ENABLE_KEY_MATRIX: bool = true; const ENABLE_ROTARY_ENCODER: bool = true; const ENABLE_RGB_MATRIX: bool = true; const ENABLE_OLED_SCREEN: bool = true; +const ENABLE_STATUS_LED: bool = true; pub struct Keyboard {} @@ -125,6 +126,15 @@ impl Configurator for Keyboard { None }; + let status_led = if ENABLE_STATUS_LED { + Some(StatusLED::new( + Box::new(pins.gpio24.into_push_pull_output()), + Box::new(pins.gpio25.into_push_pull_output()), + )) + } else { + None + }; + let mut uart_peripheral = uart::UartPeripheral::new( uart0, (pins.gpio0.into_function(), pins.gpio1.into_function()), @@ -154,6 +164,7 @@ impl Configurator for Keyboard { heartbeat_led, rgb_matrix, oled_display, + status_led, }, Some((uart_sender, uart_receiver)), ) diff --git a/src/main.rs b/src/main.rs index 7a466dc..71473f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ mod processor; mod remote; mod rotary; mod split; +mod status; mod util; #[macro_use] @@ -87,6 +88,7 @@ mod kb { }, rotary::RotaryEncoder, split, + status::StatusLED, }; rp2040_timer_monotonic!(Mono); @@ -303,6 +305,10 @@ mod kb { split::get_self_side() ); + if let Some(ref mut status_led) = config.status_led { + status_led.set_link(true); + } + if let Some(ref mut display) = config.oled_display { display.clear(); display @@ -322,7 +328,13 @@ mod kb { input_sender, ) .ok(); - master_processor::spawn(input_receiver, keys_sender, frame_sender).ok(); + master_processor::spawn( + input_receiver, + keys_sender, + frame_sender, + config.status_led, + ) + .ok(); rgb_matrix_renderer::spawn(config.rgb_matrix, frame_receiver).ok(); } split::Mode::Slave => { @@ -470,6 +482,7 @@ mod kb { >, mut keys_sender: Sender<'static, Vec, KEYS_CHANNEL_BUFFER_SIZE>, frame_sender: Sender<'static, Box, 1>, + mut status_led: Option, ) { defmt::info!("master_processor()"); let input_processors: &mut [&mut dyn InputProcessor< @@ -509,6 +522,10 @@ mod kb { }); } + if let Some(ref mut status_led) = status_led { + status_led.update_activity(!events.is_empty()); + } + if events_processors .iter_mut() .try_for_each(|p| p.process(&mut events)) diff --git a/src/status.rs b/src/status.rs new file mode 100644 index 0000000..c647ddb --- /dev/null +++ b/src/status.rs @@ -0,0 +1,73 @@ +use alloc::boxed::Box; +use embedded_hal::digital::OutputPin; +use hal::gpio; +use rtic_monotonics::rp2040::prelude::*; + +use crate::kb::Mono; + +const ACTIVITY_UPDATE_PERIOD_TICK: u64 = 5_000; +const ACTIVITY_DELAY_PERIOD_TICK: u64 = 300_000; + +pub struct StatusLED { + link_led: Box + Sync + Send>, + activity_led: Box + Sync + Send>, + activity_led_state: gpio::PinState, + activity_last_update_tick: u64, + activity_last_active_tick: u64, + counter: u16, +} + +impl StatusLED { + pub fn new( + mut link_led: Box + Send + Sync>, + mut activity_led: Box + Send + Sync>, + ) -> Self { + link_led.set_low().unwrap(); + activity_led.set_low().unwrap(); + + StatusLED { + link_led, + activity_led, + activity_led_state: gpio::PinState::High, + activity_last_update_tick: 0, + activity_last_active_tick: 0, + counter: 0, + } + } + + pub fn set_link(&mut self, enable: bool) { + self.link_led + .set_state(if enable { + gpio::PinState::High + } else { + gpio::PinState::Low + }) + .unwrap(); + } + + pub fn update_activity(&mut self, active: bool) { + let now_tick = Mono::now().ticks(); + if now_tick - self.activity_last_update_tick < ACTIVITY_UPDATE_PERIOD_TICK { + return; + } + self.activity_last_update_tick = now_tick; + self.counter = self.counter.wrapping_add(1); + if active { + self.activity_last_active_tick = now_tick; + } + + self.activity_led_state = + if active || now_tick - self.activity_last_active_tick < ACTIVITY_DELAY_PERIOD_TICK { + if self.counter % 12 < 6 { + gpio::PinState::Low + } else { + gpio::PinState::High + } + } else { + gpio::PinState::High + }; + self.activity_led + .set_state(self.activity_led_state) + .unwrap(); + } +}