Skip to main content
RKTK API Docs RKTK Home Repo

rktk_drivers_common/magnetic/
profile.rs

1pub trait SwitchProfile {
2    /// Max travel distance of the switch in 0.01mm (e.g. 400 for 4.0mm)
3    fn max_travel(&self) -> u16;
4
5    /// Maps normalized value (0-65535) to distance (0 to max_travel)
6    fn normalized_to_distance(&self, normalized: u16) -> u16;
7}
8
9/// Simple linear switch profile.
10pub struct LinearProfile {
11    pub max_travel: u16,
12}
13
14impl SwitchProfile for LinearProfile {
15    fn max_travel(&self) -> u16 {
16        self.max_travel
17    }
18
19    fn normalized_to_distance(&self, normalized: u16) -> u16 {
20        ((normalized as u32 * self.max_travel as u32) / 65535) as u16
21    }
22}
23
24/// High-performance 17-point lookup table profile.
25///
26/// Divides the 0-65535 range into exactly 16 intervals of 4096 wide.
27/// Uses fast bit-shifting for interpolation without divisions.
28pub struct Lut17Profile {
29    pub max_travel: u16,
30    pub lut: [u16; 17],
31}
32
33impl SwitchProfile for Lut17Profile {
34    fn max_travel(&self) -> u16 {
35        self.max_travel
36    }
37
38    fn normalized_to_distance(&self, normalized: u16) -> u16 {
39        let idx = (normalized >> 12) as usize;
40        if idx >= 16 {
41            return self.lut[16];
42        }
43        let y0 = self.lut[idx] as u32;
44        let y1 = self.lut[idx + 1] as u32;
45        let fraction = (normalized & 0xFFF) as u32; // 0..4095
46        let val = y0 + (((y1 as i32 - y0 as i32) * fraction as i32) >> 12) as u32;
47        val as u16
48    }
49}
50
51pub trait KeyProfileMap<const ROWS: usize, const COLS: usize> {
52    type Profile: SwitchProfile;
53    fn get_profile(&self, row: usize, col: usize) -> &Self::Profile;
54}
55
56pub struct SingleProfileMap<P: SwitchProfile> {
57    pub profile: P,
58}
59
60impl<P: SwitchProfile, const ROWS: usize, const COLS: usize> KeyProfileMap<ROWS, COLS>
61    for SingleProfileMap<P>
62{
63    type Profile = P;
64    fn get_profile(&self, _row: usize, _col: usize) -> &Self::Profile {
65        &self.profile
66    }
67}
68
69pub struct MatrixProfileMap<P: SwitchProfile, const ROWS: usize, const COLS: usize> {
70    pub profiles: [[P; COLS]; ROWS],
71}
72
73impl<P: SwitchProfile, const ROWS: usize, const COLS: usize> KeyProfileMap<ROWS, COLS>
74    for MatrixProfileMap<P, ROWS, COLS>
75{
76    type Profile = P;
77    fn get_profile(&self, row: usize, col: usize) -> &Self::Profile {
78        &self.profiles[row][col]
79    }
80}