Skip to main content

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