result state, prompts, and error display handling

This commit is contained in:
2025-07-18 20:31:23 +01:00
parent 804964cb8d
commit d3fcb507a0
2 changed files with 149 additions and 43 deletions

View File

@@ -5,6 +5,8 @@ use arduino_hal::{
port::{mode::Output, Pin},
};
use crate::DISPLAY_SEGMENTS;
pub struct SegmentPins {
kd_seg_a: Pin<Output, PD5>,
kd_seg_b: Pin<Output, PB0>,
@@ -83,7 +85,10 @@ impl SegmentPins {
pub enum SegmentState {
Num(u8, bool),
Minus,
Prompt(bool),
Dot,
O,
P,
Off,
}
@@ -162,7 +167,7 @@ impl SegmentState {
seg.set_f();
seg.set_g();
}
_ => panic!("Can't dispaly {}", no),
_ => panic!("SegmentState::Num out of range"),
}
if *dp {
seg.set_dp()
@@ -170,12 +175,33 @@ impl SegmentState {
}
SegmentState::Minus => seg.set_g(),
SegmentState::Dot => seg.set_dp(),
SegmentState::Prompt(dot) => {
seg.set_d();
if *dot {
seg.set_dp()
}
}
SegmentState::O => {
seg.set_a();
seg.set_b();
seg.set_c();
seg.set_d();
seg.set_e();
seg.set_f();
}
SegmentState::P => {
seg.set_a();
seg.set_b();
seg.set_g();
seg.set_e();
seg.set_f();
}
SegmentState::Off => (),
}
}
}
pub struct DispalyState([SegmentState; 9]);
pub struct DispalyState([SegmentState; DISPLAY_SEGMENTS]);
impl Default for DispalyState {
fn default() -> DispalyState {
@@ -214,11 +240,25 @@ impl DispalyState {
}
impl DispalyState {
fn set(&mut self, seg: [SegmentState; 9]) {
fn set(&mut self, seg: [SegmentState; DISPLAY_SEGMENTS]) {
self.0 = seg;
}
fn busy(&mut self) {
pub fn prompt(&mut self) {
self.set([
SegmentState::Prompt(false),
SegmentState::Prompt(true),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
SegmentState::Prompt(false),
])
}
pub fn error(&mut self) {
self.set([
SegmentState::Off,
SegmentState::Dot,
@@ -231,6 +271,20 @@ impl DispalyState {
SegmentState::Off,
])
}
pub fn operation(&mut self) {
self.set([
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
SegmentState::O,
SegmentState::P,
SegmentState::Off,
SegmentState::Off,
SegmentState::Off,
])
}
}
// Show data on segment display

View File

@@ -24,6 +24,15 @@ const SERIAL_BAUD: u32 = 115200;
pub const KEYBOARD_ADC_THRESHOLD: u16 = 500;
// Number of key presses to record for debounce
pub const DEBOUNCE_DEPTH: usize = 4;
// Display error for number of loops
pub const ERROR_TIMEOUT: usize = 20;
// Number of physical segment displays
pub const DISPLAY_SEGMENTS: usize = 9;
pub const DISPLAY_SEGMENTS_SIG: usize = 5;
pub const DISPLAY_SEGMENT_SIG_MINUS: usize = 0;
pub const DISPLAY_SEGMENTS_EXP: usize = 2;
pub const DISPLAY_SEGMENT_EXP_MINUS: usize = 6;
struct IOSelect<'p> {
display_no: usize,
@@ -81,9 +90,9 @@ impl IOPins {
#[derive(Default)]
pub struct NumberInput {
minus: bool,
significant: [u8; 5],
significant: [u8; DISPLAY_SEGMENTS_SIG],
minus_exponent: bool,
exponent: [u8; 2],
exponent: [u8; DISPLAY_SEGMENTS_EXP],
enter_exponent: bool,
significant_pos: usize,
exponent_pos: usize,
@@ -98,7 +107,7 @@ impl NumberInput {
if val > 9 {
panic!("Bad significatn val");
}
if self.significant_pos >= 5 {
if self.significant_pos >= DISPLAY_SEGMENTS_SIG {
return Err(());
}
self.significant[self.significant_pos] = val;
@@ -110,7 +119,7 @@ impl NumberInput {
if val > 9 {
panic!("Bad exponent val");
}
if self.exponent_pos >= 2 {
if self.exponent_pos >= DISPLAY_SEGMENTS_EXP {
return Err(());
}
self.exponent[self.exponent_pos] = val;
@@ -126,10 +135,15 @@ impl NumberInput {
}
}
pub fn toggle_enter_exponent(&mut self) {
self.significant_pos = 0;
self.exponent_pos = 0;
self.enter_exponent = !self.enter_exponent;
pub fn enter_exponent(&mut self) {
self.significant_pos = DISPLAY_SEGMENTS_SIG;
self.enter_exponent = true;
}
pub fn done(&mut self) {
self.significant_pos = DISPLAY_SEGMENTS_SIG;
self.exponent_pos = DISPLAY_SEGMENTS_EXP;
self.enter_exponent = false;
}
pub fn toggle_minus(&mut self) {
@@ -149,35 +163,41 @@ impl NumberInput {
)
}
pub fn set_decimal(&mut self, dec: Decimal<5, u8>) {
pub fn set_result(&mut self, dec: Decimal<5, u8>) -> Result<(), ()> {
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(());
}
self.exponent[0] = exponent / 10;
self.exponent[1] = exponent - exponent / 10;
self.exponent[1] = exponent - (self.exponent[0] * 10);
self.done();
Ok(())
}
}
impl Show for NumberInput {
fn show(&self, display: &mut DispalyState) {
display[0] = if self.minus {
display.prompt();
display[DISPLAY_SEGMENT_SIG_MINUS] = if self.minus {
SegmentState::Minus
} else {
SegmentState::Off
};
display[1] = SegmentState::Num(self.significant[0], true);
display[2] = SegmentState::Num(self.significant[1], false);
display[3] = SegmentState::Num(self.significant[2], false);
display[4] = SegmentState::Num(self.significant[3], false);
display[5] = SegmentState::Num(self.significant[4], false);
display[6] = if self.minus_exponent {
for i in 0..self.significant_pos {
display[DISPLAY_SEGMENT_SIG_MINUS + 1 + i] =
SegmentState::Num(self.significant[i], i == 0);
}
display[DISPLAY_SEGMENT_EXP_MINUS] = if self.minus_exponent {
SegmentState::Minus
} else {
SegmentState::Off
};
display[7] = SegmentState::Num(self.exponent[0], false);
display[8] = SegmentState::Num(self.exponent[1], false);
for i in 0..self.exponent_pos {
display[DISPLAY_SEGMENT_EXP_MINUS + 1 + i] = SegmentState::Num(self.exponent[i], false);
}
}
}
@@ -186,7 +206,8 @@ enum State {
EnterSignificant,
EnterExponent,
EnterOperation,
Err,
Result,
Err { timeout: usize },
}
#[arduino_hal::entry]
@@ -247,9 +268,37 @@ fn main() -> ! {
io_select.set_off();
}
match &mut state {
State::Err { timeout } if *timeout == 0 => {
number_input.reset();
calc.reset();
state = State::EnterSignificant;
number_input.show(&mut display);
ufmt::uwriteln!(&mut serial, "err timout state: {:?}", state).unwrap_infallible();
}
State::Err { timeout } => {
*timeout -= 1;
}
_ => (),
}
if let Some(key) = debounce.input(last_key_readout) {
ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible();
let res = match state {
let res = match &mut state {
State::Result => match key {
KeyPress::C => {
number_input.reset();
calc.reset();
state = State::EnterSignificant;
Ok(())
}
KeyPress::E => {
number_input.reset();
state = State::EnterSignificant;
Ok(())
}
_ => Ok(()),
},
State::EnterSignificant => match key {
KeyPress::C => {
number_input.reset();
@@ -259,7 +308,7 @@ fn main() -> ! {
KeyPress::Num(val) => number_input.input(val),
KeyPress::Minus => Ok(number_input.toggle_minus()),
KeyPress::E => {
number_input.toggle_enter_exponent();
number_input.enter_exponent();
state = State::EnterExponent;
Ok(())
}
@@ -275,7 +324,7 @@ fn main() -> ! {
KeyPress::Num(val) => number_input.input(val),
KeyPress::Minus => Ok(number_input.toggle_minus()),
KeyPress::E => {
number_input.toggle_enter_exponent();
number_input.done();
match calc.push(number_input.to_decimal()) {
Ok(()) => {
number_input.reset();
@@ -302,40 +351,36 @@ fn main() -> ! {
KeyPress::Num(_) => todo!(),
KeyPress::Mul => match calc.mul() {
Ok(dec) => {
number_input.set_decimal(dec);
state = State::EnterSignificant;
Ok(())
state = State::Result;
number_input.set_result(dec)
}
Err(_) => Err(()),
},
KeyPress::Div => match calc.div() {
Ok(dec) => {
number_input.set_decimal(dec);
state = State::EnterSignificant;
Ok(())
state = State::Result;
number_input.set_result(dec)
}
Err(_) => Err(()),
},
KeyPress::Plus => match calc.add() {
Ok(dec) => {
number_input.set_decimal(dec);
state = State::EnterSignificant;
Ok(())
state = State::Result;
number_input.set_result(dec)
}
Err(_) => Err(()),
},
KeyPress::Minus => match calc.sub() {
Ok(dec) => {
number_input.set_decimal(dec);
state = State::EnterSignificant;
Ok(())
state = State::Result;
number_input.set_result(dec)
}
Err(_) => Err(()),
},
KeyPress::Down => todo!(),
KeyPress::E => todo!(),
},
State::Err => match key {
State::Err { .. } => match key {
KeyPress::C => {
number_input.reset();
calc.reset();
@@ -346,16 +391,23 @@ fn main() -> ! {
},
};
if res.is_err() {
state = State::Err
state = State::Err {
timeout: ERROR_TIMEOUT,
};
}
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
.unwrap_infallible();
match state {
State::EnterSignificant | State::EnterExponent | State::EnterOperation => {
State::Result | State::EnterSignificant | State::EnterExponent => {
number_input.show(&mut display)
}
State::Err => todo!("display error"),
State::EnterOperation => {
display.operation();
}
State::Err { .. } => {
display.error();
}
}
}
arduino_hal::delay_ms(1);