82 lines
2.2 KiB
Rust
82 lines
2.2 KiB
Rust
use embassy_futures::select::select_array;
|
|
use embassy_time::{Duration, Timer};
|
|
use embedded_hal::digital::InputPin;
|
|
use embedded_hal_async::digital::Wait;
|
|
use esp_hal::gpio::Input;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum NavCommand {
|
|
NextCard,
|
|
PrevCard,
|
|
Select,
|
|
ScanTag,
|
|
}
|
|
|
|
pub struct Inputs {
|
|
pub up: Input<'static>,
|
|
pub down: Input<'static>,
|
|
pub left: Input<'static>,
|
|
pub right: Input<'static>,
|
|
pub back: Input<'static>,
|
|
pub ok: Input<'static>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum ButtonAction {
|
|
Up = 0,
|
|
Down = 1,
|
|
Left = 2,
|
|
Right = 3,
|
|
Ok = 4,
|
|
Back = 5,
|
|
}
|
|
|
|
impl Inputs {
|
|
pub async fn wait_for_press(&mut self) -> ButtonAction {
|
|
let (_, index) = select_array([
|
|
wait_for_button(&mut self.up),
|
|
wait_for_button(&mut self.down),
|
|
wait_for_button(&mut self.left),
|
|
wait_for_button(&mut self.right),
|
|
wait_for_button(&mut self.ok),
|
|
wait_for_button(&mut self.back),
|
|
])
|
|
.await;
|
|
|
|
match index {
|
|
0 => ButtonAction::Up,
|
|
1 => ButtonAction::Down,
|
|
2 => ButtonAction::Left,
|
|
3 => ButtonAction::Right,
|
|
4 => ButtonAction::Ok,
|
|
5 => ButtonAction::Back,
|
|
id => panic!("Unknown button {id} pressed"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Waits for a button press, filtering out fast transients and mechanical bounce.
|
|
async fn wait_for_button<P>(pin: &mut P)
|
|
where
|
|
P: Wait + InputPin,
|
|
{
|
|
loop {
|
|
// 1. Wait for the hardware interrupt (could be a real press or crosstalk)
|
|
let _ = pin.wait_for_falling_edge().await;
|
|
|
|
// 2. Debounce window: let the noise settle
|
|
Timer::after(Duration::from_millis(30)).await;
|
|
|
|
// 3. Verify the pin is still held down
|
|
// (Adapt unwrap() based on your specific HAL's Error type)
|
|
if pin.is_low().unwrap_or(false) {
|
|
// OPTIONAL: Wait for the button to be released before returning
|
|
// so holding it down doesn't spam triggers.
|
|
// let _ = pin.wait_for_rising_edge().await;
|
|
// Timer::after(Duration::from_millis(30)).await;
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|