mirror of
https://github.com/stakwork/sphinx-key.git
synced 2026-02-01 13:54:19 +01:00
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
This commit is contained in:
@@ -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<Status>) {
|
||||
thread::spawn(move || {
|
||||
let mut button = PinDriver::input(gpio9).unwrap();
|
||||
@@ -16,7 +18,10 @@ pub fn button_loop(gpio9: gpio::Gpio9, tx: mpsc::Sender<Status>) {
|
||||
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<Status>) {
|
||||
}
|
||||
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<Status>) {
|
||||
}
|
||||
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<Status>,
|
||||
state: Status,
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
fn new(tx: mpsc::Sender<Status>, 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user