From 7467f41c30da3493e2b9fa729d0f1f2d6159f908 Mon Sep 17 00:00:00 2001 From: Hexa Dust Date: Fri, 18 Jul 2025 20:31:23 +0100 Subject: [PATCH] factored out keyboard file --- src/keyboard.rs | 104 +++++++++++++++++++++++++++++++ src/main.rs | 161 +++++++++++------------------------------------- 2 files changed, 139 insertions(+), 126 deletions(-) create mode 100644 src/keyboard.rs diff --git a/src/keyboard.rs b/src/keyboard.rs new file mode 100644 index 0000000..b3fd539 --- /dev/null +++ b/src/keyboard.rs @@ -0,0 +1,104 @@ +use arduino_hal::{adc::AdcChannel, hal::Atmega, pac::ADC, Adc}; +use ufmt::derive::uDebug; + +use crate::{DEBOUNCE_DEPTH, KEYBOARD_ADC_THRESHOLD}; + +#[derive(uDebug, Clone, Copy, PartialEq, Eq)] +pub enum KeyPress { + Up, + C, + Num(u8), + Mul, + Div, + Plus, + Minus, + Down, + E, +} + +impl KeyPress { + fn map(display_no: usize, kn: bool, ko: bool) -> Option { + match (display_no, kn, ko) { + (0, true, false) => Some(KeyPress::Num(1)), + (0, false, true) => Some(KeyPress::C), + (1, true, false) => Some(KeyPress::Num(5)), + (1, false, true) => Some(KeyPress::Div), + (2, true, false) => Some(KeyPress::Num(6)), + (2, false, true) => Some(KeyPress::Mul), + (3, true, false) => Some(KeyPress::Num(7)), + (3, false, true) => Some(KeyPress::Up), + (4, true, false) => Some(KeyPress::Num(8)), + (4, false, true) => Some(KeyPress::E), + (5, true, false) => Some(KeyPress::Num(9)), + (5, false, true) => Some(KeyPress::Num(0)), + (6, true, false) => Some(KeyPress::Num(2)), + (6, false, true) => Some(KeyPress::Down), + (7, true, false) => Some(KeyPress::Num(3)), + (7, false, true) => Some(KeyPress::Plus), + (8, true, false) => Some(KeyPress::Num(4)), + (8, false, true) => Some(KeyPress::Minus), + _ => None, + } + } +} + +pub struct KeyReadout { + kn: bool, + ko: bool, +} + +impl KeyReadout { + pub fn to_keypress(&self, display_no: usize) -> Option { + KeyPress::map(display_no, self.kn, self.ko) + } +} + +pub struct Keyboard { + kn: KN, + ko: KO, +} + +impl, KO: AdcChannel> Keyboard { + pub fn new(kn: KN, ko: KO) -> Keyboard { + Keyboard { kn, ko } + } + + pub fn read(&self, adc: &mut Adc) -> Option { + let kn = adc.read_blocking(&self.kn); + let ko = adc.read_blocking(&self.ko); + if kn > KEYBOARD_ADC_THRESHOLD || ko > KEYBOARD_ADC_THRESHOLD { + Some(KeyReadout { + kn: kn > KEYBOARD_ADC_THRESHOLD, + ko: ko > KEYBOARD_ADC_THRESHOLD, + }) + } else { + None + } + } +} + +#[derive(Default)] +pub struct Debounce { + record: [Option; DEBOUNCE_DEPTH], + pos: usize, + last: Option, +} + +impl Debounce { + pub fn input(&mut self, key: Option) -> Option { + self.record[self.pos] = key; + self.pos += 1; + if self.pos >= self.record.len() { + self.pos = 0; + } + if self.record.iter().all(|hist| hist == &key) && self.last != key { + self.last = key; + key + } else if self.record.iter().all(|hist| hist == &None) { + self.last = None; + None + } else { + None + } + } +} diff --git a/src/main.rs b/src/main.rs index a8a0173..16e28c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,18 @@ #![no_std] #![no_main] +mod keyboard; + use calc_math::calc::StackCalc; use calc_math::Decimal; use core::ops::{Index, IndexMut}; +use keyboard::{Debounce, KeyPress, KeyReadout, Keyboard}; use arduino_hal::{ - adc::{ - channel::{ADC6, ADC7}, - AdcChannel, + adc::channel::{ADC6, ADC7}, + hal::port::{ + PB0, PB1, PB2, PB3, PB4, PC0, PC1, PC2, PC3, PC4, PC5, PD2, PD3, PD4, PD5, PD6, PD7, }, - hal::{ - port::{ - PB0, PB1, PB2, PB3, PB4, PC0, PC1, PC2, PC3, PC4, PC5, PD2, PD3, PD4, PD5, PD6, PD7, - }, - Atmega, - }, - pac::ADC, port::{mode::Output, Pin}, prelude::*, Adc, @@ -25,6 +21,10 @@ use ufmt::derive::uDebug; // NOTE: 115200 @ 16MHz is 3.5% off, try 9600 or 1M if it causes issues (https://wormfood.net/avrbaudcalc.php) const SERIAL_BAUD: u32 = 115200; +// Analog threshold level of key press on ADC read from KN or KO +pub const KEYBOARD_ADC_THRESHOLD: u16 = 500; +// Number of key presses to record for debounce +pub const DEBOUNCE_DEPTH: usize = 4; #[cfg(not(doc))] #[panic_handler] @@ -332,92 +332,6 @@ impl DispalyState { } } -#[derive(uDebug, Clone, Copy, PartialEq, Eq)] -enum InputKey { - Up, - C, - Num(u8), - Mul, - Div, - Plus, - Minus, - Down, - E, -} - -impl InputKey { - fn map(display_no: usize, kn: bool, ko: bool) -> Option { - match (display_no, kn, ko) { - (0, true, false) => Some(InputKey::Num(1)), - (0, false, true) => Some(InputKey::C), - (1, true, false) => Some(InputKey::Num(5)), - (1, false, true) => Some(InputKey::Div), - (2, true, false) => Some(InputKey::Num(6)), - (2, false, true) => Some(InputKey::Mul), - (3, true, false) => Some(InputKey::Num(7)), - (3, false, true) => Some(InputKey::Up), - (4, true, false) => Some(InputKey::Num(8)), - (4, false, true) => Some(InputKey::E), - (5, true, false) => Some(InputKey::Num(9)), - (5, false, true) => Some(InputKey::Num(0)), - (6, true, false) => Some(InputKey::Num(2)), - (6, false, true) => Some(InputKey::Down), - (7, true, false) => Some(InputKey::Num(3)), - (7, false, true) => Some(InputKey::Plus), - (8, true, false) => Some(InputKey::Num(4)), - (8, false, true) => Some(InputKey::Minus), - _ => None, - } - } -} - -struct Input { - kn: KN, - ko: KO, -} - -impl, KO: AdcChannel> Input { - fn new(kn: KN, ko: KO) -> Input { - Input { kn, ko } - } - - fn read(&self, adc: &mut Adc) -> Option<(bool, bool)> { - let kn = adc.read_blocking(&self.kn); - let ko = adc.read_blocking(&self.ko); - if kn > 500 || ko > 500 { - Some((kn > 500, ko > 500)) - } else { - None - } - } -} - -#[derive(Default)] -struct Debounce { - history: [Option; 4], - pos: usize, - last: Option, -} - -impl Debounce { - fn input(&mut self, key: Option) -> Option { - self.history[self.pos] = key; - self.pos += 1; - if self.pos >= self.history.len() { - self.pos = 0; - } - if self.history.iter().all(|hist| hist == &key) && self.last != key { - self.last = key; - key - } else if self.history.iter().all(|hist| hist == &None) { - self.last = None; - None - } else { - None - } - } -} - #[derive(Default)] struct NumberInput { minus: bool, @@ -538,14 +452,10 @@ fn main() -> ! { let dp = arduino_hal::Peripherals::take().unwrap(); let pins = arduino_hal::pins!(dp); - // let mut led = pins.d13.into_output(); let mut serial = arduino_hal::default_serial!(dp, pins, SERIAL_BAUD); ufmt::uwriteln!(&mut serial, "Hello from Arduino!").unwrap_infallible(); - // let mut kd_KN = pins..into_input(); - // let mut kd_KO = *pins.a.into_output(); - let mut io = IOPins::new( pins.d2.into_output(), pins.d3.into_output(), @@ -570,7 +480,7 @@ fn main() -> ! { ); let mut adc = Adc::new(dp.ADC, Default::default()); - let input = Input::new(ADC7, ADC6); + let input = Keyboard::new(ADC7, ADC6); let mut debounce = Debounce::default(); let mut number_input = NumberInput::default(); @@ -581,7 +491,7 @@ fn main() -> ! { let mut state = State::EnterSignificant; loop { - let mut key: Option<(usize, bool, bool)> = None; + let mut last_key_readout: Option<(usize, KeyReadout)> = None; for (mut io_select, ss) in io.iter_mut().zip(display.0.iter()) { ss.apply(&mut seg); io_select.set_on(); @@ -589,27 +499,26 @@ fn main() -> ! { io_select.set_off(); seg.set_off(); io_select.set_on(); - // arduino_hal::delay_us(100); - if let Some((kn, ko)) = input.read(&mut adc) { - key = Some((io_select.display_no(), kn, ko)) + if let Some(key_readout) = input.read(&mut adc) { + last_key_readout = Some((io_select.display_no(), key_readout)); } io_select.set_off(); } - let key = key.and_then(|(no, kn, ko)| InputKey::map(no, kn, ko)); - - if let Some(key) = debounce.input(key) { + let key_press = last_key_readout + .and_then(|(display_no, key_readout)| key_readout.to_keypress(display_no)); + if let Some(key) = debounce.input(key_press) { ufmt::uwriteln!(&mut serial, "key: {:?} state: {:?}", key, state).unwrap_infallible(); let res = match state { State::EnterSignificant => match key { - InputKey::C => { + KeyPress::C => { number_input.reset(); calc.reset(); Ok(()) } - InputKey::Num(val) => number_input.input(val), - InputKey::Minus => Ok(number_input.toggle_minus()), - InputKey::E => { + KeyPress::Num(val) => number_input.input(val), + KeyPress::Minus => Ok(number_input.toggle_minus()), + KeyPress::E => { number_input.toggle_enter_exponent(); state = State::EnterExponent; Ok(()) @@ -617,15 +526,15 @@ fn main() -> ! { _ => Ok(()), }, State::EnterExponent => match key { - InputKey::C => { + KeyPress::C => { number_input.reset(); calc.reset(); state = State::EnterSignificant; Ok(()) } - InputKey::Num(val) => number_input.input(val), - InputKey::Minus => Ok(number_input.toggle_minus()), - InputKey::E => { + KeyPress::Num(val) => number_input.input(val), + KeyPress::Minus => Ok(number_input.toggle_minus()), + KeyPress::E => { number_input.toggle_enter_exponent(); match calc.push(number_input.to_decimal()) { Ok(()) => { @@ -643,15 +552,15 @@ fn main() -> ! { _ => Ok(()), }, State::EnterOperation => match key { - InputKey::Up => todo!(), - InputKey::C => { + KeyPress::Up => todo!(), + KeyPress::C => { number_input.reset(); calc.reset(); state = State::EnterSignificant; Ok(()) } - InputKey::Num(_) => todo!(), - InputKey::Mul => match calc.mul() { + KeyPress::Num(_) => todo!(), + KeyPress::Mul => match calc.mul() { Ok(dec) => { number_input.set_decimal(dec); state = State::EnterSignificant; @@ -659,7 +568,7 @@ fn main() -> ! { } Err(_) => Err(()), }, - InputKey::Div => match calc.div() { + KeyPress::Div => match calc.div() { Ok(dec) => { number_input.set_decimal(dec); state = State::EnterSignificant; @@ -667,7 +576,7 @@ fn main() -> ! { } Err(_) => Err(()), }, - InputKey::Plus => match calc.add() { + KeyPress::Plus => match calc.add() { Ok(dec) => { number_input.set_decimal(dec); state = State::EnterSignificant; @@ -675,7 +584,7 @@ fn main() -> ! { } Err(_) => Err(()), }, - InputKey::Minus => match calc.sub() { + KeyPress::Minus => match calc.sub() { Ok(dec) => { number_input.set_decimal(dec); state = State::EnterSignificant; @@ -683,11 +592,11 @@ fn main() -> ! { } Err(_) => Err(()), }, - InputKey::Down => todo!(), - InputKey::E => todo!(), + KeyPress::Down => todo!(), + KeyPress::E => todo!(), }, State::Err => match key { - InputKey::C => { + KeyPress::C => { number_input.reset(); calc.reset(); state = State::EnterSignificant;