stm32f4xx_hal/adc/
config.rs

1//! Contains types related to ADC configuration
2
3/// The place in the sequence a given channel should be captured
4#[cfg_attr(feature = "defmt", derive(defmt::Format))]
5#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
6#[repr(u8)]
7pub enum Sequence {
8    /// 1
9    One = 0,
10    /// 2
11    Two = 1,
12    /// 3
13    Three = 2,
14    /// 4
15    Four = 3,
16    /// 5
17    Five = 4,
18    /// 6
19    Six = 5,
20    /// 7
21    Seven = 6,
22    /// 8
23    Eight = 7,
24    /// 9
25    Nine = 8,
26    /// 10
27    Ten = 9,
28    /// 11
29    Eleven = 10,
30    /// 12
31    Twelve = 11,
32    /// 13
33    Thirteen = 12,
34    /// 14
35    Fourteen = 13,
36    /// 15
37    Fifteen = 14,
38    /// 16
39    Sixteen = 15,
40}
41
42impl From<Sequence> for u8 {
43    fn from(s: Sequence) -> u8 {
44        s as _
45    }
46}
47
48impl From<u8> for Sequence {
49    fn from(bits: u8) -> Self {
50        match bits {
51            0 => Sequence::One,
52            1 => Sequence::Two,
53            2 => Sequence::Three,
54            3 => Sequence::Four,
55            4 => Sequence::Five,
56            5 => Sequence::Six,
57            6 => Sequence::Seven,
58            7 => Sequence::Eight,
59            8 => Sequence::Nine,
60            9 => Sequence::Ten,
61            10 => Sequence::Eleven,
62            11 => Sequence::Twelve,
63            12 => Sequence::Thirteen,
64            13 => Sequence::Fourteen,
65            14 => Sequence::Fifteen,
66            15 => Sequence::Sixteen,
67            _ => unimplemented!(),
68        }
69    }
70}
71
72/// The number of cycles to sample a given channel for
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74#[derive(Copy, Clone, PartialEq, Eq, Debug)]
75#[repr(u8)]
76pub enum SampleTime {
77    /// 3 cycles
78    Cycles_3 = 0,
79    /// 15 cycles
80    Cycles_15 = 1,
81    /// 28 cycles
82    Cycles_28 = 2,
83    /// 56 cycles
84    Cycles_56 = 3,
85    /// 84 cycles
86    Cycles_84 = 4,
87    /// 112 cycles
88    Cycles_112 = 5,
89    /// 144 cycles
90    Cycles_144 = 6,
91    /// 480 cycles
92    Cycles_480 = 7,
93}
94
95impl From<u8> for SampleTime {
96    fn from(f: u8) -> SampleTime {
97        match f {
98            0 => SampleTime::Cycles_3,
99            1 => SampleTime::Cycles_15,
100            2 => SampleTime::Cycles_28,
101            3 => SampleTime::Cycles_56,
102            4 => SampleTime::Cycles_84,
103            5 => SampleTime::Cycles_112,
104            6 => SampleTime::Cycles_144,
105            7 => SampleTime::Cycles_480,
106            _ => unimplemented!(),
107        }
108    }
109}
110
111impl From<SampleTime> for u8 {
112    fn from(l: SampleTime) -> u8 {
113        l as _
114    }
115}
116
117/// Clock config for the ADC
118/// Check the datasheet for the maximum speed the ADC supports
119#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120#[derive(Copy, Clone, PartialEq, Eq, Debug)]
121#[repr(u8)]
122pub enum Clock {
123    /// PCLK2 (APB2) divided by 2
124    Pclk2_div_2 = 0,
125    /// PCLK2 (APB2) divided by 4
126    Pclk2_div_4 = 1,
127    /// PCLK2 (APB2) divided by 6
128    Pclk2_div_6 = 2,
129    /// PCLK2 (APB2) divided by 8
130    Pclk2_div_8 = 3,
131}
132
133impl From<Clock> for u8 {
134    fn from(c: Clock) -> u8 {
135        c as _
136    }
137}
138
139/// Resolution to sample at
140#[cfg_attr(feature = "defmt", derive(defmt::Format))]
141#[derive(Copy, Clone, PartialEq, Eq, Debug)]
142#[repr(u8)]
143pub enum Resolution {
144    /// 12-bit
145    Twelve = 0,
146    /// 10-bit
147    Ten = 1,
148    /// 8-bit
149    Eight = 2,
150    /// 6-bit
151    Six = 3,
152}
153impl From<Resolution> for u8 {
154    fn from(r: Resolution) -> u8 {
155        r as _
156    }
157}
158
159/// Possible external triggers the ADC can listen to
160#[cfg_attr(feature = "defmt", derive(defmt::Format))]
161#[derive(Copy, Clone, PartialEq, Eq, Debug)]
162#[repr(u8)]
163pub enum ExternalTrigger {
164    /// TIM1 compare channel 1
165    Tim_1_cc_1 = 0b0000,
166    /// TIM1 compare channel 2
167    Tim_1_cc_2 = 0b0001,
168    /// TIM1 compare channel 3
169    Tim_1_cc_3 = 0b0010,
170    /// TIM2 compare channel 2
171    Tim_2_cc_2 = 0b0011,
172    /// TIM2 compare channel 3
173    Tim_2_cc_3 = 0b0100,
174    /// TIM2 compare channel 4
175    Tim_2_cc_4 = 0b0101,
176    /// TIM2 trigger out
177    Tim_2_trgo = 0b0110,
178    /// TIM3 compare channel 1
179    Tim_3_cc_1 = 0b0111,
180    /// TIM3 trigger out
181    Tim_3_trgo = 0b1000,
182    /// TIM4 compare channel 4
183    Tim_4_cc_4 = 0b1001,
184    /// TIM5 compare channel 1
185    Tim_5_cc_1 = 0b1010,
186    /// TIM5 compare channel 2
187    Tim_5_cc_2 = 0b1011,
188    /// TIM5 compare channel 3
189    Tim_5_cc_3 = 0b1100,
190    /// External interrupt line 11
191    Exti_11 = 0b1111,
192}
193impl From<ExternalTrigger> for u8 {
194    fn from(et: ExternalTrigger) -> u8 {
195        et as _
196    }
197}
198
199/// Possible trigger modes
200#[cfg_attr(feature = "defmt", derive(defmt::Format))]
201#[derive(Copy, Clone, PartialEq, Eq, Debug)]
202#[repr(u8)]
203pub enum TriggerMode {
204    /// Don't listen to external trigger
205    Disabled = 0,
206    /// Listen for rising edges of external trigger
207    RisingEdge = 1,
208    /// Listen for falling edges of external trigger
209    FallingEdge = 2,
210    /// Listen for both rising and falling edges of external trigger
211    BothEdges = 3,
212}
213impl From<TriggerMode> for u8 {
214    fn from(tm: TriggerMode) -> u8 {
215        tm as _
216    }
217}
218
219/// Data register alignment
220#[cfg_attr(feature = "defmt", derive(defmt::Format))]
221#[derive(Copy, Clone, PartialEq, Eq, Debug)]
222pub enum Align {
223    /// Right align output data
224    Right,
225    /// Left align output data
226    Left,
227}
228impl From<Align> for bool {
229    fn from(a: Align) -> bool {
230        match a {
231            Align::Right => false,
232            Align::Left => true,
233        }
234    }
235}
236
237/// Scan enable/disable
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239#[derive(Copy, Clone, PartialEq, Eq, Debug)]
240pub enum Scan {
241    /// Scan mode disabled
242    Disabled,
243    /// Scan mode enabled
244    Enabled,
245}
246impl From<Scan> for bool {
247    fn from(s: Scan) -> bool {
248        match s {
249            Scan::Disabled => false,
250            Scan::Enabled => true,
251        }
252    }
253}
254
255/// Continuous mode enable/disable
256#[cfg_attr(feature = "defmt", derive(defmt::Format))]
257#[derive(Copy, Clone, PartialEq, Eq, Debug)]
258pub enum Continuous {
259    /// Single mode, continuous disabled
260    Single,
261    /// Continuous mode enabled
262    Continuous,
263}
264impl From<Continuous> for bool {
265    fn from(c: Continuous) -> bool {
266        match c {
267            Continuous::Single => false,
268            Continuous::Continuous => true,
269        }
270    }
271}
272
273/// DMA mode
274#[cfg_attr(feature = "defmt", derive(defmt::Format))]
275#[derive(Copy, Clone, PartialEq, Eq, Debug)]
276pub enum Dma {
277    /// No DMA, disabled
278    Disabled,
279    /// Single DMA, DMA will be disabled after each conversion sequence
280    Single,
281    /// Continuous DMA, DMA will remain enabled after conversion
282    Continuous,
283}
284
285/// End-of-conversion interrupt enabled/disabled
286#[cfg_attr(feature = "defmt", derive(defmt::Format))]
287#[derive(Copy, Clone, PartialEq, Eq, Debug)]
288pub enum Eoc {
289    /// End-of-conversion interrupt disabled
290    Disabled,
291    /// End-of-conversion interrupt enabled per conversion
292    Conversion,
293    /// End-of-conversion interrupt enabled per sequence
294    Sequence,
295}
296
297/// Configuration for the adc.
298/// There are some additional parameters on the adc peripheral that can be
299/// added here when needed but this covers several basic usecases.
300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301#[derive(Copy, Clone, PartialEq, Eq, Debug)]
302pub struct AdcConfig {
303    pub(crate) clock: Clock,
304    pub(crate) resolution: Resolution,
305    pub(crate) align: Align,
306    pub(crate) scan: Scan,
307    pub(crate) external_trigger: (TriggerMode, ExternalTrigger),
308    pub(crate) continuous: Continuous,
309    pub(crate) dma: Dma,
310    pub(crate) end_of_conversion_interrupt: Eoc,
311    pub(crate) default_sample_time: SampleTime,
312    pub(crate) vdda: Option<u32>,
313}
314
315impl AdcConfig {
316    /// change the clock field
317    pub fn clock(mut self, clock: Clock) -> Self {
318        self.clock = clock;
319        self
320    }
321    /// change the resolution field
322    pub fn resolution(mut self, resolution: Resolution) -> Self {
323        self.resolution = resolution;
324        self
325    }
326    /// change the align field
327    pub fn align(mut self, align: Align) -> Self {
328        self.align = align;
329        self
330    }
331    /// change the scan field
332    pub fn scan(mut self, scan: Scan) -> Self {
333        self.scan = scan;
334        self
335    }
336    /// change the external_trigger field
337    pub fn external_trigger(mut self, trigger_mode: TriggerMode, trigger: ExternalTrigger) -> Self {
338        self.external_trigger = (trigger_mode, trigger);
339        self
340    }
341    /// change the continuous field
342    pub fn continuous(mut self, continuous: Continuous) -> Self {
343        self.continuous = continuous;
344        self
345    }
346    /// change the dma field
347    pub fn dma(mut self, dma: Dma) -> Self {
348        self.dma = dma;
349        self
350    }
351    /// change the end_of_conversion_interrupt field
352    pub fn end_of_conversion_interrupt(mut self, end_of_conversion_interrupt: Eoc) -> Self {
353        self.end_of_conversion_interrupt = end_of_conversion_interrupt;
354        self
355    }
356    /// change the default_sample_time field
357    pub fn default_sample_time(mut self, default_sample_time: SampleTime) -> Self {
358        self.default_sample_time = default_sample_time;
359        self
360    }
361
362    /// Specify the reference voltage for the ADC.
363    ///
364    /// # Args
365    /// * `vdda_mv` - The ADC reference voltage in millivolts.
366    pub fn reference_voltage(mut self, vdda_mv: u32) -> Self {
367        self.vdda = Some(vdda_mv);
368        self
369    }
370}
371
372impl Default for AdcConfig {
373    fn default() -> Self {
374        Self {
375            clock: Clock::Pclk2_div_2,
376            resolution: Resolution::Twelve,
377            align: Align::Right,
378            scan: Scan::Disabled,
379            external_trigger: (TriggerMode::Disabled, ExternalTrigger::Tim_1_cc_1),
380            continuous: Continuous::Single,
381            dma: Dma::Disabled,
382            end_of_conversion_interrupt: Eoc::Disabled,
383            default_sample_time: SampleTime::Cycles_480,
384            vdda: None,
385        }
386    }
387}