From 201dbb26cb355d0cef73082cae43452a768e0ddc Mon Sep 17 00:00:00 2001 From: irriden Date: Tue, 1 Aug 2023 17:14:38 +0000 Subject: [PATCH] sphinx-key: button state machine improvements gets rid of counters overflowing and crashing in debug mode release mode wraps them around reset state machine if unexpected input at any point in the machine's lifetime --- sphinx-key/src/periph/button.rs | 84 +++++++++++++++++++++++++++------ sphinx-key/src/status.rs | 5 +- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/sphinx-key/src/periph/button.rs b/sphinx-key/src/periph/button.rs index 12c514a..e785ff8 100644 --- a/sphinx-key/src/periph/button.rs +++ b/sphinx-key/src/periph/button.rs @@ -9,6 +9,8 @@ const MILLIS: u16 = 10_000; const PAUSE: u16 = 50; +// progression is waiting -> *starting -> reset1a -> reset1 -> reset2a -> reset2 -> reset3 +// state machine initialized at starting pub fn button_loop(gpio9: gpio::Gpio9, tx: mpsc::Sender) { thread::spawn(move || { let mut button = PinDriver::input(gpio9).unwrap(); @@ -16,7 +18,10 @@ pub fn button_loop(gpio9: gpio::Gpio9, tx: mpsc::Sender) { let mut pressed = false; let mut up_times = 0; let mut low_times = 0; - let mut last_status = Status::Starting; + let mut machine = Machine { + tx, + state: Status::Starting, + }; loop { // we are using thread::sleep here to make sure the watchdog isn't triggered thread::sleep(Duration::from_millis(PAUSE.into())); @@ -28,14 +33,34 @@ pub fn button_loop(gpio9: gpio::Gpio9, tx: mpsc::Sender) { } if !pressed { up_times = up_times + 1; + + // back to start after waiting for a button release + if machine.state == Status::Waiting { + machine.update_status(Status::Starting); + } + + // if button release while in reset2, reset + if machine.state == Status::Reset2 { + machine.update_status(Status::Starting); + } + + // advance + if machine.state == Status::Reset1a { + machine.update_status(Status::Reset1); + } + + // if stayed up, advance if PAUSE * up_times > MILLIS { - // stayed up - if last_status == Status::Reset1 { - log::info!("send Status::Reset2!"); - tx.send(Status::Reset2).unwrap(); - last_status = Status::Reset2; + if machine.state == Status::Reset1 { + machine.update_status(Status::Reset2a); } } + + // if stays up for much longer, reset + if PAUSE * up_times > 2 * MILLIS { + machine.update_status(Status::Starting); + up_times = 0; + } } } else { if !pressed { @@ -45,20 +70,49 @@ pub fn button_loop(gpio9: gpio::Gpio9, tx: mpsc::Sender) { } if pressed { low_times = low_times + 1; + + // if button press while in reset1, wait for a release, and reset + if machine.state == Status::Reset1 { + machine.update_status(Status::Waiting); + } + + // advance + if machine.state == Status::Reset2a { + machine.update_status(Status::Reset2); + } + + // if stayed held down, advance if PAUSE * low_times > MILLIS { - // stayed held down - if last_status == Status::Reset2 { - log::info!("send Status::Reset3!"); - tx.send(Status::Reset3).unwrap(); - last_status = Status::Reset3; - } else if last_status != Status::Reset1 && last_status != Status::Reset3 { - log::info!("send Status::Reset1!"); - tx.send(Status::Reset1).unwrap(); - last_status = Status::Reset1; + if machine.state == Status::Reset2 { + machine.update_status(Status::Reset3); + } else if machine.state == Status::Starting { + machine.update_status(Status::Reset1a); } } + + // if stayed held down for much longer, wait for a release, and reset + if PAUSE * low_times > 2 * MILLIS { + machine.update_status(Status::Waiting); + low_times = 0; + } } } } }); } + +struct Machine { + tx: mpsc::Sender, + state: Status, +} + +impl Machine { + fn new(tx: mpsc::Sender, state: Status) -> Machine { + Self { tx, state } + } + fn update_status(&mut self, new_state: Status) { + log::info!("send {:?}", new_state); + self.tx.send(new_state).unwrap(); + self.state = new_state; + } +} diff --git a/sphinx-key/src/status.rs b/sphinx-key/src/status.rs index fa7c684..6f904b4 100644 --- a/sphinx-key/src/status.rs +++ b/sphinx-key/src/status.rs @@ -1,5 +1,6 @@ -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Copy)] pub enum Status { + Waiting, Starting, MountingSDCard, SyncingTime, @@ -10,7 +11,9 @@ pub enum Status { Connected, Signing, Ota, + Reset1a, Reset1, + Reset2a, Reset2, Reset3, }