Skip to content

Commit

Permalink
Merge pull request #21 from lonesometraveler/refactor_8
Browse files Browse the repository at this point in the history
Refactor debounce detection to provide granular debounce state information
  • Loading branch information
HaoboGu authored May 20, 2024
2 parents 408bc7f + cc66cc5 commit 6ce0e06
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
37 changes: 28 additions & 9 deletions rmk/src/debounce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ impl DebounceCounter {
}
}

/// Debounce state
pub(crate) enum DebounceState {
Debounced,
InProgress,
HeldHigh,
HeldLow,
Ignored,
}

/// Default per-key debouncer. The debouncing algorithm is same as ZMK's [default debouncer](https://github.com/zmkfirmware/zmk/blob/19613128b901723f7b78c136792d72e6ca7cf4fc/app/module/lib/zmk_debounce/debounce.c)
pub(crate) struct Debouncer<const INPUT_PIN_NUM: usize, const OUTPUT_PIN_NUM: usize> {
last_tick: u32,
Expand All @@ -52,7 +61,10 @@ impl<const INPUT_PIN_NUM: usize, const OUTPUT_PIN_NUM: usize>
out_idx: usize,
pin_state: bool,
key_state: &KeyState,
) -> bool {
) -> DebounceState {
// Use 10khz tick, so the debounce threshold should * 10
const TICK_FREQUENCY: u16 = 10;

// Record debounce state per ms
let cur_tick = Instant::now().as_millis() as u32;
let elapsed_ms = (cur_tick - self.last_tick) as u16;
Expand All @@ -61,19 +73,26 @@ impl<const INPUT_PIN_NUM: usize, const OUTPUT_PIN_NUM: usize>
let counter: &mut DebounceCounter = &mut self.counters[out_idx][in_idx];

if key_state.pressed == pin_state {
// If current key state matches input pin, decrease debounce counter
counter.decrease(elapsed_ms);
} else {
// Use 10khz tick, so the debounce threshold should * 10
if counter.0 < DEBOUNCE_THRESHOLD * 10 {
counter.increase(elapsed_ms);
if pin_state {
DebounceState::HeldHigh
} else {
self.last_tick = cur_tick;
counter.0 = 0;
return true;
DebounceState::HeldLow
}
} else if counter.0 < DEBOUNCE_THRESHOLD * TICK_FREQUENCY {
// If debounce threshold is not exceeded, increase debounce counter
counter.increase(elapsed_ms);
DebounceState::InProgress
} else {
// Debounce threshold is exceeded, reset counter
self.last_tick = cur_tick;
counter.0 = 0;
DebounceState::Debounced
}
} else {
DebounceState::Ignored
}
false
}
}

Expand Down
14 changes: 8 additions & 6 deletions rmk/src/matrix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::debounce::Debouncer;
use crate::debounce::{DebounceState, Debouncer};
use embassy_time::{Duration, Instant, Timer};
use embedded_hal::digital::{InputPin, OutputPin};
use defmt::Format;
Expand Down Expand Up @@ -90,18 +90,20 @@ impl<In: InputPin, Out: OutputPin, const INPUT_PIN_NUM: usize, const OUTPUT_PIN_
Timer::after_micros(1).await;
for (in_idx, in_pin) in self.input_pins.iter_mut().enumerate() {
// Check input pins and debounce
let changed = self.debouncer.detect_change_with_debounce(
let debounce_state = self.debouncer.detect_change_with_debounce(
in_idx,
out_idx,
in_pin.is_high().ok().unwrap_or_default(),
&self.key_states[out_idx][in_idx],
);

if changed {
self.key_states[out_idx][in_idx].toggle_pressed();
match debounce_state {
DebounceState::Debounced => {
self.key_states[out_idx][in_idx].toggle_pressed();
self.key_states[out_idx][in_idx].changed = true;
}
_ => self.key_states[out_idx][in_idx].changed = false,
}

self.key_states[out_idx][in_idx].changed = changed;
}
out_pin.set_low().ok();
}
Expand Down

0 comments on commit 6ce0e06

Please sign in to comment.