104 lines
3.0 KiB
Rust
104 lines
3.0 KiB
Rust
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<KeyPress> {
|
|
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,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(uDebug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct KeyReadout {
|
|
display_no: usize,
|
|
kn: bool,
|
|
ko: bool,
|
|
}
|
|
|
|
pub struct Keyboard<KN, KO> {
|
|
kn: KN,
|
|
ko: KO,
|
|
}
|
|
|
|
impl<KN: AdcChannel<Atmega, ADC>, KO: AdcChannel<Atmega, ADC>> Keyboard<KN, KO> {
|
|
pub fn new(kn: KN, ko: KO) -> Keyboard<KN, KO> {
|
|
Keyboard { kn, ko }
|
|
}
|
|
|
|
pub fn read(&self, adc: &mut Adc, display_no: usize) -> Option<KeyReadout> {
|
|
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 {
|
|
display_no,
|
|
kn: kn > KEYBOARD_ADC_THRESHOLD,
|
|
ko: ko > KEYBOARD_ADC_THRESHOLD,
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct Debounce {
|
|
record: [Option<KeyReadout>; DEBOUNCE_DEPTH],
|
|
pos: usize,
|
|
last: Option<KeyReadout>,
|
|
}
|
|
|
|
impl Debounce {
|
|
pub fn input(&mut self, key: Option<KeyReadout>) -> Option<KeyPress> {
|
|
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.and_then(|key_readout| {
|
|
KeyPress::map(key_readout.display_no, key_readout.kn, key_readout.ko)
|
|
})
|
|
} else if self.record.iter().all(|hist| hist == &None) {
|
|
self.last = None;
|
|
None
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|