1use core::marker::PhantomData;
2
3cfg_if::cfg_if! {
4 if #[cfg(esp32c6)] {
5 use Interrupt::APB_SARADC as InterruptSource;
6 } else {
7 use Interrupt::APB_ADC as InterruptSource;
8 }
9}
10
11#[cfg(not(esp32h2))]
12pub use self::calibration::*;
13use super::{AdcCalSource, AdcConfig, Attenuation};
14#[cfg(any(esp32c6, esp32h2))]
15use crate::clock::clocks_ll::regi2c_write_mask;
16#[cfg(any(esp32c2, esp32c3, esp32c6))]
17use crate::efuse::Efuse;
18use crate::{
19 analog::adc::asynch::AdcFuture,
20 interrupt::{InterruptConfigurable, InterruptHandler},
21 peripheral::PeripheralRef,
22 peripherals::{Interrupt, APB_SARADC},
23 system::{GenericPeripheralGuard, Peripheral},
24 Async,
25 Blocking,
26};
27
28mod calibration;
29
30#[cfg(any(esp32c2, esp32c3))]
32#[inline(always)]
33fn regi2c_write_mask(block: u8, host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) {
34 unsafe {
35 crate::rom::rom_i2c_writeReg_Mask(
36 block as _,
37 host_id as _,
38 reg_add as _,
39 msb as _,
40 lsb as _,
41 data as _,
42 );
43 }
44}
45
46cfg_if::cfg_if! {
53 if #[cfg(adc1)] {
54 const I2C_SAR_ADC: u8 = 0x69;
55 const I2C_SAR_ADC_HOSTID: u8 = 0;
56
57 const ADC_VAL_MASK: u16 = 0xfff;
58 const ADC_CAL_CNT_MAX: u16 = 32;
59 const ADC_CAL_CHANNEL: u16 = 15;
60
61 const ADC_SAR1_ENCAL_GND_ADDR: u8 = 0x7;
62 const ADC_SAR1_ENCAL_GND_ADDR_MSB: u8 = 5;
63 const ADC_SAR1_ENCAL_GND_ADDR_LSB: u8 = 5;
64
65 const ADC_SAR1_INITIAL_CODE_HIGH_ADDR: u8 = 0x1;
66 const ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB: u8 = 0x3;
67 const ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB: u8 = 0x0;
68
69 const ADC_SAR1_INITIAL_CODE_LOW_ADDR: u8 = 0x0;
70 const ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB: u8 = 0x7;
71 const ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB: u8 = 0x0;
72
73 const ADC_SAR1_DREF_ADDR: u8 = 0x2;
74 const ADC_SAR1_DREF_ADDR_MSB: u8 = 0x6;
75 const ADC_SAR1_DREF_ADDR_LSB: u8 = 0x4;
76
77 const ADC_SARADC1_ENCAL_REF_ADDR: u8 = 0x7;
78 const ADC_SARADC1_ENCAL_REF_ADDR_MSB: u8 = 4;
79 const ADC_SARADC1_ENCAL_REF_ADDR_LSB: u8 = 4;
80 }
81}
82
83cfg_if::cfg_if! {
84 if #[cfg(adc2)] {
85 const ADC_SAR2_ENCAL_GND_ADDR: u8 = 0x7;
86 const ADC_SAR2_ENCAL_GND_ADDR_MSB: u8 = 7;
87 const ADC_SAR2_ENCAL_GND_ADDR_LSB: u8 = 7;
88
89 const ADC_SAR2_INITIAL_CODE_HIGH_ADDR: u8 = 0x4;
90 const ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB: u8 = 0x3;
91 const ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB: u8 = 0x0;
92
93 const ADC_SAR2_INITIAL_CODE_LOW_ADDR: u8 = 0x3;
94 const ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB: u8 = 0x7;
95 const ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB: u8 = 0x0;
96
97 const ADC_SAR2_DREF_ADDR: u8 = 0x5;
98 const ADC_SAR2_DREF_ADDR_MSB: u8 = 0x6;
99 const ADC_SAR2_DREF_ADDR_LSB: u8 = 0x4;
100
101 const ADC_SARADC2_ENCAL_REF_ADDR: u8 = 0x7;
102 const ADC_SARADC2_ENCAL_REF_ADDR_MSB: u8 = 6;
103 const ADC_SARADC2_ENCAL_REF_ADDR_LSB: u8 = 6;
104 }
105}
106
107cfg_if::cfg_if! {
110 if #[cfg(esp32c6)] {
111 pub(super) const NUM_ATTENS: usize = 7;
112 } else {
113 pub(super) const NUM_ATTENS: usize = 5;
114 }
115}
116
117#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
119#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120#[allow(clippy::enum_variant_names, reason = "peripheral is unstable")]
121pub enum Resolution {
122 #[default]
124 Resolution12Bit,
125}
126
127impl<ADCI> AdcConfig<ADCI>
128where
129 ADCI: RegisterAccess,
130{
131 pub fn adc_calibrate(atten: Attenuation, source: AdcCalSource) -> u16
133 where
134 ADCI: super::CalibrationAccess,
135 {
136 let mut adc_max: u16 = 0;
137 let mut adc_min: u16 = u16::MAX;
138 let mut adc_sum: u32 = 0;
139
140 ADCI::enable_vdef(true);
141
142 ADCI::config_onetime_sample(ADC_CAL_CHANNEL as u8, atten as u8);
144
145 ADCI::connect_cal(source, true);
147
148 for _ in 0..ADC_CAL_CNT_MAX {
149 ADCI::set_init_code(0);
150
151 ADCI::start_onetime_sample();
153
154 while !ADCI::is_done() {}
156
157 let adc = ADCI::read_data() & ADC_VAL_MASK;
158
159 ADCI::reset();
160
161 adc_sum += adc as u32;
162 adc_max = adc.max(adc_max);
163 adc_min = adc.min(adc_min);
164 }
165
166 let cal_val = (adc_sum - adc_max as u32 - adc_min as u32) as u16 / (ADC_CAL_CNT_MAX - 2);
167
168 ADCI::connect_cal(source, false);
170
171 cal_val
172 }
173}
174
175#[doc(hidden)]
176pub trait RegisterAccess {
177 fn config_onetime_sample(channel: u8, attenuation: u8);
179
180 fn start_onetime_sample();
182
183 fn is_done() -> bool;
185
186 fn read_data() -> u16;
188
189 fn reset();
191
192 fn set_init_code(data: u16);
194}
195
196#[cfg(adc1)]
197impl RegisterAccess for crate::peripherals::ADC1 {
198 fn config_onetime_sample(channel: u8, attenuation: u8) {
199 APB_SARADC::regs().onetime_sample().modify(|_, w| unsafe {
200 w.saradc1_onetime_sample().set_bit();
201 w.onetime_channel().bits(channel);
202 w.onetime_atten().bits(attenuation)
203 });
204 }
205
206 fn start_onetime_sample() {
207 APB_SARADC::regs()
208 .onetime_sample()
209 .modify(|_, w| w.onetime_start().set_bit());
210 }
211
212 fn is_done() -> bool {
213 APB_SARADC::regs().int_raw().read().adc1_done().bit()
214 }
215
216 fn read_data() -> u16 {
217 APB_SARADC::regs()
218 .sar1data_status()
219 .read()
220 .saradc1_data()
221 .bits() as u16
222 & 0xfff
223 }
224
225 fn reset() {
226 APB_SARADC::regs()
228 .int_clr()
229 .write(|w| w.adc1_done().clear_bit_by_one());
230
231 APB_SARADC::regs()
233 .onetime_sample()
234 .modify(|_, w| w.onetime_start().clear_bit());
235 }
236
237 fn set_init_code(data: u16) {
238 let [msb, lsb] = data.to_be_bytes();
239
240 regi2c_write_mask(
241 I2C_SAR_ADC,
242 I2C_SAR_ADC_HOSTID,
243 ADC_SAR1_INITIAL_CODE_HIGH_ADDR,
244 ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB,
245 ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB,
246 msb as _,
247 );
248 regi2c_write_mask(
249 I2C_SAR_ADC,
250 I2C_SAR_ADC_HOSTID,
251 ADC_SAR1_INITIAL_CODE_LOW_ADDR,
252 ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB,
253 ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB,
254 lsb as _,
255 );
256 }
257}
258
259#[cfg(adc1)]
260impl super::CalibrationAccess for crate::peripherals::ADC1 {
261 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
262 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
263 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
264
265 fn enable_vdef(enable: bool) {
266 let value = enable as _;
267 regi2c_write_mask(
268 I2C_SAR_ADC,
269 I2C_SAR_ADC_HOSTID,
270 ADC_SAR1_DREF_ADDR,
271 ADC_SAR1_DREF_ADDR_MSB,
272 ADC_SAR1_DREF_ADDR_LSB,
273 value,
274 );
275 }
276
277 fn connect_cal(source: AdcCalSource, enable: bool) {
278 let value = enable as _;
279 match source {
280 AdcCalSource::Gnd => regi2c_write_mask(
281 I2C_SAR_ADC,
282 I2C_SAR_ADC_HOSTID,
283 ADC_SAR1_ENCAL_GND_ADDR,
284 ADC_SAR1_ENCAL_GND_ADDR_MSB,
285 ADC_SAR1_ENCAL_GND_ADDR_LSB,
286 value,
287 ),
288 AdcCalSource::Ref => regi2c_write_mask(
289 I2C_SAR_ADC,
290 I2C_SAR_ADC_HOSTID,
291 ADC_SARADC1_ENCAL_REF_ADDR,
292 ADC_SARADC1_ENCAL_REF_ADDR_MSB,
293 ADC_SARADC1_ENCAL_REF_ADDR_LSB,
294 value,
295 ),
296 }
297 }
298}
299
300#[cfg(adc2)]
301impl RegisterAccess for crate::peripherals::ADC2 {
302 fn config_onetime_sample(channel: u8, attenuation: u8) {
303 APB_SARADC::regs().onetime_sample().modify(|_, w| unsafe {
304 w.saradc2_onetime_sample().set_bit();
305 w.onetime_channel().bits(channel);
306 w.onetime_atten().bits(attenuation)
307 });
308 }
309
310 fn start_onetime_sample() {
311 APB_SARADC::regs()
312 .onetime_sample()
313 .modify(|_, w| w.onetime_start().set_bit());
314 }
315
316 fn is_done() -> bool {
317 APB_SARADC::regs().int_raw().read().adc2_done().bit()
318 }
319
320 fn read_data() -> u16 {
321 APB_SARADC::regs()
322 .sar2data_status()
323 .read()
324 .saradc2_data()
325 .bits() as u16
326 & 0xfff
327 }
328
329 fn reset() {
330 APB_SARADC::regs()
331 .int_clr()
332 .write(|w| w.adc2_done().clear_bit_by_one());
333
334 APB_SARADC::regs()
335 .onetime_sample()
336 .modify(|_, w| w.onetime_start().clear_bit());
337 }
338
339 fn set_init_code(data: u16) {
340 let [msb, lsb] = data.to_be_bytes();
341
342 regi2c_write_mask(
343 I2C_SAR_ADC,
344 I2C_SAR_ADC_HOSTID,
345 ADC_SAR2_INITIAL_CODE_HIGH_ADDR,
346 ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB,
347 ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB,
348 msb as _,
349 );
350 regi2c_write_mask(
351 I2C_SAR_ADC,
352 I2C_SAR_ADC_HOSTID,
353 ADC_SAR2_INITIAL_CODE_LOW_ADDR,
354 ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB,
355 ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB,
356 lsb as _,
357 );
358 }
359}
360
361#[cfg(adc2)]
362impl super::CalibrationAccess for crate::peripherals::ADC2 {
363 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
364 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
365 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
366
367 fn enable_vdef(enable: bool) {
368 let value = enable as _;
369 regi2c_write_mask(
370 I2C_SAR_ADC,
371 I2C_SAR_ADC_HOSTID,
372 ADC_SAR2_DREF_ADDR,
373 ADC_SAR2_DREF_ADDR_MSB,
374 ADC_SAR2_DREF_ADDR_LSB,
375 value,
376 );
377 }
378
379 fn connect_cal(source: AdcCalSource, enable: bool) {
380 let value = enable as _;
381 match source {
382 AdcCalSource::Gnd => regi2c_write_mask(
383 I2C_SAR_ADC,
384 I2C_SAR_ADC_HOSTID,
385 ADC_SAR2_ENCAL_GND_ADDR,
386 ADC_SAR2_ENCAL_GND_ADDR_MSB,
387 ADC_SAR2_ENCAL_GND_ADDR_LSB,
388 value,
389 ),
390 AdcCalSource::Ref => regi2c_write_mask(
391 I2C_SAR_ADC,
392 I2C_SAR_ADC_HOSTID,
393 ADC_SARADC2_ENCAL_REF_ADDR,
394 ADC_SARADC2_ENCAL_REF_ADDR_MSB,
395 ADC_SARADC2_ENCAL_REF_ADDR_LSB,
396 value,
397 ),
398 }
399 }
400}
401
402pub struct Adc<'d, ADCI, Dm: crate::DriverMode> {
404 _adc: PeripheralRef<'d, ADCI>,
405 attenuations: [Option<Attenuation>; NUM_ATTENS],
406 active_channel: Option<u8>,
407 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
408 _phantom: PhantomData<Dm>,
409}
410
411impl<'d, ADCI> Adc<'d, ADCI, Blocking>
412where
413 ADCI: RegisterAccess + 'd,
414{
415 pub fn new(
418 adc_instance: impl crate::peripheral::Peripheral<P = ADCI> + 'd,
419 config: AdcConfig<ADCI>,
420 ) -> Self {
421 let guard = GenericPeripheralGuard::new();
422
423 APB_SARADC::regs().ctrl().modify(|_, w| unsafe {
424 w.start_force().set_bit();
425 w.start().set_bit();
426 w.sar_clk_gated().set_bit();
427 w.xpd_sar_force().bits(0b11)
428 });
429
430 Adc {
431 _adc: adc_instance.into_ref(),
432 attenuations: config.attenuations,
433 active_channel: None,
434 _guard: guard,
435 _phantom: PhantomData,
436 }
437 }
438
439 pub fn into_async(mut self) -> Adc<'d, ADCI, Async> {
441 asynch::acquire_async_adc();
442 self.set_interrupt_handler(asynch::adc_interrupt_handler);
443
444 ADCI::reset();
448
449 Adc {
450 _adc: self._adc,
451 attenuations: self.attenuations,
452 active_channel: self.active_channel,
453 _guard: self._guard,
454 _phantom: PhantomData,
455 }
456 }
457
458 pub fn read_oneshot<PIN, CS>(
464 &mut self,
465 pin: &mut super::AdcPin<PIN, ADCI, CS>,
466 ) -> nb::Result<u16, ()>
467 where
468 PIN: super::AdcChannel,
469 CS: super::AdcCalScheme<ADCI>,
470 {
471 if self.attenuations[PIN::CHANNEL as usize].is_none() {
472 panic!("Channel {} is not configured reading!", PIN::CHANNEL);
473 }
474
475 if let Some(active_channel) = self.active_channel {
476 if active_channel != PIN::CHANNEL {
480 return Err(nb::Error::WouldBlock);
481 }
482 } else {
483 self.active_channel = Some(PIN::CHANNEL);
485
486 ADCI::set_init_code(pin.cal_scheme.adc_cal());
488
489 let channel = self.active_channel.unwrap();
490 let attenuation = self.attenuations[channel as usize].unwrap() as u8;
491 ADCI::config_onetime_sample(channel, attenuation);
492 ADCI::start_onetime_sample();
493
494 #[cfg(esp32c6)]
497 {
498 crate::rom::ets_delay_us(40);
499 ADCI::start_onetime_sample();
500 }
501 }
502
503 let conversion_finished = ADCI::is_done();
505 if !conversion_finished {
506 return Err(nb::Error::WouldBlock);
507 }
508
509 let converted_value = ADCI::read_data();
511 ADCI::reset();
512
513 let converted_value = pin.cal_scheme.adc_val(converted_value);
515
516 self.active_channel = None;
528
529 Ok(converted_value)
530 }
531}
532
533impl<ADCI> crate::private::Sealed for Adc<'_, ADCI, Blocking> {}
534
535impl<ADCI> InterruptConfigurable for Adc<'_, ADCI, Blocking> {
536 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
537 for core in crate::system::Cpu::other() {
538 crate::interrupt::disable(core, InterruptSource);
539 }
540 unsafe { crate::interrupt::bind_interrupt(InterruptSource, handler.handler()) };
541 unwrap!(crate::interrupt::enable(
542 InterruptSource,
543 handler.priority()
544 ));
545 }
546}
547
548#[cfg(all(adc1, not(esp32h2)))]
549impl super::AdcCalEfuse for crate::peripherals::ADC1 {
550 fn init_code(atten: Attenuation) -> Option<u16> {
551 Efuse::rtc_calib_init_code(1, atten)
552 }
553
554 fn cal_mv(atten: Attenuation) -> u16 {
555 Efuse::rtc_calib_cal_mv(1, atten)
556 }
557
558 fn cal_code(atten: Attenuation) -> Option<u16> {
559 Efuse::rtc_calib_cal_code(1, atten)
560 }
561}
562
563#[cfg(adc2)]
564impl super::AdcCalEfuse for crate::peripherals::ADC2 {
565 fn init_code(atten: Attenuation) -> Option<u16> {
566 Efuse::rtc_calib_init_code(2, atten)
567 }
568
569 fn cal_mv(atten: Attenuation) -> u16 {
570 Efuse::rtc_calib_cal_mv(2, atten)
571 }
572
573 fn cal_code(atten: Attenuation) -> Option<u16> {
574 Efuse::rtc_calib_cal_code(2, atten)
575 }
576}
577
578#[cfg(esp32c2)]
579mod adc_implementation {
580 crate::analog::adc::impl_adc_interface! {
581 ADC1 [
582 (GpioPin<0>, 0),
583 (GpioPin<1>, 1),
584 (GpioPin<2>, 2),
585 (GpioPin<3>, 3),
586 (GpioPin<4>, 4),
587 ]
588 }
589}
590
591#[cfg(esp32c3)]
592mod adc_implementation {
593 crate::analog::adc::impl_adc_interface! {
594 ADC1 [
595 (GpioPin<0>, 0),
596 (GpioPin<1>, 1),
597 (GpioPin<2>, 2),
598 (GpioPin<3>, 3),
599 (GpioPin<4>, 4),
600 ]
601 }
602
603 crate::analog::adc::impl_adc_interface! {
604 ADC2 [
605 (GpioPin<5>, 0),
606 ]
607 }
608}
609
610#[cfg(esp32c6)]
611mod adc_implementation {
612 crate::analog::adc::impl_adc_interface! {
613 ADC1 [
614 (GpioPin<0>, 0),
615 (GpioPin<1>, 1),
616 (GpioPin<2>, 2),
617 (GpioPin<3>, 3),
618 (GpioPin<4>, 4),
619 (GpioPin<5>, 5),
620 (GpioPin<6>, 6),
621 ]
622 }
623}
624
625#[cfg(esp32h2)]
626mod adc_implementation {
627 crate::analog::adc::impl_adc_interface! {
628 ADC1 [
629 (GpioPin<1>, 0),
630 (GpioPin<2>, 1),
631 (GpioPin<3>, 2),
632 (GpioPin<4>, 3),
633 (GpioPin<5>, 4),
634 ]
635 }
636}
637
638impl<'d, ADCI> Adc<'d, ADCI, Async>
639where
640 ADCI: RegisterAccess + 'd,
641{
642 pub fn into_blocking(self) -> Adc<'d, ADCI, Blocking> {
644 if asynch::release_async_adc() {
645 for cpu in crate::system::Cpu::all() {
647 crate::interrupt::disable(cpu, InterruptSource);
648 }
649 }
650 Adc {
651 _adc: self._adc,
652 attenuations: self.attenuations,
653 active_channel: self.active_channel,
654 _guard: self._guard,
655 _phantom: PhantomData,
656 }
657 }
658
659 pub async fn read_oneshot<PIN, CS>(&mut self, pin: &mut super::AdcPin<PIN, ADCI, CS>) -> u16
665 where
666 ADCI: asynch::AsyncAccess,
667 PIN: super::AdcChannel,
668 CS: super::AdcCalScheme<ADCI>,
669 {
670 let channel = PIN::CHANNEL;
671 if self.attenuations[channel as usize].is_none() {
672 panic!("Channel {} is not configured reading!", channel);
673 }
674
675 ADCI::set_init_code(pin.cal_scheme.adc_cal());
677
678 let attenuation = self.attenuations[channel as usize].unwrap() as u8;
679 ADCI::config_onetime_sample(channel, attenuation);
680 ADCI::start_onetime_sample();
681
682 let adc_ready_future = AdcFuture::new(self);
684 adc_ready_future.await;
685 let converted_value = ADCI::read_data();
686
687 ADCI::reset();
698
699 pin.cal_scheme.adc_val(converted_value)
701 }
702}
703
704pub(crate) mod asynch {
706 use core::{
707 marker::PhantomData,
708 pin::Pin,
709 task::{Context, Poll},
710 };
711
712 #[cfg(all(adc1, adc2))]
714 use portable_atomic::{AtomicU32, Ordering};
715 use procmacros::handler;
716
717 use crate::{asynch::AtomicWaker, peripherals::APB_SARADC, Async};
718
719 #[cfg(all(adc1, adc2))]
720 static ASYNC_ADC_COUNT: AtomicU32 = AtomicU32::new(0);
721
722 pub(super) fn acquire_async_adc() {
723 #[cfg(all(adc1, adc2))]
724 ASYNC_ADC_COUNT.fetch_add(1, Ordering::Relaxed);
725 }
726
727 pub(super) fn release_async_adc() -> bool {
728 cfg_if::cfg_if! {
729 if #[cfg(all(adc1, adc2))] {
730 ASYNC_ADC_COUNT.fetch_sub(1, Ordering::Relaxed) == 1
731 } else {
732 true
733 }
734 }
735 }
736
737 #[handler]
738 pub(crate) fn adc_interrupt_handler() {
739 let saradc = APB_SARADC::regs();
740 let interrupt_status = saradc.int_st().read();
741
742 #[cfg(adc1)]
743 if interrupt_status.adc1_done().bit_is_set() {
744 handle_async(crate::peripherals::ADC1)
745 }
746
747 #[cfg(adc2)]
748 if interrupt_status.adc2_done().bit_is_set() {
749 handle_async(crate::peripherals::ADC2)
750 }
751 }
752
753 fn handle_async<ADCI: AsyncAccess>(_instance: ADCI) {
754 ADCI::waker().wake();
755 ADCI::disable_interrupt();
756 }
757
758 #[doc(hidden)]
759 pub trait AsyncAccess {
760 fn enable_interrupt();
762
763 fn disable_interrupt();
765
766 fn clear_interrupt();
768
769 fn waker() -> &'static AtomicWaker;
771 }
772
773 #[cfg(adc1)]
774 impl AsyncAccess for crate::peripherals::ADC1 {
775 fn enable_interrupt() {
776 APB_SARADC::regs()
777 .int_ena()
778 .modify(|_, w| w.adc1_done().set_bit());
779 }
780
781 fn disable_interrupt() {
782 APB_SARADC::regs()
783 .int_ena()
784 .modify(|_, w| w.adc1_done().clear_bit());
785 }
786
787 fn clear_interrupt() {
788 APB_SARADC::regs()
789 .int_clr()
790 .write(|w| w.adc1_done().clear_bit_by_one());
791 }
792
793 fn waker() -> &'static AtomicWaker {
794 static WAKER: AtomicWaker = AtomicWaker::new();
795
796 &WAKER
797 }
798 }
799
800 #[cfg(adc2)]
801 impl AsyncAccess for crate::peripherals::ADC2 {
802 fn enable_interrupt() {
803 APB_SARADC::regs()
804 .int_ena()
805 .modify(|_, w| w.adc2_done().set_bit());
806 }
807
808 fn disable_interrupt() {
809 APB_SARADC::regs()
810 .int_ena()
811 .modify(|_, w| w.adc2_done().clear_bit());
812 }
813
814 fn clear_interrupt() {
815 APB_SARADC::regs()
816 .int_clr()
817 .write(|w| w.adc2_done().clear_bit_by_one());
818 }
819
820 fn waker() -> &'static AtomicWaker {
821 static WAKER: AtomicWaker = AtomicWaker::new();
822
823 &WAKER
824 }
825 }
826
827 #[must_use = "futures do nothing unless you `.await` or poll them"]
828 pub(crate) struct AdcFuture<ADCI: AsyncAccess> {
829 phantom: PhantomData<ADCI>,
830 }
831
832 impl<ADCI: AsyncAccess> AdcFuture<ADCI> {
833 pub fn new(_self: &super::Adc<'_, ADCI, Async>) -> Self {
834 Self {
835 phantom: PhantomData,
836 }
837 }
838 }
839
840 impl<ADCI: AsyncAccess + super::RegisterAccess> core::future::Future for AdcFuture<ADCI> {
841 type Output = ();
842
843 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
844 if ADCI::is_done() {
845 ADCI::clear_interrupt();
846 Poll::Ready(())
847 } else {
848 ADCI::waker().register(cx.waker());
849 ADCI::enable_interrupt();
850 Poll::Pending
851 }
852 }
853 }
854
855 impl<ADCI: AsyncAccess> Drop for AdcFuture<ADCI> {
856 fn drop(&mut self) {
857 ADCI::disable_interrupt();
858 }
859 }
860}