Skip to main content

esp_hal/analog/adc/
xtensa.rs

1use core::{
2    marker::PhantomData,
3    pin::Pin,
4    task::{Context, Poll},
5};
6
7use portable_atomic::{AtomicU32, Ordering};
8use procmacros::{handler, ram};
9
10pub use self::calibration::*;
11use super::{AdcCalScheme, AdcCalSource, AdcChannel, AdcConfig, AdcPin, Attenuation};
12use crate::{
13    Async,
14    Blocking,
15    asynch::AtomicWaker,
16    efuse::AdcCalibUnit,
17    interrupt::{InterruptConfigurable, InterruptHandler},
18    peripherals::{APB_SARADC, Interrupt, LPWR, SENS},
19    rtc_cntl::WakeLock,
20    soc::regi2c,
21    system::{GenericPeripheralGuard, Peripheral},
22};
23
24mod calibration;
25
26pub(super) const NUM_ATTENS: usize = 10;
27
28cfg_select! {
29    esp32s2 => {
30        const ADC_VAL_MASK: u16 = 0x1fff;
31        const ADC_CAL_CNT_MAX: u16 = 32;
32        const ADC_CAL_CHANNEL: u16 = 15;
33    }
34    esp32s3 => {
35        const ADC_VAL_MASK: u16 = 0xfff;
36        const ADC_CAL_CNT_MAX: u16 = 32;
37        const ADC_CAL_CHANNEL: u16 = 15;
38    }
39}
40
41impl<ADCX> AdcConfig<ADCX>
42where
43    ADCX: RegisterAccess,
44{
45    /// Calibrate ADC with specified attenuation and voltage source
46    pub fn adc_calibrate(atten: Attenuation, source: AdcCalSource) -> u16
47    where
48        ADCX: super::CalibrationAccess,
49    {
50        let mut adc_max: u16 = 0;
51        let mut adc_min: u16 = u16::MAX;
52        let mut adc_sum: u32 = 0;
53
54        ADCX::enable_vdef(true);
55
56        // Start sampling
57        ADCX::set_en_pad(ADCX::ADC_CAL_CHANNEL as u8);
58        ADCX::set_attenuation(ADCX::ADC_CAL_CHANNEL as usize, atten as u8);
59
60        // Connect calibration source
61        ADCX::connect_cal(source, true);
62
63        ADCX::calibration_init();
64        ADCX::set_init_code(0);
65
66        for _ in 0..ADCX::ADC_CAL_CNT_MAX {
67            // Trigger ADC sampling
68            ADCX::start_sample();
69
70            // Wait until ADC sampling is done
71            while !ADCX::is_done() {}
72
73            let adc = ADCX::read_data() & ADCX::ADC_VAL_MASK;
74
75            ADCX::reset();
76
77            adc_sum += adc as u32;
78            adc_max = adc.max(adc_max);
79            adc_min = adc.min(adc_min);
80        }
81
82        let cal_val =
83            (adc_sum - adc_max as u32 - adc_min as u32) as u16 / (ADCX::ADC_CAL_CNT_MAX - 2);
84
85        // Disconnect calibration source
86        ADCX::connect_cal(source, false);
87
88        cal_val
89    }
90}
91
92#[doc(hidden)]
93pub trait RegisterAccess {
94    fn set_attenuation(channel: usize, attenuation: u8);
95
96    fn clear_dig_force();
97
98    fn set_start_force();
99
100    fn set_en_pad_force();
101
102    fn set_en_pad(channel: u8);
103
104    fn clear_start_sample();
105
106    fn start_sample();
107
108    /// Check if sampling is done
109    fn is_done() -> bool;
110
111    /// Read sample data
112    fn read_data() -> u16;
113
114    /// Set up ADC hardware for calibration
115    fn calibration_init();
116
117    /// Set calibration parameter to ADC hardware
118    fn set_init_code(data: u16);
119
120    /// Reset flags
121    fn reset();
122}
123
124impl RegisterAccess for crate::peripherals::ADC1<'_> {
125    fn set_attenuation(channel: usize, attenuation: u8) {
126        SENS::regs().sar_atten1().modify(|r, w| {
127            let new_value = (r.bits() & !(0b11 << (channel * 2)))
128                | (((attenuation & 0b11) as u32) << (channel * 2));
129
130            unsafe { w.sar1_atten().bits(new_value) }
131        });
132    }
133
134    fn clear_dig_force() {
135        SENS::regs()
136            .sar_meas1_mux()
137            .modify(|_, w| w.sar1_dig_force().clear_bit());
138    }
139
140    fn set_start_force() {
141        SENS::regs()
142            .sar_meas1_ctrl2()
143            .modify(|_, w| w.meas1_start_force().set_bit());
144    }
145
146    fn set_en_pad_force() {
147        SENS::regs()
148            .sar_meas1_ctrl2()
149            .modify(|_, w| w.sar1_en_pad_force().set_bit());
150    }
151
152    fn set_en_pad(channel: u8) {
153        SENS::regs()
154            .sar_meas1_ctrl2()
155            .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
156    }
157
158    fn clear_start_sample() {
159        SENS::regs()
160            .sar_meas1_ctrl2()
161            .modify(|_, w| w.meas1_start_sar().clear_bit());
162    }
163
164    fn start_sample() {
165        // ADC1 must be idle before a new software trigger. See
166        // https://github.com/espressif/esp-idf/blob/8c750b0/components/hal/esp32s3/include/hal/adc_ll.h#L973
167        while meas1_busy() {}
168
169        SENS::regs()
170            .sar_meas1_ctrl2()
171            .modify(|_, w| w.meas1_start_sar().set_bit());
172    }
173
174    fn is_done() -> bool {
175        SENS::regs()
176            .sar_meas1_ctrl2()
177            .read()
178            .meas1_done_sar()
179            .bit_is_set()
180    }
181
182    fn read_data() -> u16 {
183        SENS::regs()
184            .sar_meas1_ctrl2()
185            .read()
186            .meas1_data_sar()
187            .bits()
188    }
189
190    #[cfg(any(esp32s2, esp32s3))]
191    fn calibration_init() {
192        // https://github.com/espressif/esp-idf/blob/800f141f94c0f880c162de476512e183df671307/components/hal/esp32s3/include/hal/adc_ll.h#L833
193        // https://github.com/espressif/esp-idf/blob/800f141f94c0f880c162de476512e183df671307/components/hal/esp32s2/include/hal/adc_ll.h#L1145
194        regi2c::ADC_SAR1_DREF.write_field(4);
195    }
196
197    fn set_init_code(data: u16) {
198        let [msb, lsb] = data.to_be_bytes();
199
200        regi2c::ADC_SAR1_INITIAL_CODE_HIGH.write_field(msb);
201        regi2c::ADC_SAR1_INITIAL_CODE_LOW.write_field(lsb);
202    }
203
204    fn reset() {
205        let adc = APB_SARADC::regs();
206        let sensors = SENS::regs();
207
208        adc.int_clr().write(|w| w.adc1_done().clear_bit_by_one());
209        LPWR::regs()
210            .int_clr()
211            .write(|w| w.saradc1().clear_bit_by_one());
212
213        sensors
214            .sar_meas1_ctrl2()
215            .modify(|_, w| w.meas1_start_sar().clear_bit());
216    }
217}
218
219fn meas1_busy() -> bool {
220    let status = SENS::regs().sar_slave_addr1().read();
221    cfg_select! {
222        esp32s3 => status.sar_saradc_meas_status().bits() != 0,
223        _ => status.meas_status().bits() != 0,
224    }
225}
226
227impl super::CalibrationAccess for crate::peripherals::ADC1<'_> {
228    const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
229    const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
230    const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
231
232    fn enable_vdef(enable: bool) {
233        regi2c::ADC_SAR1_DREF.write_field(enable as u8);
234    }
235
236    fn connect_cal(source: AdcCalSource, enable: bool) {
237        match source {
238            AdcCalSource::Gnd => regi2c::ADC_SAR1_ENCAL_GND.write_field(enable as u8),
239            AdcCalSource::Ref => regi2c::ADC_SAR1_ENCAL_REF.write_field(enable as u8),
240        }
241    }
242}
243
244impl RegisterAccess for crate::peripherals::ADC2<'_> {
245    fn set_attenuation(channel: usize, attenuation: u8) {
246        SENS::regs().sar_atten2().modify(|r, w| {
247            let new_value = (r.bits() & !(0b11 << (channel * 2)))
248                | (((attenuation & 0b11) as u32) << (channel * 2));
249
250            unsafe { w.sar2_atten().bits(new_value) }
251        });
252    }
253
254    fn clear_dig_force() {
255        SENS::regs()
256            .sar_meas2_mux()
257            .modify(|_, w| w.sar2_rtc_force().set_bit());
258
259        APB_SARADC::regs()
260            .arb_ctrl()
261            .modify(|_, w| w.rtc_force().set_bit());
262    }
263
264    fn set_start_force() {
265        SENS::regs()
266            .sar_meas2_ctrl2()
267            .modify(|_, w| w.meas2_start_force().set_bit());
268    }
269
270    fn set_en_pad_force() {
271        SENS::regs()
272            .sar_meas2_ctrl2()
273            .modify(|_, w| w.sar2_en_pad_force().set_bit());
274    }
275
276    fn set_en_pad(channel: u8) {
277        SENS::regs()
278            .sar_meas2_ctrl2()
279            .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
280    }
281
282    fn clear_start_sample() {
283        SENS::regs()
284            .sar_meas2_ctrl2()
285            .modify(|_, w| w.meas2_start_sar().clear_bit());
286    }
287
288    fn start_sample() {
289        SENS::regs()
290            .sar_meas2_ctrl2()
291            .modify(|_, w| w.meas2_start_sar().set_bit());
292    }
293
294    fn is_done() -> bool {
295        SENS::regs()
296            .sar_meas2_ctrl2()
297            .read()
298            .meas2_done_sar()
299            .bit_is_set()
300    }
301
302    fn read_data() -> u16 {
303        SENS::regs()
304            .sar_meas2_ctrl2()
305            .read()
306            .meas2_data_sar()
307            .bits()
308    }
309
310    #[cfg(any(esp32s2, esp32s3))]
311    fn calibration_init() {
312        regi2c::ADC_SAR2_DREF.write_field(4);
313    }
314
315    fn set_init_code(data: u16) {
316        let [msb, lsb] = data.to_be_bytes();
317
318        regi2c::ADC_SAR2_INITIAL_CODE_HIGH.write_field(msb);
319        regi2c::ADC_SAR2_INITIAL_CODE_LOW.write_field(lsb);
320    }
321
322    fn reset() {
323        let adc = APB_SARADC::regs();
324        let sensors = SENS::regs();
325
326        adc.int_clr().write(|w| w.adc2_done().clear_bit_by_one());
327        LPWR::regs()
328            .int_clr()
329            .write(|w| w.saradc2().clear_bit_by_one());
330
331        sensors
332            .sar_meas2_ctrl2()
333            .modify(|_, w| w.meas2_start_sar().clear_bit());
334    }
335}
336
337impl super::CalibrationAccess for crate::peripherals::ADC2<'_> {
338    const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
339    const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
340    const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
341
342    fn enable_vdef(enable: bool) {
343        regi2c::ADC_SAR2_DREF.write_field(enable as u8);
344    }
345
346    fn connect_cal(source: AdcCalSource, enable: bool) {
347        match source {
348            AdcCalSource::Gnd => regi2c::ADC_SAR2_ENCAL_GND.write_field(enable as u8),
349            AdcCalSource::Ref => regi2c::ADC_SAR2_ENCAL_REF.write_field(enable as u8),
350        }
351    }
352}
353
354/// Analog-to-Digital Converter peripheral driver.
355pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
356    _adc: ADC,
357    active_channel: Option<u8>,
358    last_init_code: u16,
359    _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
360    _phantom: PhantomData<(Dm, &'d mut ())>,
361}
362
363impl<'d, ADCX> Adc<'d, ADCX, Blocking>
364where
365    ADCX: RegisterAccess + 'd,
366{
367    /// Configure a given ADC instance using the provided configuration, and
368    /// initialize the ADC for use
369    pub fn new(adc_instance: ADCX, config: AdcConfig<ADCX>) -> Self {
370        let guard = GenericPeripheralGuard::new();
371        let sensors = SENS::regs();
372
373        // Set attenuation for pins
374        let attenuations = config.attenuations;
375
376        for (channel, attenuation) in attenuations.iter().enumerate() {
377            if let Some(attenuation) = attenuation {
378                ADCX::set_attenuation(channel, *attenuation as u8);
379            }
380        }
381
382        // Set controller to RTC
383        ADCX::clear_dig_force();
384        ADCX::set_start_force();
385        ADCX::set_en_pad_force();
386        sensors.sar_hall_ctrl().modify(|_, w| {
387            w.xpd_hall_force().set_bit();
388            w.hall_phase_force().set_bit()
389        });
390
391        // Set power to SW power on
392        #[cfg(esp32s2)]
393        sensors
394            .sar_meas1_ctrl1()
395            .modify(|_, w| w.rtc_saradc_clkgate_en().set_bit());
396
397        #[cfg(esp32s3)]
398        sensors
399            .sar_peri_clk_gate_conf()
400            .modify(|_, w| w.saradc_clk_en().set_bit());
401
402        sensors.sar_power_xpd_sar().modify(|_, w| unsafe {
403            w.sarclk_en().set_bit();
404            w.force_xpd_sar().bits(0b11)
405        });
406
407        // disable AMP
408        sensors
409            .sar_meas1_ctrl1()
410            .modify(|_, w| unsafe { w.force_xpd_amp().bits(0b11) });
411        sensors.sar_amp_ctrl3().modify(|_, w| unsafe {
412            w.amp_rst_fb_fsm().bits(0);
413            w.amp_short_ref_fsm().bits(0);
414            w.amp_short_ref_gnd_fsm().bits(0)
415        });
416        sensors.sar_amp_ctrl1().modify(|_, w| unsafe {
417            w.sar_amp_wait1().bits(1);
418            w.sar_amp_wait2().bits(1)
419        });
420        sensors
421            .sar_amp_ctrl2()
422            .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
423
424        Adc {
425            _adc: adc_instance,
426            active_channel: None,
427            last_init_code: 0,
428            _guard: guard,
429            _phantom: PhantomData,
430        }
431    }
432
433    /// Reconfigures the ADC driver to operate in asynchronous mode.
434    pub fn into_async(mut self) -> Adc<'d, ADCX, Async> {
435        acquire_async_adc();
436        self.set_interrupt_handler(adc_interrupt_handler);
437
438        // Reset interrupt flags and the start bit so both ADC units start from a
439        // known state in async mode.
440        ADCX::reset();
441
442        Adc {
443            _adc: self._adc,
444            active_channel: self.active_channel,
445            last_init_code: self.last_init_code,
446            _guard: self._guard,
447            _phantom: PhantomData,
448        }
449    }
450
451    /// Start and wait for a conversion on the specified pin and return the
452    /// result
453    pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> u16
454    where
455        PIN: AdcChannel,
456        CS: AdcCalScheme<ADCX>,
457    {
458        self.start_sample(pin);
459
460        // Wait for ADC to finish conversion
461        while !ADCX::is_done() {}
462
463        // Get converted value
464        let converted_value = ADCX::read_data();
465        ADCX::reset();
466
467        // Postprocess converted value according to calibration scheme used for pin
468        pin.cal_scheme.adc_val(converted_value)
469    }
470
471    /// Request that the ADC begin a conversion on the specified pin
472    ///
473    /// This method takes an [AdcPin](super::AdcPin) reference, as it is
474    /// expected that the ADC will be able to sample whatever channel
475    /// underlies the pin.
476    pub fn read_oneshot<PIN, CS>(
477        &mut self,
478        pin: &mut super::AdcPin<PIN, ADCX, CS>,
479    ) -> nb::Result<u16, ()>
480    where
481        PIN: super::AdcChannel,
482        CS: super::AdcCalScheme<ADCX>,
483    {
484        if let Some(active_channel) = self.active_channel {
485            // There is conversion in progress:
486            // - if it's for a different channel try again later
487            // - if it's for the given channel, go ahead and check progress
488            if active_channel != pin.pin.adc_channel() {
489                return Err(nb::Error::WouldBlock);
490            }
491        } else {
492            // If no conversions are in progress, start a new one for given channel
493            self.active_channel = Some(pin.pin.adc_channel());
494
495            self.start_sample(pin);
496        }
497
498        // Wait for ADC to finish conversion
499        let conversion_finished = ADCX::is_done();
500        if !conversion_finished {
501            return Err(nb::Error::WouldBlock);
502        }
503
504        // Get converted value
505        let converted_value = ADCX::read_data();
506        ADCX::reset();
507
508        // Postprocess converted value according to calibration scheme used for pin
509        let converted_value = pin.cal_scheme.adc_val(converted_value);
510
511        // Mark that no conversions are currently in progress
512        self.active_channel = None;
513
514        Ok(converted_value)
515    }
516}
517
518fn adc_interrupt_sources() -> [Interrupt; 2] {
519    // Oneshot conversion uses the RTC SAR controller. Completion is signalled on
520    // RTC_CORE (`RTC_CNTL` SARADCn). APB_ADC is bound as well for the digital
521    // `APB_SARADC_ADCn_DONE` bits.
522    [Interrupt::APB_ADC, Interrupt::RTC_CORE]
523}
524
525impl<ADCX> crate::private::Sealed for Adc<'_, ADCX, Blocking> {}
526
527impl<ADCX> InterruptConfigurable for Adc<'_, ADCX, Blocking> {
528    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
529        for interrupt in adc_interrupt_sources() {
530            for core in crate::system::Cpu::other() {
531                crate::interrupt::disable(core, interrupt);
532            }
533            crate::interrupt::bind_handler(interrupt, handler);
534        }
535    }
536}
537
538impl<'d, ADCX, Dm> Adc<'d, ADCX, Dm>
539where
540    ADCX: RegisterAccess + 'd,
541    Dm: crate::DriverMode,
542{
543    fn start_sample<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>)
544    where
545        PIN: AdcChannel,
546        CS: AdcCalScheme<ADCX>,
547    {
548        // Set ADC unit calibration according used scheme for pin
549        let init_code = pin.cal_scheme.adc_cal();
550        if self.last_init_code != init_code {
551            ADCX::calibration_init();
552            ADCX::set_init_code(init_code);
553            self.last_init_code = init_code;
554        }
555
556        ADCX::set_en_pad(pin.pin.adc_channel());
557
558        ADCX::clear_start_sample();
559        ADCX::start_sample();
560    }
561}
562
563impl<'d, ADCX> Adc<'d, ADCX, Async>
564where
565    ADCX: RegisterAccess + 'd,
566{
567    /// Creates a new instance in [`Blocking`] mode.
568    pub fn into_blocking(self) -> Adc<'d, ADCX, Blocking> {
569        if release_async_adc() {
570            // Disable ADC interrupt on all cores if the last async ADC instance is disabled
571            for interrupt in adc_interrupt_sources() {
572                for cpu in crate::system::Cpu::all() {
573                    crate::interrupt::disable(cpu, interrupt);
574                }
575            }
576        }
577        Adc {
578            _adc: self._adc,
579            active_channel: self.active_channel,
580            last_init_code: self.last_init_code,
581            _guard: self._guard,
582            _phantom: PhantomData,
583        }
584    }
585
586    /// Starts a conversion on the specified pin and waits until it completes.
587    ///
588    /// This method takes an [`AdcPin`] reference, as it is expected that the
589    /// ADC will be able to sample whatever channel underlies the pin.
590    pub async fn read_oneshot<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCX, CS>) -> u16
591    where
592        ADCX: Instance,
593        PIN: AdcChannel,
594        CS: AdcCalScheme<ADCX>,
595    {
596        self.start_sample(pin);
597
598        AdcFuture::new(self).await;
599
600        let converted_value = ADCX::read_data();
601        ADCX::reset();
602
603        pin.cal_scheme.adc_val(converted_value)
604    }
605}
606
607static ASYNC_ADC_COUNT: AtomicU32 = AtomicU32::new(0);
608
609fn acquire_async_adc() {
610    ASYNC_ADC_COUNT.fetch_add(1, Ordering::Relaxed);
611}
612
613fn release_async_adc() -> bool {
614    ASYNC_ADC_COUNT.fetch_sub(1, Ordering::Relaxed) == 1
615}
616
617#[handler]
618#[ram]
619fn adc_interrupt_handler() {
620    let apb_status = APB_SARADC::regs().int_st().read();
621    let rtc_status = LPWR::regs().int_st().read();
622
623    if apb_status.adc1_done().bit_is_set() || rtc_status.saradc1().bit_is_set() {
624        unsafe { handle_async(crate::peripherals::ADC1::steal()) }
625    }
626
627    if apb_status.adc2_done().bit_is_set() || rtc_status.saradc2().bit_is_set() {
628        unsafe { handle_async(crate::peripherals::ADC2::steal()) }
629    }
630}
631
632fn handle_async<ADCX: Instance>(_instance: ADCX) {
633    ADCX::clear_interrupt();
634    ADCX::unlisten();
635    ADCX::waker().wake();
636}
637
638/// Enable asynchronous access.
639pub trait Instance: crate::private::Sealed {
640    /// Enable the ADC interrupt
641    fn listen();
642
643    /// Disable the ADC interrupt
644    fn unlisten();
645
646    /// Clear the ADC interrupt
647    fn clear_interrupt();
648
649    /// Obtain the waker for the ADC interrupt
650    fn waker() -> &'static AtomicWaker;
651}
652
653impl Instance for crate::peripherals::ADC1<'_> {
654    fn listen() {
655        APB_SARADC::regs()
656            .int_ena()
657            .modify(|_, w| w.adc1_done().set_bit());
658
659        SENS::regs().sar_reader1_ctrl().modify(|_, w| {
660            cfg_select! {
661                esp32s3 => w.sar_sar1_int_en().set_bit(),
662                _ => w.sar1_int_en().set_bit(),
663            }
664        });
665
666        LPWR::regs().int_ena().modify(|_, w| w.saradc1().set_bit());
667    }
668
669    fn unlisten() {
670        APB_SARADC::regs()
671            .int_ena()
672            .modify(|_, w| w.adc1_done().clear_bit());
673
674        SENS::regs().sar_reader1_ctrl().modify(|_, w| {
675            cfg_select! {
676                esp32s3 => w.sar_sar1_int_en().clear_bit(),
677                _ => w.sar1_int_en().clear_bit(),
678            }
679        });
680
681        LPWR::regs()
682            .int_ena()
683            .modify(|_, w| w.saradc1().clear_bit());
684    }
685
686    fn clear_interrupt() {
687        APB_SARADC::regs()
688            .int_clr()
689            .write(|w| w.adc1_done().clear_bit_by_one());
690        LPWR::regs()
691            .int_clr()
692            .write(|w| w.saradc1().clear_bit_by_one());
693    }
694
695    fn waker() -> &'static AtomicWaker {
696        static WAKER: AtomicWaker = AtomicWaker::new();
697
698        &WAKER
699    }
700}
701
702impl Instance for crate::peripherals::ADC2<'_> {
703    fn listen() {
704        APB_SARADC::regs()
705            .int_ena()
706            .modify(|_, w| w.adc2_done().set_bit());
707
708        SENS::regs().sar_reader2_ctrl().modify(|_, w| {
709            cfg_select! {
710                esp32s3 => w.sar_sar2_int_en().set_bit(),
711                _ => w.sar2_int_en().set_bit(),
712            }
713        });
714
715        LPWR::regs().int_ena().modify(|_, w| w.saradc2().set_bit());
716    }
717
718    fn unlisten() {
719        APB_SARADC::regs()
720            .int_ena()
721            .modify(|_, w| w.adc2_done().clear_bit());
722
723        SENS::regs().sar_reader2_ctrl().modify(|_, w| {
724            cfg_select! {
725                esp32s3 => w.sar_sar2_int_en().clear_bit(),
726                _ => w.sar2_int_en().clear_bit(),
727            }
728        });
729
730        LPWR::regs()
731            .int_ena()
732            .modify(|_, w| w.saradc2().clear_bit());
733    }
734
735    fn clear_interrupt() {
736        APB_SARADC::regs()
737            .int_clr()
738            .write(|w| w.adc2_done().clear_bit_by_one());
739        LPWR::regs()
740            .int_clr()
741            .write(|w| w.saradc2().clear_bit_by_one());
742    }
743
744    fn waker() -> &'static AtomicWaker {
745        static WAKER: AtomicWaker = AtomicWaker::new();
746
747        &WAKER
748    }
749}
750
751#[must_use = "futures do nothing unless you `.await` or poll them"]
752struct AdcFuture<ADCX: Instance> {
753    phantom: PhantomData<ADCX>,
754    _wake_lock: WakeLock,
755}
756
757impl<ADCX: Instance> AdcFuture<ADCX> {
758    fn new(_self: &Adc<'_, ADCX, Async>) -> Self {
759        ADCX::listen();
760        Self {
761            phantom: PhantomData,
762            _wake_lock: WakeLock::new(),
763        }
764    }
765}
766
767impl<ADCX: Instance + RegisterAccess> core::future::Future for AdcFuture<ADCX> {
768    type Output = ();
769
770    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
771        ADCX::waker().register(cx.waker());
772        if ADCX::is_done() {
773            ADCX::clear_interrupt();
774            Poll::Ready(())
775        } else {
776            Poll::Pending
777        }
778    }
779}
780
781impl<ADCX: Instance> Drop for AdcFuture<ADCX> {
782    fn drop(&mut self) {
783        ADCX::unlisten();
784    }
785}
786
787#[cfg(any(esp32s2, esp32s3))]
788impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
789    fn init_code(atten: Attenuation) -> Option<u16> {
790        crate::efuse::rtc_calib_init_code(AdcCalibUnit::ADC1, atten)
791    }
792
793    fn cal_mv(atten: Attenuation) -> u16 {
794        crate::efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC1, atten)
795    }
796
797    fn cal_code(atten: Attenuation) -> Option<u16> {
798        crate::efuse::rtc_calib_cal_code(AdcCalibUnit::ADC1, atten)
799    }
800}
801
802#[cfg(any(esp32s2, esp32s3))]
803impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
804    fn init_code(atten: Attenuation) -> Option<u16> {
805        crate::efuse::rtc_calib_init_code(AdcCalibUnit::ADC2, atten)
806    }
807
808    fn cal_mv(atten: Attenuation) -> u16 {
809        crate::efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC2, atten)
810    }
811
812    fn cal_code(atten: Attenuation) -> Option<u16> {
813        crate::efuse::rtc_calib_cal_code(AdcCalibUnit::ADC2, atten)
814    }
815}