diff --git a/sphinx-key/src/periph/button.rs b/sphinx-key/src/periph/button.rs index 12c514a..285e204 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,7 @@ 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::new(tx, 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 +30,38 @@ 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 machine.state == Status::Reset3a { + machine.update_status(Status::Reset3); + } + + // 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 +71,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::Reset3a); + } 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..f71c556 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,10 @@ pub enum Status { Connected, Signing, Ota, + Reset1a, Reset1, + Reset2a, Reset2, + Reset3a, Reset3, }