Skip to main content

xpanse_api/
metadata.rs

1//! Metadata for apps about the drivers, like what physical slot the module is in, that the driver uses,
2//! and what type of module is used by the driver.
3//!
4//! Module identification is resistor-coded: two detection resistors (`md0` and
5//! `md1`) are read by the ADC at boot. The combination uniquely selects a
6//! [`ModuleID`], which a [`crate::driver::Driver`] matches against its
7//! [`DriverMeta::ID`](crate::driver::DriverMeta::ID) constant.
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, defmt::Format)]
10/// Physical slot that a module is plugged into.
11pub enum ModuleSlot {
12    FrontRight,
13    FrontLeft,
14    BackRight,
15    BackLeft,
16}
17
18/// Resistor-coded module identifier: two 12-bit detection resistor values.
19#[derive(Clone, Copy, Debug, PartialEq, Eq, defmt::Format)]
20pub struct ModuleID {
21    /// Resistor on detection line 0.
22    pub md0: ModuleDetectResistor,
23    /// Resistor on detection line 1.
24    pub md1: ModuleDetectResistor,
25}
26
27/// Standard E24-series resistor values used for module detection.
28#[derive(Clone, Copy, Debug, PartialEq, Eq, defmt::Format)]
29pub enum ModuleDetectResistor {
30    R1K,
31    R1K1,
32    R1K2,
33    R1K3,
34    R1K5,
35    R1K6,
36    R1K8,
37    R2K,
38    R2K2,
39    R2K4,
40    R2K7,
41    R3K,
42    R3K3,
43    R3K6,
44    R3K9,
45    R4K3,
46    R4K7,
47    R5K1,
48    R5K6,
49    R6K2,
50    R6K8,
51    R7K5,
52    R8K2,
53    R9K1,
54    R10K,
55    R11K,
56    R12K,
57    R13K,
58    R15K,
59    R16K,
60    R18K,
61    R20K,
62    R22K,
63    R24K,
64    R27K,
65    R30K,
66    R33K,
67    R36K,
68    R39K,
69    R43K,
70    R47K,
71    R51K,
72    R56K,
73    R62K,
74    R68K,
75    R75K,
76    R82K,
77    R91K,
78    R100K,
79}
80
81/// Fixed 10 kΩ pull-down resistor on the module-detection line.
82pub const BOTTOM_RESISTOR: f64 = 10_000.0;
83
84/// Supply voltage (nominal 3.3 V) used for the resistor-divider ADC reading.
85pub const AVDD: f64 = 3.3;
86
87impl ModuleDetectResistor {
88    /// Convert a measured divider voltage back to the closest standard resistor value.
89    ///
90    /// Returns `None` if the voltage is out of range (≤ 0 V or ≥ `AVDD`) or the
91    /// computed resistance falls outside the E24 range.
92    ///
93    /// # Example
94    ///
95    /// ```ignore
96    /// use xpanse_api::metadata::{ModuleDetectResistor, AVDD, BOTTOM_RESISTOR};
97    ///
98    /// // A 10 kΩ resistor with the 10 kΩ pull-down gives half of AVDD.
99    /// let voltage = AVDD / 2.0;
100    /// assert_eq!(ModuleDetectResistor::from_voltage(voltage), Some(ModuleDetectResistor::R10K));
101    /// ```
102    pub fn from_voltage(voltage: f64) -> Option<Self> {
103        if !voltage.is_finite() || voltage <= 0.0 || voltage >= AVDD {
104            return None;
105        }
106
107        let calculated_resistor = (AVDD * BOTTOM_RESISTOR) / voltage - BOTTOM_RESISTOR;
108        if !calculated_resistor.is_finite() || !(950.0..=105_000.0).contains(&calculated_resistor) {
109            return None;
110        }
111
112        let (_, closest_resistor) = RESISTOR_MAP
113            .iter()
114            .min_by(|(val_a, _), (val_b, _)| {
115                let diff_a = (val_a - calculated_resistor).abs();
116                let diff_b = (val_b - calculated_resistor).abs();
117
118                diff_a
119                    .partial_cmp(&diff_b)
120                    .unwrap_or(core::cmp::Ordering::Equal)
121            })
122            .expect("RESISTOR_MAP should never be empty");
123
124        Some(*closest_resistor)
125    }
126}
127
128const RESISTOR_MAP: &[(f64, ModuleDetectResistor)] = &[
129    (1_000.0, ModuleDetectResistor::R1K),
130    (1_100.0, ModuleDetectResistor::R1K1),
131    (1_200.0, ModuleDetectResistor::R1K2),
132    (1_300.0, ModuleDetectResistor::R1K3),
133    (1_500.0, ModuleDetectResistor::R1K5),
134    (1_600.0, ModuleDetectResistor::R1K6),
135    (1_800.0, ModuleDetectResistor::R1K8),
136    (2_000.0, ModuleDetectResistor::R2K),
137    (2_200.0, ModuleDetectResistor::R2K2),
138    (2_400.0, ModuleDetectResistor::R2K4),
139    (2_700.0, ModuleDetectResistor::R2K7),
140    (3_000.0, ModuleDetectResistor::R3K),
141    (3_300.0, ModuleDetectResistor::R3K3),
142    (3_600.0, ModuleDetectResistor::R3K6),
143    (3_900.0, ModuleDetectResistor::R3K9),
144    (4_300.0, ModuleDetectResistor::R4K3),
145    (4_700.0, ModuleDetectResistor::R4K7),
146    (5_100.0, ModuleDetectResistor::R5K1),
147    (5_600.0, ModuleDetectResistor::R5K6),
148    (6_200.0, ModuleDetectResistor::R6K2),
149    (6_800.0, ModuleDetectResistor::R6K8),
150    (7_500.0, ModuleDetectResistor::R7K5),
151    (8_200.0, ModuleDetectResistor::R8K2),
152    (9_100.0, ModuleDetectResistor::R9K1),
153    (10_000.0, ModuleDetectResistor::R10K),
154    (11_000.0, ModuleDetectResistor::R11K),
155    (12_000.0, ModuleDetectResistor::R12K),
156    (13_000.0, ModuleDetectResistor::R13K),
157    (15_000.0, ModuleDetectResistor::R15K),
158    (16_000.0, ModuleDetectResistor::R16K),
159    (18_000.0, ModuleDetectResistor::R18K),
160    (20_000.0, ModuleDetectResistor::R20K),
161    (22_000.0, ModuleDetectResistor::R22K),
162    (24_000.0, ModuleDetectResistor::R24K),
163    (27_000.0, ModuleDetectResistor::R27K),
164    (30_000.0, ModuleDetectResistor::R30K),
165    (33_000.0, ModuleDetectResistor::R33K),
166    (36_000.0, ModuleDetectResistor::R36K),
167    (39_000.0, ModuleDetectResistor::R39K),
168    (43_000.0, ModuleDetectResistor::R4K3),
169    (47_000.0, ModuleDetectResistor::R47K),
170    (51_000.0, ModuleDetectResistor::R51K),
171    (56_000.0, ModuleDetectResistor::R56K),
172    (62_000.0, ModuleDetectResistor::R62K),
173    (68_000.0, ModuleDetectResistor::R68K),
174    (75_000.0, ModuleDetectResistor::R75K),
175    (82_000.0, ModuleDetectResistor::R82K),
176    (91_000.0, ModuleDetectResistor::R91K),
177    (100_000.0, ModuleDetectResistor::R100K),
178];
179
180impl From<ModuleDetectResistor> for f64 {
181    fn from(val: ModuleDetectResistor) -> Self {
182        match val {
183            ModuleDetectResistor::R1K => 1_000.0,
184            ModuleDetectResistor::R1K1 => 1_100.0,
185            ModuleDetectResistor::R1K2 => 1_200.0,
186            ModuleDetectResistor::R1K3 => 1_300.0,
187            ModuleDetectResistor::R1K5 => 1_500.0,
188            ModuleDetectResistor::R1K6 => 1_600.0,
189            ModuleDetectResistor::R1K8 => 1_800.0,
190            ModuleDetectResistor::R2K => 2_000.0,
191            ModuleDetectResistor::R2K2 => 2_200.0,
192            ModuleDetectResistor::R2K4 => 2_400.0,
193            ModuleDetectResistor::R2K7 => 2_700.0,
194            ModuleDetectResistor::R3K => 3_000.0,
195            ModuleDetectResistor::R3K3 => 3_300.0,
196            ModuleDetectResistor::R3K6 => 3_600.0,
197            ModuleDetectResistor::R3K9 => 3_900.0,
198            ModuleDetectResistor::R4K3 => 4_300.0,
199            ModuleDetectResistor::R4K7 => 4_700.0,
200            ModuleDetectResistor::R5K1 => 5_100.0,
201            ModuleDetectResistor::R5K6 => 5_600.0,
202            ModuleDetectResistor::R6K2 => 6_200.0,
203            ModuleDetectResistor::R6K8 => 6_800.0,
204            ModuleDetectResistor::R7K5 => 7_500.0,
205            ModuleDetectResistor::R8K2 => 8_200.0,
206            ModuleDetectResistor::R9K1 => 9_100.0,
207            ModuleDetectResistor::R10K => 10_000.0,
208            ModuleDetectResistor::R11K => 11_000.0,
209            ModuleDetectResistor::R12K => 12_000.0,
210            ModuleDetectResistor::R13K => 13_000.0,
211            ModuleDetectResistor::R15K => 15_000.0,
212            ModuleDetectResistor::R16K => 16_000.0,
213            ModuleDetectResistor::R18K => 18_000.0,
214            ModuleDetectResistor::R20K => 20_000.0,
215            ModuleDetectResistor::R22K => 22_000.0,
216            ModuleDetectResistor::R24K => 24_000.0,
217            ModuleDetectResistor::R27K => 27_000.0,
218            ModuleDetectResistor::R30K => 30_000.0,
219            ModuleDetectResistor::R33K => 33_000.0,
220            ModuleDetectResistor::R36K => 36_000.0,
221            ModuleDetectResistor::R39K => 39_000.0,
222            ModuleDetectResistor::R43K => 43_000.0,
223            ModuleDetectResistor::R47K => 47_000.0,
224            ModuleDetectResistor::R51K => 51_000.0,
225            ModuleDetectResistor::R56K => 56_000.0,
226            ModuleDetectResistor::R62K => 62_000.0,
227            ModuleDetectResistor::R68K => 68_000.0,
228            ModuleDetectResistor::R75K => 75_000.0,
229            ModuleDetectResistor::R82K => 82_000.0,
230            ModuleDetectResistor::R91K => 91_000.0,
231            ModuleDetectResistor::R100K => 100_000.0,
232        }
233    }
234}