Files

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;
}
}
}