result state, prompts, and error display handling
This commit is contained in:
@@ -5,6 +5,8 @@ use arduino_hal::{
|
|||||||
port::{mode::Output, Pin},
|
port::{mode::Output, Pin},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::DISPLAY_SEGMENTS;
|
||||||
|
|
||||||
pub struct SegmentPins {
|
pub struct SegmentPins {
|
||||||
kd_seg_a: Pin<Output, PD5>,
|
kd_seg_a: Pin<Output, PD5>,
|
||||||
kd_seg_b: Pin<Output, PB0>,
|
kd_seg_b: Pin<Output, PB0>,
|
||||||
@@ -83,7 +85,10 @@ impl SegmentPins {
|
|||||||
pub enum SegmentState {
|
pub enum SegmentState {
|
||||||
Num(u8, bool),
|
Num(u8, bool),
|
||||||
Minus,
|
Minus,
|
||||||
|
Prompt(bool),
|
||||||
Dot,
|
Dot,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +167,7 @@ impl SegmentState {
|
|||||||
seg.set_f();
|
seg.set_f();
|
||||||
seg.set_g();
|
seg.set_g();
|
||||||
}
|
}
|
||||||
_ => panic!("Can't dispaly {}", no),
|
_ => panic!("SegmentState::Num out of range"),
|
||||||
}
|
}
|
||||||
if *dp {
|
if *dp {
|
||||||
seg.set_dp()
|
seg.set_dp()
|
||||||
@@ -170,12 +175,33 @@ impl SegmentState {
|
|||||||
}
|
}
|
||||||
SegmentState::Minus => seg.set_g(),
|
SegmentState::Minus => seg.set_g(),
|
||||||
SegmentState::Dot => seg.set_dp(),
|
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 => (),
|
SegmentState::Off => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DispalyState([SegmentState; 9]);
|
pub struct DispalyState([SegmentState; DISPLAY_SEGMENTS]);
|
||||||
|
|
||||||
impl Default for DispalyState {
|
impl Default for DispalyState {
|
||||||
fn default() -> DispalyState {
|
fn default() -> DispalyState {
|
||||||
@@ -214,11 +240,25 @@ impl DispalyState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DispalyState {
|
impl DispalyState {
|
||||||
fn set(&mut self, seg: [SegmentState; 9]) {
|
fn set(&mut self, seg: [SegmentState; DISPLAY_SEGMENTS]) {
|
||||||
self.0 = seg;
|
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([
|
self.set([
|
||||||
SegmentState::Off,
|
SegmentState::Off,
|
||||||
SegmentState::Dot,
|
SegmentState::Dot,
|
||||||
@@ -231,6 +271,20 @@ impl DispalyState {
|
|||||||
SegmentState::Off,
|
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
|
// Show data on segment display
|
||||||
|
|||||||
130
src/main.rs
130
src/main.rs
@@ -24,6 +24,15 @@ const SERIAL_BAUD: u32 = 115200;
|
|||||||
pub const KEYBOARD_ADC_THRESHOLD: u16 = 500;
|
pub const KEYBOARD_ADC_THRESHOLD: u16 = 500;
|
||||||
// Number of key presses to record for debounce
|
// Number of key presses to record for debounce
|
||||||
pub const DEBOUNCE_DEPTH: usize = 4;
|
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> {
|
struct IOSelect<'p> {
|
||||||
display_no: usize,
|
display_no: usize,
|
||||||
@@ -81,9 +90,9 @@ impl IOPins {
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct NumberInput {
|
pub struct NumberInput {
|
||||||
minus: bool,
|
minus: bool,
|
||||||
significant: [u8; 5],
|
significant: [u8; DISPLAY_SEGMENTS_SIG],
|
||||||
minus_exponent: bool,
|
minus_exponent: bool,
|
||||||
exponent: [u8; 2],
|
exponent: [u8; DISPLAY_SEGMENTS_EXP],
|
||||||
enter_exponent: bool,
|
enter_exponent: bool,
|
||||||
significant_pos: usize,
|
significant_pos: usize,
|
||||||
exponent_pos: usize,
|
exponent_pos: usize,
|
||||||
@@ -98,7 +107,7 @@ impl NumberInput {
|
|||||||
if val > 9 {
|
if val > 9 {
|
||||||
panic!("Bad significatn val");
|
panic!("Bad significatn val");
|
||||||
}
|
}
|
||||||
if self.significant_pos >= 5 {
|
if self.significant_pos >= DISPLAY_SEGMENTS_SIG {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
self.significant[self.significant_pos] = val;
|
self.significant[self.significant_pos] = val;
|
||||||
@@ -110,7 +119,7 @@ impl NumberInput {
|
|||||||
if val > 9 {
|
if val > 9 {
|
||||||
panic!("Bad exponent val");
|
panic!("Bad exponent val");
|
||||||
}
|
}
|
||||||
if self.exponent_pos >= 2 {
|
if self.exponent_pos >= DISPLAY_SEGMENTS_EXP {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
self.exponent[self.exponent_pos] = val;
|
self.exponent[self.exponent_pos] = val;
|
||||||
@@ -126,10 +135,15 @@ impl NumberInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_enter_exponent(&mut self) {
|
pub fn enter_exponent(&mut self) {
|
||||||
self.significant_pos = 0;
|
self.significant_pos = DISPLAY_SEGMENTS_SIG;
|
||||||
self.exponent_pos = 0;
|
self.enter_exponent = true;
|
||||||
self.enter_exponent = !self.enter_exponent;
|
}
|
||||||
|
|
||||||
|
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) {
|
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();
|
let (minus, significant, minus_exponent, exponent) = dec.into_parts();
|
||||||
self.minus = minus;
|
self.minus = minus;
|
||||||
self.significant = significant;
|
self.significant = significant;
|
||||||
self.minus_exponent = minus_exponent;
|
self.minus_exponent = minus_exponent;
|
||||||
|
if exponent > 99 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
self.exponent[0] = exponent / 10;
|
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 {
|
impl Show for NumberInput {
|
||||||
fn show(&self, display: &mut DispalyState) {
|
fn show(&self, display: &mut DispalyState) {
|
||||||
display[0] = if self.minus {
|
display.prompt();
|
||||||
|
display[DISPLAY_SEGMENT_SIG_MINUS] = if self.minus {
|
||||||
SegmentState::Minus
|
SegmentState::Minus
|
||||||
} else {
|
} else {
|
||||||
SegmentState::Off
|
SegmentState::Off
|
||||||
};
|
};
|
||||||
display[1] = SegmentState::Num(self.significant[0], true);
|
for i in 0..self.significant_pos {
|
||||||
display[2] = SegmentState::Num(self.significant[1], false);
|
display[DISPLAY_SEGMENT_SIG_MINUS + 1 + i] =
|
||||||
display[3] = SegmentState::Num(self.significant[2], false);
|
SegmentState::Num(self.significant[i], i == 0);
|
||||||
display[4] = SegmentState::Num(self.significant[3], false);
|
}
|
||||||
display[5] = SegmentState::Num(self.significant[4], false);
|
display[DISPLAY_SEGMENT_EXP_MINUS] = if self.minus_exponent {
|
||||||
display[6] = if self.minus_exponent {
|
|
||||||
SegmentState::Minus
|
SegmentState::Minus
|
||||||
} else {
|
} else {
|
||||||
SegmentState::Off
|
SegmentState::Off
|
||||||
};
|
};
|
||||||
display[7] = SegmentState::Num(self.exponent[0], false);
|
for i in 0..self.exponent_pos {
|
||||||
display[8] = SegmentState::Num(self.exponent[1], false);
|
display[DISPLAY_SEGMENT_EXP_MINUS + 1 + i] = SegmentState::Num(self.exponent[i], false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +206,8 @@ enum State {
|
|||||||
EnterSignificant,
|
EnterSignificant,
|
||||||
EnterExponent,
|
EnterExponent,
|
||||||
EnterOperation,
|
EnterOperation,
|
||||||
Err,
|
Result,
|
||||||
|
Err { timeout: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[arduino_hal::entry]
|
#[arduino_hal::entry]
|
||||||
@@ -247,9 +268,37 @@ fn main() -> ! {
|
|||||||
io_select.set_off();
|
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) {
|
if let Some(key) = debounce.input(last_key_readout) {
|
||||||
ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible();
|
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 {
|
State::EnterSignificant => match key {
|
||||||
KeyPress::C => {
|
KeyPress::C => {
|
||||||
number_input.reset();
|
number_input.reset();
|
||||||
@@ -259,7 +308,7 @@ fn main() -> ! {
|
|||||||
KeyPress::Num(val) => number_input.input(val),
|
KeyPress::Num(val) => number_input.input(val),
|
||||||
KeyPress::Minus => Ok(number_input.toggle_minus()),
|
KeyPress::Minus => Ok(number_input.toggle_minus()),
|
||||||
KeyPress::E => {
|
KeyPress::E => {
|
||||||
number_input.toggle_enter_exponent();
|
number_input.enter_exponent();
|
||||||
state = State::EnterExponent;
|
state = State::EnterExponent;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -275,7 +324,7 @@ fn main() -> ! {
|
|||||||
KeyPress::Num(val) => number_input.input(val),
|
KeyPress::Num(val) => number_input.input(val),
|
||||||
KeyPress::Minus => Ok(number_input.toggle_minus()),
|
KeyPress::Minus => Ok(number_input.toggle_minus()),
|
||||||
KeyPress::E => {
|
KeyPress::E => {
|
||||||
number_input.toggle_enter_exponent();
|
number_input.done();
|
||||||
match calc.push(number_input.to_decimal()) {
|
match calc.push(number_input.to_decimal()) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
number_input.reset();
|
number_input.reset();
|
||||||
@@ -302,40 +351,36 @@ fn main() -> ! {
|
|||||||
KeyPress::Num(_) => todo!(),
|
KeyPress::Num(_) => todo!(),
|
||||||
KeyPress::Mul => match calc.mul() {
|
KeyPress::Mul => match calc.mul() {
|
||||||
Ok(dec) => {
|
Ok(dec) => {
|
||||||
number_input.set_decimal(dec);
|
state = State::Result;
|
||||||
state = State::EnterSignificant;
|
number_input.set_result(dec)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(()),
|
Err(_) => Err(()),
|
||||||
},
|
},
|
||||||
KeyPress::Div => match calc.div() {
|
KeyPress::Div => match calc.div() {
|
||||||
Ok(dec) => {
|
Ok(dec) => {
|
||||||
number_input.set_decimal(dec);
|
state = State::Result;
|
||||||
state = State::EnterSignificant;
|
number_input.set_result(dec)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(()),
|
Err(_) => Err(()),
|
||||||
},
|
},
|
||||||
KeyPress::Plus => match calc.add() {
|
KeyPress::Plus => match calc.add() {
|
||||||
Ok(dec) => {
|
Ok(dec) => {
|
||||||
number_input.set_decimal(dec);
|
state = State::Result;
|
||||||
state = State::EnterSignificant;
|
number_input.set_result(dec)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(()),
|
Err(_) => Err(()),
|
||||||
},
|
},
|
||||||
KeyPress::Minus => match calc.sub() {
|
KeyPress::Minus => match calc.sub() {
|
||||||
Ok(dec) => {
|
Ok(dec) => {
|
||||||
number_input.set_decimal(dec);
|
state = State::Result;
|
||||||
state = State::EnterSignificant;
|
number_input.set_result(dec)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(()),
|
Err(_) => Err(()),
|
||||||
},
|
},
|
||||||
KeyPress::Down => todo!(),
|
KeyPress::Down => todo!(),
|
||||||
KeyPress::E => todo!(),
|
KeyPress::E => todo!(),
|
||||||
},
|
},
|
||||||
State::Err => match key {
|
State::Err { .. } => match key {
|
||||||
KeyPress::C => {
|
KeyPress::C => {
|
||||||
number_input.reset();
|
number_input.reset();
|
||||||
calc.reset();
|
calc.reset();
|
||||||
@@ -346,16 +391,23 @@ fn main() -> ! {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
state = State::Err
|
state = State::Err {
|
||||||
|
timeout: ERROR_TIMEOUT,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
|
ufmt::uwriteln!(&mut serial, "state: {:?} stack: {}", state, calc.len())
|
||||||
.unwrap_infallible();
|
.unwrap_infallible();
|
||||||
match state {
|
match state {
|
||||||
State::EnterSignificant | State::EnterExponent | State::EnterOperation => {
|
State::Result | State::EnterSignificant | State::EnterExponent => {
|
||||||
number_input.show(&mut display)
|
number_input.show(&mut display)
|
||||||
}
|
}
|
||||||
State::Err => todo!("display error"),
|
State::EnterOperation => {
|
||||||
|
display.operation();
|
||||||
|
}
|
||||||
|
State::Err { .. } => {
|
||||||
|
display.error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arduino_hal::delay_ms(1);
|
arduino_hal::delay_ms(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user