1mod calibration;
5mod scan;
6mod types;
7
8pub(crate) use crate::matrix::analog_matrix::types::{
9 AdcSampleTime,
10 AutoCalib,
11 EEPROM_POWER_ON_DELAY,
12 KeyCalib,
13 KeyState,
14};
15use crate::{
16 eeprom::Ft24c64,
17 matrix::{
18 calib_store::{CALIB_BUF_LEN, CalibEntry, EEPROM_BASE_ADDR, try_deserialize},
19 hc164_cols::Hc164Cols,
20 },
21};
22use core::future::pending;
23use embassy_stm32::{
24 Peri,
25 adc::{Adc, AnyAdcChannel, BasicInstance, Instance, RxDma},
26 dma::InterruptHandler,
27 i2c::mode::MasterMode,
28 interrupt::typelevel::Binding,
29 pac::adc,
30};
31use embassy_time::Timer;
32use rmk::{
33 event::{KeyboardEvent, publish_event_async},
34 input_device::{InputDevice, Runnable},
35};
36pub use types::HallCfg;
37
38pub struct AdcPart<'peripherals, ADC, D, const ROW: usize>
41where
42 ADC: Instance<Regs = adc::Adc> + BasicInstance,
43 D: RxDma<ADC>,
44 AdcSampleTime<ADC>: Clone,
45{
46 pub adc: Adc<'peripherals, ADC>,
48 pub dma: Peri<'peripherals, D>,
50 pub row_adc: [AnyAdcChannel<'peripherals, ADC>; ROW],
52 pub sample_time: AdcSampleTime<ADC>,
54}
55
56impl<'peripherals, ADC, D, const ROW: usize> AdcPart<'peripherals, ADC, D, ROW>
57where
58 ADC: Instance<Regs = adc::Adc> + BasicInstance,
59 D: RxDma<ADC>,
60 AdcSampleTime<ADC>: Clone,
61{
62 fn configured_sequence<'reader, IRQ2>(
69 &'reader mut self,
70 irq: IRQ2,
71 ) -> embassy_stm32::adc::ConfiguredSequence<'reader, adc::Adc>
72 where
73 IRQ2: Binding<D::Interrupt, InterruptHandler<D>> + 'reader + 'peripherals,
74 {
75 let st = self.sample_time;
76 self.adc.configured_sequence(self.dma.reborrow(), self.row_adc.iter_mut().map(|ch| (ch, st)), irq)
77 }
78
79 pub const fn new(
81 adc: Adc<'peripherals, ADC>,
82 row_adc: [AnyAdcChannel<'peripherals, ADC>; ROW],
83 dma: Peri<'peripherals, D>,
84 sample_time: AdcSampleTime<ADC>,
85 ) -> Self {
86 Self { adc, dma, row_adc, sample_time }
87 }
88}
89
90pub struct AnalogHallMatrix<'peripherals, ADC, D, IRQ, IM, const ROW: usize, const COL: usize>
114where
115 ADC: Instance<Regs = adc::Adc> + BasicInstance,
116 D: RxDma<ADC>,
117 IRQ: Binding<D::Interrupt, InterruptHandler<D>> + Copy + 'peripherals,
118 IM: MasterMode,
119 AdcSampleTime<ADC>: Clone,
120{
121 adc_part: AdcPart<'peripherals, ADC, D, ROW>,
123 auto_calib: [[AutoCalib; COL]; ROW],
126 calib: [[KeyCalib; COL]; ROW],
128 cfg: HallCfg,
130 cols: Hc164Cols<'peripherals>,
132 eeprom: Ft24c64<'peripherals, IM>,
134 irq: IRQ,
136 state: [[KeyState; COL]; ROW],
138}
139
140impl<'peripherals, ADC, D, IRQ, IM, const ROW: usize, const COL: usize>
141 AnalogHallMatrix<'peripherals, ADC, D, IRQ, IM, ROW, COL>
142where
143 ADC: Instance<Regs = adc::Adc> + BasicInstance,
144 D: RxDma<ADC>,
145 IRQ: Binding<D::Interrupt, InterruptHandler<D>> + Copy + 'peripherals,
146 IM: MasterMode,
147 AdcSampleTime<ADC>: Clone,
148{
149 pub fn new(
154 adc_part: AdcPart<'peripherals, ADC, D, ROW>,
155 irq: IRQ,
156 cols: Hc164Cols<'peripherals>,
157 cfg: HallCfg,
158 eeprom: Ft24c64<'peripherals, IM>,
159 ) -> Self {
160 Self {
161 adc_part,
162 auto_calib: [[AutoCalib::new(); COL]; ROW],
163 calib: [[KeyCalib::uncalibrated(); COL]; ROW],
164 cfg,
165 cols,
166 eeprom,
167 irq,
168 state: [[KeyState::new(); COL]; ROW],
169 }
170 }
171
172 fn apply_calib(&mut self, entries: &[[CalibEntry; COL]; ROW], zero_raw: &[[u16; COL]; ROW]) {
176 for ((cal_row, entry_row), zero_row) in self.calib.iter_mut().zip(entries).zip(zero_raw) {
177 for ((cal, entry), &zero) in cal_row.iter_mut().zip(entry_row).zip(zero_row) {
178 *cal = KeyCalib::new(zero, entry.full);
179 }
180 }
181 }
182}
183
184impl<'peripherals, ADC, D, IRQ, IM, const ROW: usize, const COL: usize> InputDevice
185 for AnalogHallMatrix<'peripherals, ADC, D, IRQ, IM, ROW, COL>
186where
187 ADC: Instance<Regs = adc::Adc> + BasicInstance,
188 D: RxDma<ADC>,
189 IRQ: Binding<D::Interrupt, InterruptHandler<D>> + Copy + 'peripherals,
190 IM: MasterMode,
191 AdcSampleTime<ADC>: Clone,
192{
193 type Event = KeyboardEvent;
194
195 async fn read_event(&mut self) -> Self::Event { pending().await }
199}
200
201impl<'peripherals, ADC, D, IRQ, IM, const ROW: usize, const COL: usize> Runnable
202 for AnalogHallMatrix<'peripherals, ADC, D, IRQ, IM, ROW, COL>
203where
204 ADC: Instance<Regs = adc::Adc> + BasicInstance,
205 D: RxDma<ADC>,
206 IRQ: Binding<D::Interrupt, InterruptHandler<D>> + Copy + 'peripherals,
207 IM: MasterMode,
208 AdcSampleTime<ADC>: Clone,
209{
210 async fn run(&mut self) -> ! {
211 let mut eeprom_buf = [0_u8; CALIB_BUF_LEN];
212 let mut entries = Self::default_entries();
213
214 Timer::after(EEPROM_POWER_ON_DELAY).await;
217
218 let loaded = self.eeprom.read(EEPROM_BASE_ADDR, &mut eeprom_buf).await.is_ok()
219 && try_deserialize::<ROW, COL>(&eeprom_buf, &mut entries);
220
221 if loaded {
222 let zero_raw = self.calibrate_zero_raw().await;
225 self.apply_calib(&entries, &zero_raw);
226 } else {
227 self.run_first_boot_calib(&mut eeprom_buf, &mut entries).await;
228 }
229
230 let mut buf = [0_u16; ROW];
231 let mut seq = self.adc_part.configured_sequence(self.irq);
232 loop {
233 if let Some(ev) = Self::scan_for_next_change(
234 &mut self.cols,
235 &mut self.state,
236 &mut self.calib,
237 &mut self.auto_calib,
238 &mut seq,
239 &mut buf,
240 self.cfg,
241 )
242 .await
243 {
244 publish_event_async(ev).await;
245 }
246 }
247 }
248}
249
250#[inline]
253fn get2<T: Copy, const C: usize>(arr: &[[T; C]], row: usize, col: usize) -> Option<T> {
254 arr.get(row).and_then(|r| r.get(col)).copied()
255}
256
257#[inline]
260fn get2_mut<T, const C: usize>(arr: &mut [[T; C]], row: usize, col: usize) -> Option<&mut T> {
261 arr.get_mut(row).and_then(|r| r.get_mut(col))
262}