1pub const ADC_16_BIT_FULL_SCALE: f32 = u16::MAX as f32;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct AnalogChannelCalibration {
12 pub scale_factor: f32,
13 pub offset: f32,
14}
15
16impl AnalogChannelCalibration {
17 pub const fn new(scale_factor: f32, offset: f32) -> Self {
18 Self {
19 scale_factor,
20 offset,
21 }
22 }
23
24 pub fn apply_multiplier(&mut self, multiplier: f32) {
27 if multiplier != 0.0 {
28 self.scale_factor = multiplier;
29 }
30 }
31
32 pub fn convert_16_bit_sample(self, adc_count: u16, vdda: f32) -> f32 {
33 let pin_voltage = f32::from(adc_count) / ADC_16_BIT_FULL_SCALE * vdda;
34 (pin_voltage - self.offset) * self.scale_factor
35 }
36}
37
38#[derive(Debug, Clone, Copy, PartialEq)]
40pub struct BatteryMonitorCalibration {
41 pub voltage: AnalogChannelCalibration,
42 pub current: AnalogChannelCalibration,
43}
44
45impl BatteryMonitorCalibration {
46 pub const fn new(
47 voltage_scale: f32,
48 voltage_offset: f32,
49 current_scale: f32,
50 current_offset: f32,
51 ) -> Self {
52 Self {
53 voltage: AnalogChannelCalibration::new(voltage_scale, voltage_offset),
54 current: AnalogChannelCalibration::new(current_scale, current_offset),
55 }
56 }
57
58 pub fn apply_multipliers(&mut self, voltage_multiplier: f32, current_multiplier: f32) {
59 self.voltage.apply_multiplier(voltage_multiplier);
60 self.current.apply_multiplier(current_multiplier);
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn conversion_matches_rosflight_order_of_operations() {
70 let calibration = AnalogChannelCalibration::new(60.5, 0.0747);
71 let value = calibration.convert_16_bit_sample(32_768, 3.3);
72 let expected = (f32::from(32_768_u16) / 65_535.0 * 3.3 - 0.0747) * 60.5;
73 assert!((value - expected).abs() < 1.0e-5);
74 }
75
76 #[test]
77 fn nonzero_multiplier_replaces_board_scale() {
78 let mut calibration = BatteryMonitorCalibration::new(12.62, 0.0, 60.5, 0.0747);
79 calibration.apply_multipliers(7.675, 42.0);
80 assert_eq!(calibration.voltage.scale_factor, 7.675);
81 assert_eq!(calibration.current.scale_factor, 42.0);
82 }
83
84 #[test]
85 fn zero_multiplier_leaves_current_scale_unchanged() {
86 let mut calibration = BatteryMonitorCalibration::new(12.62, 0.0, 60.5, 0.0747);
87 calibration.apply_multipliers(7.675, 0.0);
88 calibration.apply_multipliers(0.0, 0.0);
89 assert_eq!(calibration.voltage.scale_factor, 7.675);
90 assert_eq!(calibration.current.scale_factor, 60.5);
91 }
92}