ad7147/
stage.rs

1#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
2pub struct StageConfiguration(pub(crate) InternalStageConfiguration);
3
4impl StageConfiguration {
5    pub fn builder() -> StageConfigurationBuilder {
6        StageConfigurationBuilder {
7            configuration: InternalStageConfiguration::default(),
8            input_connections: heapless::Vec::new(),
9        }
10    }
11}
12
13pub struct StageConfigurationBuilder {
14    configuration: InternalStageConfiguration,
15    input_connections: heapless::Vec<InputConnection, 12>,
16}
17
18impl StageConfigurationBuilder {
19    pub fn calibration_enabled(mut self, enabled: bool) -> StageConfigurationBuilder {
20        self.configuration.global.calibration_enabled = enabled;
21        self
22    }
23
24    pub fn low_interrupt_enabled(mut self, enabled: bool) -> StageConfigurationBuilder {
25        self.configuration.global.low_int_enabled = enabled;
26        self
27    }
28
29    pub fn high_interrupt_enabled(mut self, enabled: bool) -> StageConfigurationBuilder {
30        self.configuration.global.high_int_enabled = enabled;
31        self
32    }
33
34    pub fn conversion_complete_interrupt_enabled(
35        mut self,
36        enabled: bool,
37    ) -> StageConfigurationBuilder {
38        self.configuration.global.complete_int_enabled = enabled;
39        self
40    }
41
42    pub fn add_input_connection(
43        mut self,
44        input_connection: InputConnection,
45    ) -> StageConfigurationBuilder {
46        let _ = self.input_connections.push(input_connection);
47        self
48    }
49
50    pub fn sensitivity(mut self, sensitivity: StageSensitivity) -> StageConfigurationBuilder {
51        self.configuration.sensitivity = sensitivity;
52        self
53    }
54
55    pub fn initial_offset_low(mut self, offset: u16) -> StageConfigurationBuilder {
56        self.configuration.initial_offset_low = offset;
57        self
58    }
59
60    pub fn initial_offset_high(mut self, offset: u16) -> StageConfigurationBuilder {
61        self.configuration.initial_offset_high = offset;
62        self
63    }
64
65    pub fn offset_high_clamp(mut self, clamp: u16) -> StageConfigurationBuilder {
66        self.configuration.offset_high_clamp = clamp;
67        self
68    }
69
70    pub fn offset_low_clamp(mut self, clamp: u16) -> StageConfigurationBuilder {
71        self.configuration.offset_low_clamp = clamp;
72        self
73    }
74
75    pub fn pos_afe_offset(mut self, offset: u8) -> StageConfigurationBuilder {
76        self.configuration.afe_offset_configuration.pos_afe_offset = offset;
77        self
78    }
79
80    pub fn neg_afe_offset(mut self, offset: u8) -> StageConfigurationBuilder {
81        self.configuration.afe_offset_configuration.neg_afe_offset = offset;
82        self
83    }
84
85    pub fn build(mut self) -> StageConfiguration {
86        if self.input_connections.len() > 1 {
87            self.configuration.input_configuration =
88                InputMode::Differential([self.input_connections[0], self.input_connections[1]]);
89        } else {
90            self.configuration.input_configuration =
91                InputMode::SingleEnded(self.input_connections[0]);
92        }
93        StageConfiguration(self.configuration)
94    }
95}
96
97#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
98pub(crate) struct InternalStageConfiguration {
99    input_configuration: InputMode,
100    neg_afe_offset_disable: bool,
101    pos_afe_offset_disable: bool,
102    afe_offset_configuration: AfeOffsetConfiguration,
103    sensitivity: StageSensitivity,
104    initial_offset_low: u16,
105    initial_offset_high: u16,
106    offset_high_clamp: u16,
107    offset_low_clamp: u16,
108    pub(crate) global: StageGlobalConfig,
109}
110
111impl InternalStageConfiguration {
112    pub(crate) fn to_reg_value(self) -> [u16; 8] {
113        let mut res = [0u16; 8];
114        res[0..2].copy_from_slice(&self.input_configuration.to_reg_value());
115        res[1] |= (self.neg_afe_offset_disable as u16) << 14;
116        res[1] |= (self.pos_afe_offset_disable as u16) << 15;
117        res[2] = self.afe_offset_configuration.to_reg_value();
118        res[3] = self.sensitivity.to_reg_value();
119        res[4] = self.initial_offset_low;
120        res[5] = self.initial_offset_high;
121        res[6] = self.offset_high_clamp;
122        res[7] = self.offset_low_clamp;
123        res
124    }
125}
126
127#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
128pub(crate) struct StageGlobalConfig {
129    pub(crate) calibration_enabled: bool,
130    pub(crate) low_int_enabled: bool,
131    pub(crate) high_int_enabled: bool,
132    pub(crate) complete_int_enabled: bool,
133}
134
135#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
136enum InputMode {
137    #[default]
138    NotConfigured,
139    SingleEnded(InputConnection),
140    Differential([InputConnection; 2]),
141}
142
143impl InputMode {
144    pub(crate) fn to_reg_value(self) -> [u16; 2] {
145        let mut res = 0u32;
146        match self {
147            Self::NotConfigured => {
148                panic!("Input mode cannot be left unconfigured")
149            }
150            InputMode::SingleEnded(conn) => {
151                res |= 0xFFFFFFFF >> 4;
152                res &= ((conn.cdc as u32) << (conn.cin as u32)) | !(0b11 << (conn.cin as u32));
153                res |= if conn.cdc == CdcInput::Positive {
154                    0b01
155                } else {
156                    0b10
157                } << 28;
158            }
159            InputMode::Differential(conns) => {
160                res |= 0xFFFFFFFF >> 4;
161                for conn in conns {
162                    res &= ((conn.cdc as u32) << (conn.cin as u32)) | !(0b11 << (conn.cin as u32));
163                }
164                res |= 0b11 << 28;
165            }
166        }
167        [res as u16, (res >> 16) as u16]
168    }
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
172pub struct InputConnection {
173    pub cin: CapInput,
174    pub cdc: CdcInput,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
178pub enum CapInput {
179    CIN0 = 0,
180    CIN1 = 2,
181    CIN2 = 4,
182    CIN3 = 6,
183    CIN4 = 8,
184    CIN5 = 10,
185    CIN6 = 12,
186    CIN7 = 16,
187    CIN8 = 18,
188    CIN9 = 20,
189    CIN10 = 22,
190    CIN11 = 24,
191    CIN12 = 26,
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
195pub enum CdcInput {
196    Positive = 0b10,
197    Negative = 0b01,
198}
199
200#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
201struct AfeOffsetConfiguration {
202    neg_afe_offset: u8,
203    neg_afe_offset_swap: bool,
204    pos_afe_offset: u8,
205    pos_afe_offset_swap: bool,
206}
207
208impl AfeOffsetConfiguration {
209    pub(crate) fn to_reg_value(self) -> u16 {
210        let mut res = 0u16;
211        res |= (self.neg_afe_offset & 0b00011111) as u16;
212        res |= (self.neg_afe_offset_swap as u16) << 7;
213        res |= ((self.pos_afe_offset & 0b00011111) as u16) << 8;
214        res |= (self.pos_afe_offset_swap as u16) << 15;
215        res
216    }
217}
218
219#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
220pub struct StageSensitivity {
221    pub neg_threshold_sensitivity: ThresholdSensitivity,
222    pub neg_peak_detect: PeakDetect,
223    pub pos_threshold_sensitivity: ThresholdSensitivity,
224    pub pos_peak_detect: PeakDetect,
225}
226
227impl StageSensitivity {
228    pub(crate) fn to_reg_value(self) -> u16 {
229        let mut res = 0u16;
230        res |= self.neg_threshold_sensitivity as u16;
231        res |= (self.neg_peak_detect as u16) << 4;
232        res |= (self.pos_threshold_sensitivity as u16) << 8;
233        res |= (self.pos_peak_detect as u16) << 12;
234        res
235    }
236}
237
238#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
239pub enum ThresholdSensitivity {
240    #[default]
241    Percent25 = 0,
242    Percent29 = 1,
243    Percent34 = 2,
244    Percent39 = 3,
245    Percent43 = 4,
246    Percent48 = 5,
247    Percent53 = 6,
248    Percent58 = 7,
249    Percent62 = 8,
250    Percent67 = 9,
251    Percent71 = 10,
252    Percent76 = 11,
253    Percent81 = 12,
254    Percent85 = 13,
255    Percent90 = 14,
256    Percent95 = 15,
257}
258
259#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
260pub enum PeakDetect {
261    #[default]
262    Percent40 = 0,
263    Percent50 = 1,
264    Percent60 = 2,
265    Percent70 = 3,
266    Percent80 = 4,
267    Percent90 = 5,
268}