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

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