A step sequencer for Adafruit's RP2040-based macropad
at main 56 lines 1.5 kB view raw
1use core::future::IntoFuture; 2 3use embassy_futures::select::{Either, select}; 4use embassy_time::{Duration, Timer}; 5 6use crate::debounced_button::DebouncedButton; 7 8pub struct ToggleWithHold<'a> { 9 button: DebouncedButton<'a>, 10 pub is_held: bool, 11 pub is_pressed: bool, 12 hold_threshold: Duration, 13 timer: Option<Timer>, 14} 15 16impl<'a> ToggleWithHold<'a> { 17 pub fn new(button: DebouncedButton<'a>, hold_threshold: Duration) -> Self { 18 ToggleWithHold { 19 button, 20 is_pressed: false, 21 is_held: false, 22 hold_threshold, 23 timer: None, 24 } 25 } 26 27 pub async fn on_change(&mut self) { 28 let button_future = self.button.on_change(); 29 let timer_future = if let Some(timer) = self.timer.as_mut() { 30 &mut timer.into_future() 31 } else { 32 &mut Timer::after_secs(31536000) // one year, arbitrarily large 33 }; 34 35 self.is_pressed = match select(button_future, timer_future).await { 36 Either::First(pressed) => { 37 self.timer = if pressed { 38 Some(Timer::after(self.hold_threshold)) 39 } else { 40 None 41 }; 42 43 if !pressed { 44 self.is_held = false; 45 } 46 47 pressed 48 } 49 Either::Second(_) => { 50 self.is_held = true; 51 self.timer = None; 52 true 53 } 54 }; 55 } 56}