use crate::navigation::state::NavigationState; use crate::views::view::View; use crate::{display::primary_lcd::PrimaryLcdDisplay, navigation::inputs::Inputs}; use embassy_futures::select::Either6; use embassy_futures::select::select6; use embassy_time::{Duration, Timer}; const DEBOUNCE_DURATION_MILLIS: u64 = 100; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Action { Up, Down, Left, Right, Ok, Back, } pub trait Navigable { fn display( &self, display: &mut PrimaryLcdDisplay<'static>, ) -> impl core::future::Future + Send; fn handle_input(&self, input: Action) -> impl core::future::Future + Send; } #[embassy_executor::task] pub async fn run(mut inputs: Inputs, display: &'static mut PrimaryLcdDisplay<'static>) { log::info!("starting navigation"); let mut state = NavigationState::new(); state.screens.last().unwrap().display(display).await; loop { let selection = select6( inputs.up.wait_for_low(), inputs.down.wait_for_low(), inputs.left.wait_for_low(), inputs.right.wait_for_low(), inputs.ok.wait_for_low(), inputs.back.wait_for_low(), ) .await; let action = match selection { Either6::First(_) => Action::Up, Either6::Second(_) => Action::Down, Either6::Third(_) => Action::Left, Either6::Fourth(_) => Action::Right, Either6::Fifth(_) => Action::Ok, Either6::Sixth(_) => Action::Back, }; log::info!("Action: {:?}", action); let screen = match action { Action::Back => state.back(), _ => { state .screens .last() .expect("no screen on stack") .handle_input(action) .await } }; screen.display(display).await; state.screens.push(screen); Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await; } }