rktk_drivers_common/keyscan/
shift_register_matrix.rs1use super::pressed::Pressed;
2use embedded_hal::{digital::InputPin, spi::Operation};
3use embedded_hal_async::spi::SpiDevice;
4use rktk::drivers::interface::keyscan::{KeyChangeEvent, KeyscanDriver};
5
6pub struct ShiftRegisterMatrix<
10 S: SpiDevice,
11 IP: InputPin,
12 T: Fn(usize, usize) -> Option<(usize, usize)>,
13 const OUTPUT_PIN_COUNT: usize,
14 const INPUT_PIN_COUNT: usize,
15 const ROWS: usize,
16 const COLS: usize,
17> {
18 row_shift_register: S,
19 input_pins: [IP; INPUT_PIN_COUNT],
20 pressed: Pressed<ROWS, COLS>,
21 map_key_pos: T,
22 scan_delay: embassy_time::Duration,
23}
24
25impl<
26 S: SpiDevice,
27 IP: InputPin,
28 T: Fn(usize, usize) -> Option<(usize, usize)>,
29 const OUTPUT_PIN_COUNT: usize,
30 const INPUT_PIN_COUNT: usize,
31 const ROWS: usize,
32 const COLS: usize,
33> ShiftRegisterMatrix<S, IP, T, OUTPUT_PIN_COUNT, INPUT_PIN_COUNT, ROWS, COLS>
34{
35 pub fn new(
48 row_shift_register: S,
49 input_pins: [IP; INPUT_PIN_COUNT],
50 map_key_pos: T,
51 scan_delay: Option<embassy_time::Duration>,
52 ) -> Self {
53 Self {
54 row_shift_register,
55 input_pins,
56 pressed: Pressed::new(),
57 map_key_pos,
58 scan_delay: scan_delay.unwrap_or(embassy_time::Duration::from_micros(5)),
59 }
60 }
61}
62
63impl<
64 S: SpiDevice,
65 IP: InputPin,
66 T: Fn(usize, usize) -> Option<(usize, usize)>,
67 const OUTPUT_PIN_COUNT: usize,
68 const INPUT_PIN_COUNT: usize,
69 const ROWS: usize,
70 const COLS: usize,
71> KeyscanDriver for ShiftRegisterMatrix<S, IP, T, OUTPUT_PIN_COUNT, INPUT_PIN_COUNT, ROWS, COLS>
72{
73 type CalibrationError = core::convert::Infallible;
74
75 async fn scan(&mut self, mut cb: impl FnMut(KeyChangeEvent)) {
77 for output_idx in 0..OUTPUT_PIN_COUNT {
78 let _ = self
79 .row_shift_register
80 .transaction(&mut [Operation::DelayNs(1000), Operation::Write(&[1 << output_idx])])
81 .await;
82
83 embassy_time::Timer::after(self.scan_delay).await;
84
85 for (input_idx, input_pin) in self.input_pins.iter_mut().enumerate() {
86 if let Some((row, col)) = (self.map_key_pos)(input_idx, output_idx)
87 && let Some(change) =
88 self.pressed.set_pressed(input_pin.is_high().unwrap(), row, col)
89 {
90 cb(KeyChangeEvent { row: row as u8, col: col as u8, pressed: change });
91 }
92 }
93 }
94 }
95}