better error handling and debugging

This commit is contained in:
2025-07-18 20:31:23 +01:00
parent 321ae584bf
commit 0655fb2724
3 changed files with 93 additions and 57 deletions

1
Cargo.lock generated
View File

@@ -92,6 +92,7 @@ name = "calc-math"
version = "0.1.0"
dependencies = [
"num-traits",
"ufmt",
]
[[package]]

View File

@@ -14,7 +14,7 @@ bench = false
ufmt = "0.2.0"
nb = "1.1.0"
embedded-hal = "1.0"
calc-math = { path = "../calc-math" }
calc-math = { path = "../calc-math", features = ["ufmt"] }
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"

View File

@@ -5,7 +5,10 @@ mod display;
mod keyboard;
mod panic;
use calc_math::{calc::StackCalc, Decimal};
use calc_math::{
calc::{StackCalc, StackCalcError},
Decimal,
};
use display::{DispalyState, SegmentPins, SegmentState, Show};
use keyboard::{Debounce, KeyPress, KeyReadout, Keyboard};
@@ -13,7 +16,6 @@ use arduino_hal::{
adc::channel::{ADC6, ADC7},
hal::port::{PB3, PB4, PC1, PC2, PC3, PD2, PD3, PD4, PD7},
port::{mode::Output, Pin},
prelude::*,
Adc,
};
use ufmt::derive::uDebug;
@@ -89,6 +91,12 @@ impl IOPins {
}
}
#[derive(uDebug)]
pub enum NumberInputError {
SignificantOverflow,
ExponentOverflow,
}
#[derive(Default)]
pub struct NumberInput {
minus: bool,
@@ -105,31 +113,31 @@ impl NumberInput {
*self = Self::default();
}
pub fn input_significant(&mut self, val: u8) -> Result<(), ()> {
pub fn input_significant(&mut self, val: u8) -> Result<(), NumberInputError> {
if val > 9 {
panic!("Bad significatn val");
}
if self.significant_pos >= DISPLAY_SEGMENTS_SIG {
return Err(());
return Err(NumberInputError::SignificantOverflow);
}
self.significant[self.significant_pos] = val;
self.significant_pos += 1;
return Ok(());
}
pub fn input_exponent(&mut self, val: u8) -> Result<(), ()> {
pub fn input_exponent(&mut self, val: u8) -> Result<(), NumberInputError> {
if val > 9 {
panic!("Bad exponent val");
}
if self.exponent_pos >= DISPLAY_SEGMENTS_EXP {
return Err(());
return Err(NumberInputError::ExponentOverflow);
}
self.exponent[self.exponent_pos] = val;
self.exponent_pos += 1;
Ok(())
}
pub fn input(&mut self, val: u8) -> Result<(), ()> {
pub fn input(&mut self, val: u8) -> Result<(), NumberInputError> {
if self.enter_exponent {
self.input_exponent(val)
} else {
@@ -165,13 +173,13 @@ impl NumberInput {
)
}
pub fn set_result(&mut self, dec: Decimal<5, u8>) -> Result<(), ()> {
pub fn set_result(&mut self, dec: Decimal<5, u8>) -> Result<(), NumberInputError> {
let (minus, significant, minus_exponent, exponent) = dec.into_parts();
self.minus = minus;
self.significant = significant;
self.minus_exponent = minus_exponent;
if exponent > 99 {
return Err(());
return Err(NumberInputError::ExponentOverflow);
}
self.exponent[0] = exponent / 10;
self.exponent[1] = exponent - (self.exponent[0] * 10);
@@ -235,6 +243,26 @@ impl TransientState {
}
}
#[derive(uDebug)]
enum CalcluclatorError {
NumberInputError(NumberInputError),
StackCalcError(StackCalcError),
StackOverflow,
InvalidOperation,
}
impl From<NumberInputError> for CalcluclatorError {
fn from(value: NumberInputError) -> Self {
CalcluclatorError::NumberInputError(value)
}
}
impl From<StackCalcError> for CalcluclatorError {
fn from(value: StackCalcError) -> Self {
CalcluclatorError::StackCalcError(value)
}
}
#[derive(uDebug)]
enum CalcluclatorState {
EnterSignificant,
@@ -248,7 +276,7 @@ impl CalcluclatorState {
key: KeyPress,
number_input: &mut NumberInput,
calc: &mut Calc,
) -> Result<CalcluclatorState, ()> {
) -> Result<CalcluclatorState, CalcluclatorError> {
match self {
CalcluclatorState::EnterSignificant => match key {
KeyPress::C => {
@@ -268,7 +296,7 @@ impl CalcluclatorState {
number_input.enter_exponent();
Ok(CalcluclatorState::EnterExponent)
}
_ => Ok(CalcluclatorState::EnterSignificant),
_ => Err(CalcluclatorError::InvalidOperation),
},
CalcluclatorState::EnterExponent => match key {
KeyPress::C => {
@@ -286,58 +314,46 @@ impl CalcluclatorState {
}
KeyPress::E => {
number_input.done();
match calc.push(number_input.to_decimal()) {
Ok(()) => Ok(CalcluclatorState::EnterOperation),
Err(_) => Err(()),
}
calc.push(number_input.to_decimal())?;
Ok(CalcluclatorState::EnterOperation)
}
_ => Ok(CalcluclatorState::EnterExponent),
_ => Err(CalcluclatorError::InvalidOperation),
},
CalcluclatorState::EnterOperation => match key {
KeyPress::Up => todo!(),
KeyPress::C => {
number_input.reset();
calc.reset();
Ok(CalcluclatorState::EnterSignificant)
}
KeyPress::Num(_) => todo!(),
KeyPress::Mul => match calc.mul() {
Ok(dec) => {
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
Err(_) => Err(()),
},
KeyPress::Div => match calc.div() {
Ok(dec) => {
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
Err(_) => Err(()),
},
KeyPress::Plus => match calc.add() {
Ok(dec) => {
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
Err(_) => Err(()),
},
KeyPress::Minus => match calc.sub() {
Ok(dec) => {
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
Err(_) => Err(()),
},
KeyPress::Down => todo!(),
KeyPress::Mul => {
let dec = calc.mul()?;
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
KeyPress::Div => {
let dec = calc.div()?;
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
KeyPress::Plus => {
let dec = calc.add()?;
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
KeyPress::Minus => {
let dec = calc.sub()?;
number_input.set_result(dec)?;
Ok(CalcluclatorState::EnterOperation)
}
KeyPress::E => {
if calc.is_full() {
Err(())
Err(CalcluclatorError::StackOverflow)
} else {
number_input.reset();
Ok(CalcluclatorState::EnterSignificant)
}
}
_ => Err(CalcluclatorError::InvalidOperation),
},
}
}
@@ -350,7 +366,7 @@ fn main() -> ! {
let mut serial = arduino_hal::default_serial!(dp, pins, SERIAL_BAUD);
ufmt::uwriteln!(&mut serial, "Hello from Arduino!").unwrap_infallible();
ufmt::uwriteln!(&mut serial, "Hello from Arduino!").ok();
let mut io = IOPins::new(
pins.d2.into_output(),
@@ -406,22 +422,41 @@ fn main() -> ! {
let key = debounce.input(last_key_readout);
if let Some(key) = &key {
ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible();
}
if let TransientState::Done = state.transient {
if let Some(key) = key {
ufmt::uwriteln!(
&mut serial,
"-> key: {:?} state: {:?}",
key,
state.calculator
)
.ok();
match state.calculator.on_key(key, &mut number_input, &mut calc) {
Ok(new_state) => state.calculator = new_state,
Err(()) => {
Err(err) => {
match err {
CalcluclatorError::StackCalcError(_) => {
number_input.reset();
state.calculator = CalcluclatorState::EnterSignificant;
}
_ => (),
}
ufmt::uwriteln!(&mut serial, "!! error: {:?}", err).ok();
state.transient = TransientState::Err {
timeout: ERROR_TIMEOUT,
};
}
}
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
.unwrap_infallible();
ufmt::uwriteln!(
&mut serial,
"<- state: {:?} stack: {}",
state.calculator,
calc.len()
)
.ok();
for (i, dec) in calc.iter().enumerate() {
ufmt::uwriteln!(&mut serial, "[{}] {}", i, dec).ok();
}
}
} else {
state.transient.on_frame(key)