rmk_q6_he_ansi/matrix/
calib_store.rs1use crate::keymap::{COL, ROW};
2use core::mem::size_of;
3use crc::{CRC_16_IBM_3740, Crc, NoTable};
4
5pub const CALIB_BUF_LEN: usize = total_len(ROW, COL);
7const CRC16: Crc<u16, NoTable> = Crc::<u16, NoTable>::new(&CRC_16_IBM_3740);
9const CRC_LEN: usize = size_of::<u16>();
11pub const EEPROM_BASE_ADDR: u16 = 0x0000;
13const ENTRY_LEN: usize = size_of::<u16>();
15const HEADER_LEN: usize = size_of::<u32>().saturating_add(size_of::<u8>());
17const VERSION: u8 = 1;
19const MAGIC: u32 = 0x5136_4845;
21
22#[derive(Clone, Copy)]
24pub struct CalibEntry {
25 pub full: u16,
27}
28
29#[inline]
36fn read_array<const N: usize>(buf: &[u8], start: usize, end: usize) -> Option<[u8; N]> {
37 buf.get(start..end)?.try_into().ok()
38}
39
40pub fn serialize<const ROW: usize, const COL: usize>(
46 entries: &[[CalibEntry; COL]; ROW],
47 buf: &mut [u8; CALIB_BUF_LEN],
48) {
49 if let Some(dst) = buf.get_mut(0..size_of::<u32>()) {
51 dst.copy_from_slice(&MAGIC.to_le_bytes());
52 }
53
54 if let Some(version_byte) = buf.get_mut(size_of::<u32>()) {
56 *version_byte = VERSION;
57 }
58
59 let mut pos = HEADER_LEN;
60 for row in entries {
61 for entry in row {
62 let end = pos.saturating_add(ENTRY_LEN);
63 if let Some(dst) = buf.get_mut(pos..end) {
64 dst.copy_from_slice(&entry.full.to_le_bytes());
65 }
66 pos = end;
67 }
68 }
69
70 let crc_start = pos;
72 let crc_end = crc_start.saturating_add(CRC_LEN);
73 let crc = buf.get(..crc_start).map_or(0, |data| CRC16.checksum(data));
74 if let Some(dst) = buf.get_mut(crc_start..crc_end) {
75 dst.copy_from_slice(&crc.to_le_bytes());
76 }
77}
78
79pub fn try_deserialize<const ROW: usize, const COL: usize>(buf: &[u8], out: &mut [[CalibEntry; COL]; ROW]) -> bool {
86 if buf.len() < CALIB_BUF_LEN {
87 return false;
88 }
89
90 let magic_end = size_of::<u32>();
92 let Some(magic_bytes) = read_array::<4>(buf, 0, magic_end) else { return false };
93 if u32::from_le_bytes(magic_bytes) != MAGIC {
94 return false;
95 }
96
97 let Some(&stored_version) = buf.get(size_of::<u32>()) else { return false };
99 if stored_version != VERSION {
100 return false;
101 }
102
103 let data_end = HEADER_LEN.saturating_add(ROW.saturating_mul(COL).saturating_mul(ENTRY_LEN));
105 let crc_end = data_end.saturating_add(CRC_LEN);
106 let Some(stored_crc_bytes) = read_array::<2>(buf, data_end, crc_end) else { return false };
108 let stored_crc = u16::from_le_bytes(stored_crc_bytes);
109 let computed_crc = buf.get(..data_end).map_or(0, |data| CRC16.checksum(data));
110 if computed_crc != stored_crc {
111 return false;
112 }
113
114 let mut pos = HEADER_LEN;
116 for row in out.iter_mut() {
117 for entry in row.iter_mut() {
118 let end = pos.saturating_add(ENTRY_LEN);
119 let Some(fb) = read_array::<2>(buf, pos, end) else { return false };
120 entry.full = u16::from_le_bytes(fb);
121 pos = end;
122 }
123 }
124 true
125}
126
127pub const fn total_len(rows: usize, cols: usize) -> usize {
129 HEADER_LEN.saturating_add(rows.saturating_mul(cols).saturating_mul(ENTRY_LEN)).saturating_add(CRC_LEN)
130}