187 lines
4 KiB
Rust
187 lines
4 KiB
Rust
use arrayvec::ArrayVec;
|
|
|
|
const NB_KEYS: usize = 21;
|
|
/// Key repeat max delay (ms)
|
|
const REPEAT_DELAY: u64 = 500;
|
|
|
|
pub type KeyEvents = ArrayVec<KeyEvent, 4>;
|
|
|
|
pub struct Keypad {
|
|
last_key: Option<(Key, u64, u8)>,
|
|
pressed: [bool; NB_KEYS],
|
|
}
|
|
|
|
impl Default for Keypad {
|
|
fn default() -> Self {
|
|
Self {
|
|
last_key: None,
|
|
pressed: [false; NB_KEYS],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Keypad {
|
|
pub fn update(&mut self) -> KeyEvents {
|
|
self.get_keys()
|
|
.into_iter()
|
|
.zip(self.pressed.iter_mut())
|
|
.zip(0u8..)
|
|
.filter_map(|((new_pressed, old_pressed), key)| {
|
|
let mut repeats = 0;
|
|
let event_type = match (*old_pressed, new_pressed) {
|
|
(true, true) => KeyEventType::Down,
|
|
(true, false) => {
|
|
*old_pressed = new_pressed;
|
|
KeyEventType::Released
|
|
}
|
|
(false, true) => {
|
|
*old_pressed = new_pressed;
|
|
'count_repeats: {
|
|
if let Some((last_key, last_when, last_repeats)) = &mut self.last_key {
|
|
if *last_key as u8 == key {
|
|
let now = crate::time::millis();
|
|
if now.wrapping_sub(*last_when) < REPEAT_DELAY {
|
|
*last_repeats = last_repeats.saturating_add(1);
|
|
} else {
|
|
*last_repeats = 1;
|
|
}
|
|
repeats = *last_repeats;
|
|
*last_when = now;
|
|
break 'count_repeats;
|
|
}
|
|
}
|
|
self.last_key =
|
|
Some((Key::from_u8_unchecked(key), crate::time::millis(), 1));
|
|
}
|
|
KeyEventType::Pressed
|
|
}
|
|
(false, false) => return None,
|
|
};
|
|
|
|
Some(KeyEvent {
|
|
key: Key::from_u8_unchecked(key),
|
|
event_type,
|
|
repeats,
|
|
})
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
#[cfg(feature = "simulator")]
|
|
fn get_keys(&self) -> [bool; NB_KEYS] {
|
|
use embedded_graphics_simulator::sdl2::Keycode;
|
|
use embedded_graphics_simulator::SimulatorEvent;
|
|
|
|
let mut keys = [false; NB_KEYS];
|
|
crate::display::window_mut()
|
|
.events()
|
|
.filter_map(|event| match event {
|
|
SimulatorEvent::KeyDown { keycode, .. } => match keycode {
|
|
Keycode::Num0 | Keycode::Kp0 => Some(Key::D0),
|
|
Keycode::Num1 | Keycode::Kp1 => Some(Key::D1),
|
|
Keycode::Num2 | Keycode::Kp2 => Some(Key::D2),
|
|
Keycode::Num3 | Keycode::Kp3 => Some(Key::D3),
|
|
Keycode::Num4 | Keycode::Kp4 => Some(Key::D4),
|
|
Keycode::Num5 | Keycode::Kp5 => Some(Key::D5),
|
|
Keycode::Num6 | Keycode::Kp6 => Some(Key::D6),
|
|
Keycode::Num7 | Keycode::Kp7 => Some(Key::D7),
|
|
Keycode::Num8 | Keycode::Kp8 => Some(Key::D8),
|
|
Keycode::Num9 | Keycode::Kp9 => Some(Key::D9),
|
|
Keycode::KpEnter | Keycode::Return => Some(Key::Enter),
|
|
Keycode::Asterisk => Some(Key::Asterisk),
|
|
Keycode::Hash | Keycode::KpHash => Some(Key::Hash),
|
|
// TODO more
|
|
_ => None,
|
|
},
|
|
SimulatorEvent::Quit => std::process::exit(0),
|
|
_ => None,
|
|
})
|
|
.for_each(|key| keys[key as usize] = true);
|
|
keys
|
|
}
|
|
|
|
#[cfg(not(feature = "simulator"))]
|
|
fn get_keys(&self) -> [bool; NB_KEYS] {
|
|
[false; NB_KEYS]
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
#[repr(u8)]
|
|
pub enum Key {
|
|
D0 = 0,
|
|
D1 = 1,
|
|
D2 = 2,
|
|
D3 = 3,
|
|
D4 = 4,
|
|
D5 = 5,
|
|
D6 = 6,
|
|
D7 = 7,
|
|
D8 = 8,
|
|
D9 = 9,
|
|
Enter = 10,
|
|
OptionRight = 11,
|
|
OptionLeft = 12,
|
|
Left = 13,
|
|
Right = 14,
|
|
Top = 15,
|
|
Down = 16,
|
|
Asterisk = 17,
|
|
Hash = 18,
|
|
PickUp = 19,
|
|
HangUp = 20,
|
|
}
|
|
|
|
impl Key {
|
|
fn from_u8_unchecked(key: u8) -> Self {
|
|
unsafe { core::mem::transmute(key) }
|
|
}
|
|
}
|
|
|
|
pub struct KeyEvent {
|
|
pub event_type: KeyEventType,
|
|
pub key: Key,
|
|
pub repeats: u8,
|
|
}
|
|
|
|
impl KeyEvent {
|
|
pub fn get_char(&self, key_input_mode: KeyInputMode) -> Option<char> {
|
|
use Key::*;
|
|
match key_input_mode {
|
|
KeyInputMode::Digit => match self.key {
|
|
D0 => Some('0'),
|
|
D1 => Some('1'),
|
|
D2 => Some('2'),
|
|
D3 => Some('3'),
|
|
D4 => Some('4'),
|
|
D5 => Some('5'),
|
|
D6 => Some('6'),
|
|
D7 => Some('7'),
|
|
D8 => Some('8'),
|
|
D9 => Some('9'),
|
|
Asterisk => Some('*'),
|
|
Hash => Some('#'),
|
|
_ => None,
|
|
},
|
|
_ => {
|
|
None /* TODO */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//ncb1 upz2 tdk3
|
|
//eow4 lqh5 age6
|
|
//sfx7 rmj8 ivy9
|
|
|
|
#[derive(Eq, PartialEq)]
|
|
pub enum KeyEventType {
|
|
Pressed,
|
|
Down,
|
|
Released,
|
|
}
|
|
|
|
pub enum KeyInputMode {
|
|
Digit,
|
|
Alpha,
|
|
}
|