transient state keeps calculator state

This commit is contained in:
2025-07-18 20:31:23 +01:00
parent f4dde687cf
commit 321ae584bf

View File

@@ -204,135 +204,128 @@ impl Show for NumberInput {
} }
#[derive(uDebug)] #[derive(uDebug)]
enum State { struct State {
Trans(TransState), transient: TransientState,
Calc(CalcState), calculator: CalcluclatorState,
} }
#[derive(uDebug)] #[derive(uDebug)]
enum TransState { enum TransientState {
Done,
Err { timeout: usize }, Err { timeout: usize },
} }
impl TransState { impl TransientState {
fn on_frame( fn on_frame(&mut self, key: Option<KeyPress>) {
&mut self,
key: Option<KeyPress>,
number_input: &mut NumberInput,
calc: &mut Calc,
) -> Option<CalcState> {
match self { match self {
TransState::Err { timeout: 0 } => { TransientState::Err { timeout: 0 } => {
number_input.reset(); *self = TransientState::Done;
calc.reset();
Some(CalcState::EnterSignificant)
} }
TransState::Err { timeout } => { TransientState::Err { timeout } => {
*timeout -= 1; *timeout -= 1;
match key { match key {
Some(KeyPress::C) => { Some(KeyPress::C) => {
number_input.reset(); *self = TransientState::Done;
calc.reset();
Some(CalcState::EnterSignificant)
} }
_ => None, _ => (),
} }
} }
TransientState::Done => (),
} }
} }
} }
#[derive(uDebug)] #[derive(uDebug)]
enum CalcState { enum CalcluclatorState {
EnterSignificant, EnterSignificant,
EnterExponent, EnterExponent,
EnterOperation, EnterOperation,
} }
impl CalcState { impl CalcluclatorState {
fn on_key( fn on_key(
&self, &self,
key: KeyPress, key: KeyPress,
number_input: &mut NumberInput, number_input: &mut NumberInput,
calc: &mut Calc, calc: &mut Calc,
) -> Result<CalcState, ()> { ) -> Result<CalcluclatorState, ()> {
match self { match self {
CalcState::EnterSignificant => match key { CalcluclatorState::EnterSignificant => match key {
KeyPress::C => { KeyPress::C => {
number_input.reset(); number_input.reset();
calc.reset(); calc.reset();
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
KeyPress::Num(val) => { KeyPress::Num(val) => {
number_input.input(val)?; number_input.input(val)?;
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
KeyPress::Minus => { KeyPress::Minus => {
number_input.toggle_minus(); number_input.toggle_minus();
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
KeyPress::E => { KeyPress::E => {
number_input.enter_exponent(); number_input.enter_exponent();
Ok(CalcState::EnterExponent) Ok(CalcluclatorState::EnterExponent)
} }
_ => Ok(CalcState::EnterSignificant), _ => Ok(CalcluclatorState::EnterSignificant),
}, },
CalcState::EnterExponent => match key { CalcluclatorState::EnterExponent => match key {
KeyPress::C => { KeyPress::C => {
number_input.reset(); number_input.reset();
calc.reset(); calc.reset();
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
KeyPress::Num(val) => { KeyPress::Num(val) => {
number_input.input(val)?; number_input.input(val)?;
Ok(CalcState::EnterExponent) Ok(CalcluclatorState::EnterExponent)
} }
KeyPress::Minus => { KeyPress::Minus => {
number_input.toggle_minus(); number_input.toggle_minus();
Ok(CalcState::EnterExponent) Ok(CalcluclatorState::EnterExponent)
} }
KeyPress::E => { KeyPress::E => {
number_input.done(); number_input.done();
match calc.push(number_input.to_decimal()) { match calc.push(number_input.to_decimal()) {
Ok(()) => Ok(CalcState::EnterOperation), Ok(()) => Ok(CalcluclatorState::EnterOperation),
Err(_) => Err(()), Err(_) => Err(()),
} }
} }
_ => Ok(CalcState::EnterExponent), _ => Ok(CalcluclatorState::EnterExponent),
}, },
CalcState::EnterOperation => match key { CalcluclatorState::EnterOperation => match key {
KeyPress::Up => todo!(), KeyPress::Up => todo!(),
KeyPress::C => { KeyPress::C => {
number_input.reset(); number_input.reset();
calc.reset(); calc.reset();
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
KeyPress::Num(_) => todo!(), KeyPress::Num(_) => todo!(),
KeyPress::Mul => match calc.mul() { KeyPress::Mul => match calc.mul() {
Ok(dec) => { Ok(dec) => {
number_input.set_result(dec)?; number_input.set_result(dec)?;
Ok(CalcState::EnterOperation) Ok(CalcluclatorState::EnterOperation)
} }
Err(_) => Err(()), Err(_) => Err(()),
}, },
KeyPress::Div => match calc.div() { KeyPress::Div => match calc.div() {
Ok(dec) => { Ok(dec) => {
number_input.set_result(dec)?; number_input.set_result(dec)?;
Ok(CalcState::EnterOperation) Ok(CalcluclatorState::EnterOperation)
} }
Err(_) => Err(()), Err(_) => Err(()),
}, },
KeyPress::Plus => match calc.add() { KeyPress::Plus => match calc.add() {
Ok(dec) => { Ok(dec) => {
number_input.set_result(dec)?; number_input.set_result(dec)?;
Ok(CalcState::EnterOperation) Ok(CalcluclatorState::EnterOperation)
} }
Err(_) => Err(()), Err(_) => Err(()),
}, },
KeyPress::Minus => match calc.sub() { KeyPress::Minus => match calc.sub() {
Ok(dec) => { Ok(dec) => {
number_input.set_result(dec)?; number_input.set_result(dec)?;
Ok(CalcState::EnterOperation) Ok(CalcluclatorState::EnterOperation)
} }
Err(_) => Err(()), Err(_) => Err(()),
}, },
@@ -342,7 +335,7 @@ impl CalcState {
Err(()) Err(())
} else { } else {
number_input.reset(); number_input.reset();
Ok(CalcState::EnterSignificant) Ok(CalcluclatorState::EnterSignificant)
} }
} }
}, },
@@ -391,7 +384,10 @@ fn main() -> ! {
number_input.show(&mut display); number_input.show(&mut display);
let mut calc = Calc::default(); let mut calc = Calc::default();
let mut state = State::Calc(CalcState::EnterSignificant); let mut state = State {
transient: TransientState::Done,
calculator: CalcluclatorState::EnterSignificant,
};
loop { loop {
let mut last_key_readout: Option<KeyReadout> = None; let mut last_key_readout: Option<KeyReadout> = None;
@@ -414,39 +410,28 @@ fn main() -> ! {
ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible(); ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible();
} }
match &mut state { if let TransientState::Done = state.transient {
State::Trans(trans_state) => { if let Some(key) = key {
if let Some(calc_state) = trans_state.on_frame(key, &mut number_input, &mut calc) { match state.calculator.on_key(key, &mut number_input, &mut calc) {
state = State::Calc(calc_state); Ok(new_state) => state.calculator = new_state,
} Err(()) => {
} state.transient = TransientState::Err {
State::Calc(calc_state) => { timeout: ERROR_TIMEOUT,
if let Some(key) = key { };
match calc_state.on_key(key, &mut number_input, &mut calc) {
Ok(new_state) => *calc_state = new_state,
Err(()) => {
state = State::Trans(TransState::Err {
timeout: ERROR_TIMEOUT,
});
}
} }
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
.unwrap_infallible();
} }
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
.unwrap_infallible();
} }
} else {
state.transient.on_frame(key)
} }
match &state { match &state.transient {
State::Trans(_) => display.error(), TransientState::Done => number_input.show(&mut display),
State::Calc(_) => number_input.show(&mut display), TransientState::Err { .. } => display.error(),
} }
arduino_hal::delay_ms(1); arduino_hal::delay_ms(1);
} }
// loop {
// led.toggle();
// arduino_hal::delay_ms(1000);
// ufmt::uwrite!(&mut serial, ".").unwrap_infallible();
// }
} }