use embassy_time::Instant;
use super::{DebounceState, DebouncerTrait};
use crate::DEBOUNCE_THRESHOLD;
use crate::matrix::KeyState;
#[derive(Copy, Clone, Debug)]
struct DebounceCounter(u16);
impl DebounceCounter {
fn increase(&mut self, elapsed_ms: u16) {
if u16::MAX - self.0 <= elapsed_ms {
self.0 = u16::MAX;
} else {
self.0 += elapsed_ms;
}
}
fn decrease(&mut self, elapsed_ms: u16) {
if elapsed_ms > self.0 {
self.0 = 0;
} else {
self.0 -= elapsed_ms;
}
}
}
pub struct DefaultDebouncer<const ROW: usize, const COL: usize> {
last_ms: u32,
counters: [[DebounceCounter; ROW]; COL],
}
impl<const ROW: usize, const COL: usize> Default for DefaultDebouncer<ROW, COL> {
fn default() -> Self {
Self::new()
}
}
impl<const ROW: usize, const COL: usize> DefaultDebouncer<ROW, COL> {
pub fn new() -> Self {
DefaultDebouncer {
counters: [[DebounceCounter(0); ROW]; COL],
last_ms: 0,
}
}
}
impl<const ROW: usize, const COL: usize> DebouncerTrait<ROW, COL> for DefaultDebouncer<ROW, COL> {
fn detect_change_with_debounce(
&mut self,
row_idx: usize,
col_idx: usize,
pin_state: bool,
key_state: &KeyState,
) -> DebounceState {
let cur_ms = Instant::now().as_millis() as u32;
let elapsed_ms = (cur_ms - self.last_ms) as u16;
if elapsed_ms > 0 {
let counter: &mut DebounceCounter = &mut self.counters[col_idx][row_idx];
if key_state.pressed == pin_state {
counter.decrease(elapsed_ms);
if counter.0 > 0 {
DebounceState::InProgress
} else {
DebounceState::Ignored
}
} else if counter.0 < DEBOUNCE_THRESHOLD {
counter.increase(elapsed_ms);
DebounceState::InProgress
} else {
self.last_ms = cur_ms;
counter.0 = 0;
DebounceState::Debounced
}
} else {
DebounceState::Ignored
}
}
}