better error handling and debugging
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -92,6 +92,7 @@ name = "calc-math"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"ufmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -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"
|
||||
|
||||
147
src/main.rs
147
src/main.rs
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user