esp_hal/analog/adc/
esp32.rs

1use core::marker::PhantomData;
2
3use super::{AdcConfig, Attenuation};
4use crate::peripherals::{ADC1, ADC2, RTC_IO, SENS};
5
6pub(super) const NUM_ATTENS: usize = 10;
7
8/// The sampling/readout resolution of the ADC.
9#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11#[allow(clippy::enum_variant_names, reason = "peripheral is unstable")]
12pub enum Resolution {
13    /// 9-bit resolution
14    Resolution9Bit  = 0b00,
15    /// 10-bit resolution
16    Resolution10Bit = 0b01,
17    /// 11-bit resolution
18    Resolution11Bit = 0b10,
19    /// 12-bit resolution
20    #[default]
21    Resolution12Bit = 0b11,
22}
23
24#[doc(hidden)]
25pub trait RegisterAccess {
26    fn set_bit_width(resolution: u8);
27
28    fn set_sample_bit(resolution: u8);
29
30    fn set_attenuation(channel: usize, attenuation: u8);
31
32    fn clear_dig_force();
33
34    fn set_start_force();
35
36    fn set_en_pad_force();
37
38    fn set_en_pad(channel: u8);
39
40    fn clear_start_sar();
41
42    fn set_start_sar();
43
44    fn read_done_sar() -> bool;
45
46    fn read_data_sar() -> u16;
47}
48
49impl RegisterAccess for ADC1<'_> {
50    fn set_bit_width(resolution: u8) {
51        SENS::regs()
52            .sar_start_force()
53            .modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) });
54    }
55
56    fn set_sample_bit(resolution: u8) {
57        SENS::regs()
58            .sar_read_ctrl()
59            .modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) });
60    }
61
62    fn set_attenuation(channel: usize, attenuation: u8) {
63        SENS::regs().sar_atten1().modify(|r, w| {
64            let new_value = (r.bits() & !(0b11 << (channel * 2)))
65                | (((attenuation & 0b11) as u32) << (channel * 2));
66
67            unsafe { w.sar1_atten().bits(new_value) }
68        });
69    }
70
71    fn clear_dig_force() {
72        SENS::regs()
73            .sar_read_ctrl()
74            .modify(|_, w| w.sar1_dig_force().clear_bit());
75    }
76
77    fn set_start_force() {
78        SENS::regs()
79            .sar_meas_start1()
80            .modify(|_, w| w.meas1_start_force().set_bit());
81    }
82
83    fn set_en_pad_force() {
84        SENS::regs()
85            .sar_meas_start1()
86            .modify(|_, w| w.sar1_en_pad_force().set_bit());
87    }
88
89    fn set_en_pad(channel: u8) {
90        SENS::regs()
91            .sar_meas_start1()
92            .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
93    }
94
95    fn clear_start_sar() {
96        SENS::regs()
97            .sar_meas_start1()
98            .modify(|_, w| w.meas1_start_sar().clear_bit());
99    }
100
101    fn set_start_sar() {
102        SENS::regs()
103            .sar_meas_start1()
104            .modify(|_, w| w.meas1_start_sar().set_bit());
105    }
106
107    fn read_done_sar() -> bool {
108        SENS::regs()
109            .sar_meas_start1()
110            .read()
111            .meas1_done_sar()
112            .bit_is_set()
113    }
114
115    fn read_data_sar() -> u16 {
116        SENS::regs()
117            .sar_meas_start1()
118            .read()
119            .meas1_data_sar()
120            .bits()
121    }
122}
123
124impl RegisterAccess for ADC2<'_> {
125    fn set_bit_width(resolution: u8) {
126        SENS::regs()
127            .sar_start_force()
128            .modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) });
129    }
130
131    fn set_sample_bit(resolution: u8) {
132        SENS::regs()
133            .sar_read_ctrl2()
134            .modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) });
135    }
136
137    fn set_attenuation(channel: usize, attenuation: u8) {
138        SENS::regs().sar_atten2().modify(|r, w| {
139            let new_value = (r.bits() & !(0b11 << (channel * 2)))
140                | (((attenuation & 0b11) as u32) << (channel * 2));
141
142            unsafe { w.sar2_atten().bits(new_value) }
143        });
144    }
145
146    fn clear_dig_force() {
147        SENS::regs()
148            .sar_read_ctrl2()
149            .modify(|_, w| w.sar2_dig_force().clear_bit());
150    }
151
152    fn set_start_force() {
153        SENS::regs()
154            .sar_meas_start2()
155            .modify(|_, w| w.meas2_start_force().set_bit());
156    }
157
158    fn set_en_pad_force() {
159        SENS::regs()
160            .sar_meas_start2()
161            .modify(|_, w| w.sar2_en_pad_force().set_bit());
162    }
163
164    fn set_en_pad(channel: u8) {
165        SENS::regs()
166            .sar_meas_start2()
167            .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
168    }
169
170    fn clear_start_sar() {
171        SENS::regs()
172            .sar_meas_start2()
173            .modify(|_, w| w.meas2_start_sar().clear_bit());
174    }
175
176    fn set_start_sar() {
177        SENS::regs()
178            .sar_meas_start2()
179            .modify(|_, w| w.meas2_start_sar().set_bit());
180    }
181
182    fn read_done_sar() -> bool {
183        SENS::regs()
184            .sar_meas_start2()
185            .read()
186            .meas2_done_sar()
187            .bit_is_set()
188    }
189
190    fn read_data_sar() -> u16 {
191        SENS::regs()
192            .sar_meas_start2()
193            .read()
194            .meas2_data_sar()
195            .bits()
196    }
197}
198
199/// Analog-to-Digital Converter peripheral driver.
200pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
201    _adc: ADC,
202    attenuations: [Option<Attenuation>; NUM_ATTENS],
203    active_channel: Option<u8>,
204    _phantom: PhantomData<(Dm, &'d mut ())>,
205}
206
207impl<'d, ADCI> Adc<'d, ADCI, crate::Blocking>
208where
209    ADCI: RegisterAccess + 'd,
210{
211    /// Configure a given ADC instance using the provided configuration, and
212    /// initialize the ADC for use
213    pub fn new(adc_instance: ADCI, config: AdcConfig<ADCI>) -> Self {
214        let sensors = SENS::regs();
215
216        // Set reading and sampling resolution
217        let resolution: u8 = config.resolution as u8;
218
219        ADCI::set_bit_width(resolution);
220        ADCI::set_sample_bit(resolution);
221
222        // Set attenuation for pins
223        let attenuations = config.attenuations;
224
225        for (channel, attentuation) in attenuations.iter().enumerate() {
226            if let Some(attenuation) = attentuation {
227                ADC1::set_attenuation(channel, *attenuation as u8);
228            }
229        }
230
231        // Set controller to RTC
232        ADCI::clear_dig_force();
233        ADCI::set_start_force();
234        ADCI::set_en_pad_force();
235        sensors
236            .sar_touch_ctrl1()
237            .modify(|_, w| w.xpd_hall_force().set_bit());
238        sensors
239            .sar_touch_ctrl1()
240            .modify(|_, w| w.hall_phase_force().set_bit());
241
242        // Set power to SW power on
243        sensors
244            .sar_meas_wait2()
245            .modify(|_, w| unsafe { w.force_xpd_sar().bits(0b11) });
246
247        // disable AMP
248        sensors
249            .sar_meas_wait2()
250            .modify(|_, w| unsafe { w.force_xpd_amp().bits(0b10) });
251        sensors
252            .sar_meas_ctrl()
253            .modify(|_, w| unsafe { w.amp_rst_fb_fsm().bits(0) });
254        sensors
255            .sar_meas_ctrl()
256            .modify(|_, w| unsafe { w.amp_short_ref_fsm().bits(0) });
257        sensors
258            .sar_meas_ctrl()
259            .modify(|_, w| unsafe { w.amp_short_ref_gnd_fsm().bits(0) });
260        sensors
261            .sar_meas_wait1()
262            .modify(|_, w| unsafe { w.sar_amp_wait1().bits(1) });
263        sensors
264            .sar_meas_wait1()
265            .modify(|_, w| unsafe { w.sar_amp_wait2().bits(1) });
266        sensors
267            .sar_meas_wait2()
268            .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
269
270        // Do *not* invert the output
271        // NOTE: This seems backwards, but was verified experimentally.
272        sensors
273            .sar_read_ctrl2()
274            .modify(|_, w| w.sar2_data_inv().set_bit());
275
276        Adc {
277            _adc: adc_instance,
278            attenuations: config.attenuations,
279            active_channel: None,
280            _phantom: PhantomData,
281        }
282    }
283
284    /// Request that the ADC begin a conversion on the specified pin
285    ///
286    /// This method takes an [AdcPin](super::AdcPin) reference, as it is
287    /// expected that the ADC will be able to sample whatever channel
288    /// underlies the pin.
289    pub fn read_oneshot<PIN>(&mut self, _pin: &mut super::AdcPin<PIN, ADCI>) -> nb::Result<u16, ()>
290    where
291        PIN: super::AdcChannel,
292    {
293        if self.attenuations[PIN::CHANNEL as usize].is_none() {
294            panic!("Channel {} is not configured reading!", PIN::CHANNEL);
295        }
296
297        if let Some(active_channel) = self.active_channel {
298            // There is conversion in progress:
299            // - if it's for a different channel try again later
300            // - if it's for the given channel, go ahead and check progress
301            if active_channel != PIN::CHANNEL {
302                return Err(nb::Error::WouldBlock);
303            }
304        } else {
305            // If no conversions are in progress, start a new one for given channel
306            self.active_channel = Some(PIN::CHANNEL);
307
308            ADCI::set_en_pad(PIN::CHANNEL);
309
310            ADCI::clear_start_sar();
311            ADCI::set_start_sar();
312        }
313
314        // Wait for ADC to finish conversion
315        let conversion_finished = ADCI::read_done_sar();
316        if !conversion_finished {
317            return Err(nb::Error::WouldBlock);
318        }
319
320        // Get converted value
321        let converted_value = ADCI::read_data_sar();
322
323        // Mark that no conversions are currently in progress
324        self.active_channel = None;
325
326        Ok(converted_value)
327    }
328}
329
330impl<ADC1> Adc<'_, ADC1, crate::Blocking> {
331    /// Enable the Hall sensor
332    pub fn enable_hall_sensor() {
333        RTC_IO::regs()
334            .hall_sens()
335            .modify(|_, w| w.xpd_hall().set_bit());
336    }
337
338    /// Disable the Hall sensor
339    pub fn disable_hall_sensor() {
340        RTC_IO::regs()
341            .hall_sens()
342            .modify(|_, w| w.xpd_hall().clear_bit());
343    }
344}
345
346mod adc_implementation {
347    crate::analog::adc::impl_adc_interface! {
348        ADC1 [
349            (GPIO36<'_>, 0), // Alt. name: SENSOR_VP
350            (GPIO37<'_>, 1), // Alt. name: SENSOR_CAPP
351            (GPIO38<'_>, 2), // Alt. name: SENSOR_CAPN
352            (GPIO39<'_>, 3), // Alt. name: SENSOR_VN
353            (GPIO33<'_>, 4), // Alt. name: 32K_XP
354            (GPIO32<'_>, 5), // Alt. name: 32K_XN
355            (GPIO34<'_>, 6), // Alt. name: VDET_1
356            (GPIO35<'_>, 7), // Alt. name: VDET_2
357        ]
358    }
359
360    crate::analog::adc::impl_adc_interface! {
361        ADC2 [
362            (GPIO4<'_>,  0),
363            (GPIO0<'_>,  1),
364            (GPIO2<'_>,  2),
365            (GPIO15<'_>, 3), // Alt. name: MTDO
366            (GPIO13<'_>, 4), // Alt. name: MTCK
367            (GPIO12<'_>, 5), // Alt. name: MTDI
368            (GPIO14<'_>, 6), // Alt. name: MTMS
369            (GPIO27<'_>, 7),
370            (GPIO25<'_>, 8),
371            (GPIO26<'_>, 9),
372        ]
373    }
374}