diff --git a/src/display.rs b/src/display.rs index ac8d871..4c5d744 100644 --- a/src/display.rs +++ b/src/display.rs @@ -5,6 +5,8 @@ use arduino_hal::{ port::{mode::Output, Pin}, }; +use crate::DISPLAY_SEGMENTS; + pub struct SegmentPins { kd_seg_a: Pin, kd_seg_b: Pin, @@ -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 diff --git a/src/main.rs b/src/main.rs index 20aa2f0..093201d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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);