Skip to main content

rmk_q6_he_ansi/matrix/
encoder_switch.rs

1use embassy_stm32::{exti::ExtiInput, mode::Async};
2use embassy_time::{Duration, Timer};
3use rmk::{event::KeyboardEvent, macros::input_device};
4
5/// Debounced encoder switch exposed as an input device.
6#[input_device(publish = KeyboardEvent)]
7pub struct EncoderSwitch<'peripherals> {
8    /// Logical column index reported to the input system.
9    col: u8,
10    /// Debounce duration applied to state changes.
11    debounce: Duration,
12    /// Last debounced logical state of the switch.
13    last_pressed: bool,
14    /// External interrupt–backed input pin for the switch.
15    pin: ExtiInput<'peripherals, Async>,
16    /// Logical row index reported to the input system.
17    row: u8,
18}
19
20impl<'peripherals> EncoderSwitch<'peripherals> {
21    /// Create a new encoder switch input wrapper.
22    #[must_use]
23    pub const fn new(pin: ExtiInput<'peripherals, Async>, row: u8, col: u8) -> Self {
24        Self { pin, row, col, last_pressed: false, debounce: Duration::from_millis(15) }
25    }
26
27    /// Wait for the next debounced encoder switch event.
28    async fn read_keyboard_event(&mut self) -> KeyboardEvent {
29        loop {
30            self.pin.wait_for_any_edge().await;
31            Timer::after(self.debounce).await;
32
33            let pressed = self.pin.is_low();
34            if pressed != self.last_pressed {
35                self.last_pressed = pressed;
36                return KeyboardEvent::key(self.row, self.col, pressed);
37            }
38        }
39    }
40}