use core::num::NonZeroU16;
use embassy_time::Instant;
use super::{DebounceState, DebouncerTrait};
use crate::DEBOUNCE_THRESHOLD;
use crate::matrix::KeyState;
#[derive(Copy, Clone, Debug, PartialEq)]
enum DebounceCounter {
Idle,
Debouncing(NonZeroU16),
}
pub struct DefaultDebouncer<const ROW: usize, const COL: usize> {
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::Idle; ROW]; COL],
}
}
}
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,
key_active: bool,
key_state: &KeyState,
) -> DebounceState {
let counter = &mut self.counters[col_idx][row_idx];
if key_state.pressed == key_active {
*counter = DebounceCounter::Idle;
return DebounceState::Ignored;
}
let Some(now) = NonZeroU16::new(Instant::now().as_millis() as u16) else {
return DebounceState::InProgress;
};
match counter {
DebounceCounter::Idle => {
*counter = DebounceCounter::Debouncing(now);
DebounceState::InProgress
}
DebounceCounter::Debouncing(start_time) => {
let elapsed = now.get().wrapping_sub(start_time.get());
if elapsed >= DEBOUNCE_THRESHOLD {
*counter = DebounceCounter::Idle;
DebounceState::Debounced
} else {
DebounceState::InProgress
}
}
}
}
}