1use core::marker::PhantomData;
4
5use esp_idf_sys::*;
6
7#[cfg(all(
8 not(esp_idf_version_major = "4"),
9 not(esp32c2),
10 esp_idf_comp_esp_adc_enabled
11))]
12#[allow(deprecated)]
13pub use continuous::{
14 config as cont_config, config::Config as AdcContConfig, AdcChannels, AdcChannelsArray,
15 AdcDriver as AdcContDriver, AdcMeasurement, Atten11dB, Atten12dB, Atten2p5dB, Atten6dB,
16 AttenNone, Attenuated, ChainedAdcChannels, EmptyAdcChannels,
17};
18
19#[cfg(any(
20 all(feature = "adc-oneshot-legacy", esp_idf_version_major = "5"),
21 esp_idf_version_major = "4"
22))]
23pub use oneshot_legacy::*;
24
25pub trait AdcUnit: 'static {
29 fn unit() -> adc_unit_t;
31}
32
33macro_rules! impl_adcu {
34 ($adcu:ident: $unit:expr) => {
35 pub struct $adcu;
36
37 impl AdcUnit for $adcu {
38 fn unit() -> adc_unit_t {
39 $unit
40 }
41 }
42 };
43}
44
45impl_adcu!(ADCU1: adc_unit_t_ADC_UNIT_1);
46#[cfg(any(esp32, esp32s2, esp32s3, esp32c3, esp32p4))]
47impl_adcu!(ADCU2: adc_unit_t_ADC_UNIT_2);
48
49pub trait AdcChannel: 'static {
53 type AdcUnit: AdcUnit;
55
56 fn unit() -> adc_unit_t {
58 Self::AdcUnit::unit()
59 }
60
61 fn channel() -> adc_channel_t;
63}
64
65macro_rules! impl_adcch {
66 ($adcch:ident: $unit:expr) => {
67 pub struct $adcch<U: AdcUnit>(PhantomData<U>);
68
69 impl<U: AdcUnit> AdcChannel for $adcch<U> {
70 type AdcUnit = U;
71
72 fn channel() -> adc_channel_t {
73 $unit
74 }
75 }
76 };
77}
78
79impl_adcch!(ADCCH0: adc_channel_t_ADC_CHANNEL_0);
80impl_adcch!(ADCCH1: adc_channel_t_ADC_CHANNEL_1);
81impl_adcch!(ADCCH2: adc_channel_t_ADC_CHANNEL_2);
82impl_adcch!(ADCCH3: adc_channel_t_ADC_CHANNEL_3);
83impl_adcch!(ADCCH4: adc_channel_t_ADC_CHANNEL_4);
84impl_adcch!(ADCCH5: adc_channel_t_ADC_CHANNEL_5);
85impl_adcch!(ADCCH6: adc_channel_t_ADC_CHANNEL_6);
86impl_adcch!(ADCCH7: adc_channel_t_ADC_CHANNEL_7);
87impl_adcch!(ADCCH8: adc_channel_t_ADC_CHANNEL_8);
88impl_adcch!(ADCCH9: adc_channel_t_ADC_CHANNEL_9);
89
90pub trait Adc: Send {
92 type AdcUnit: AdcUnit;
94
95 fn unit() -> adc_unit_t {
97 Self::AdcUnit::unit()
98 }
99}
100
101pub mod attenuation {
103 pub use esp_idf_sys::{
104 adc_atten_t, adc_atten_t_ADC_ATTEN_DB_0, adc_atten_t_ADC_ATTEN_DB_2_5,
105 adc_atten_t_ADC_ATTEN_DB_6,
106 };
107
108 #[cfg(esp_idf_version_at_least_6_0_0)]
109 pub use esp_idf_sys::adc_atten_t_ADC_ATTEN_DB_12;
110 #[cfg(esp_idf_version_at_least_6_0_0)]
111 #[allow(non_upper_case_globals)]
112 pub const adc_atten_t_ADC_ATTEN_DB_11: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_12;
113
114 #[cfg(not(esp_idf_version_at_least_6_0_0))]
115 pub use esp_idf_sys::adc_atten_t_ADC_ATTEN_DB_11;
116 #[cfg(not(esp_idf_version_at_least_6_0_0))]
117 #[allow(non_upper_case_globals)]
118 pub const adc_atten_t_ADC_ATTEN_DB_12: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_11;
119
120 pub const NONE: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_0;
121 pub const DB_2_5: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_2_5;
122 pub const DB_6: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_6;
123 #[deprecated(since = "0.45.3", note = "Use `DB_12` instead")]
124 pub const DB_11: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_11;
125 pub const DB_12: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_12;
126}
127
128#[derive(Debug, PartialEq, Eq, Clone, Copy)]
130pub enum Resolution {
131 #[cfg(esp32)]
132 Resolution9Bit,
133 #[cfg(esp32)]
134 Resolution10Bit,
135 #[cfg(esp32)]
136 Resolution11Bit,
137 #[cfg(any(
138 esp32, esp32c3, esp32s3, esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4
139 ))]
140 Resolution12Bit,
141 #[cfg(esp32s2)]
142 Resolution13Bit,
143}
144
145impl Resolution {
146 #[cfg(not(esp32s2))]
147 pub const fn new() -> Self {
148 Self::Resolution12Bit
149 }
150
151 #[cfg(esp32s2)]
152 pub const fn new() -> Self {
153 Self::Resolution13Bit
154 }
155}
156
157impl Default for Resolution {
158 fn default() -> Self {
159 Self::new()
160 }
161}
162
163#[cfg(esp_idf_version_at_least_6_0_0)]
164impl From<Resolution> for adc_bitwidth_t {
165 fn from(resolution: Resolution) -> Self {
166 match resolution {
167 #[cfg(esp32)]
168 Resolution::Resolution9Bit => adc_bitwidth_t_ADC_BITWIDTH_9,
169 #[cfg(esp32)]
170 Resolution::Resolution10Bit => adc_bitwidth_t_ADC_BITWIDTH_10,
171 #[cfg(esp32)]
172 Resolution::Resolution11Bit => adc_bitwidth_t_ADC_BITWIDTH_11,
173 #[cfg(any(
174 esp32, esp32s3, esp32c3, esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61,
175 esp32p4
176 ))]
177 Resolution::Resolution12Bit => adc_bitwidth_t_ADC_BITWIDTH_12,
178 #[cfg(esp32s2)]
179 Resolution::Resolution13Bit => adc_bitwidth_t_ADC_BITWIDTH_13,
180 }
181 }
182}
183
184#[cfg(not(esp_idf_version_at_least_6_0_0))]
185impl From<Resolution> for adc_bits_width_t {
186 fn from(resolution: Resolution) -> Self {
187 match resolution {
188 #[cfg(esp32)]
189 Resolution::Resolution9Bit => adc_bits_width_t_ADC_WIDTH_BIT_9,
190 #[cfg(esp32)]
191 Resolution::Resolution10Bit => adc_bits_width_t_ADC_WIDTH_BIT_10,
192 #[cfg(esp32)]
193 Resolution::Resolution11Bit => adc_bits_width_t_ADC_WIDTH_BIT_11,
194 #[cfg(any(
195 esp32, esp32s3, esp32c3, esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61,
196 esp32p4
197 ))]
198 Resolution::Resolution12Bit => adc_bits_width_t_ADC_WIDTH_BIT_12,
199 #[cfg(esp32s2)]
200 Resolution::Resolution13Bit => adc_bits_width_t_ADC_WIDTH_BIT_13,
201 }
202 }
203}
204
205#[cfg(any(
206 all(feature = "adc-oneshot-legacy", esp_idf_version_major = "5"),
207 esp_idf_version_major = "4"
208))]
209mod oneshot_legacy {
210 use core::marker::PhantomData;
211
212 use esp_idf_sys::*;
213
214 use crate::{
215 adc::{AdcChannel, AdcUnit},
216 gpio::ADCPin,
217 };
218
219 use super::{to_nb_err, Adc, DirectConverter};
220
221 pub type AdcConfig = config::Config;
222
223 pub mod config {
225 pub use crate::adc::Resolution;
226
227 #[derive(Debug, Copy, Clone, Default)]
228 pub struct Config {
229 pub resolution: Resolution,
230 #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))]
231 pub calibration: bool,
232 }
233
234 impl Config {
235 pub fn new() -> Self {
236 Default::default()
237 }
238
239 #[must_use]
240 pub fn resolution(mut self, resolution: Resolution) -> Self {
241 self.resolution = resolution;
242 self
243 }
244
245 #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))]
246 #[must_use]
247 pub fn calibration(mut self, calibration: bool) -> Self {
248 self.calibration = calibration;
249 self
250 }
251 }
252 }
253
254 pub struct AdcChannelDriver<'d, const A: adc_atten_t, C: AdcChannel> {
255 _channel: PhantomData<C>,
256 _t: PhantomData<&'d mut ()>,
257 }
258
259 impl<'d, const A: adc_atten_t, C: AdcChannel> AdcChannelDriver<'d, A, C>
260 where
261 C: AdcChannel,
262 {
263 pub fn new(pin: impl ADCPin<AdcChannel = C> + 'd) -> Result<Self, EspError> {
264 unsafe {
265 crate::gpio::rtc_reset_pin(pin.pin() as _)?;
266 }
267
268 if C::unit() == adc_unit_t_ADC_UNIT_1 {
269 esp!(unsafe { adc1_config_channel_atten(C::channel(), A) })?;
270 } else {
271 #[cfg(not(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4)))]
272 esp!(unsafe { adc2_config_channel_atten(C::channel(), A) })?;
273
274 #[cfg(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4))]
275 unreachable!();
276 }
277
278 Ok(Self {
279 _channel: PhantomData,
280 _t: PhantomData,
281 })
282 }
283 }
284
285 impl<const A: adc_atten_t, C: AdcChannel> embedded_hal_0_2::adc::Channel<C::AdcUnit>
286 for AdcChannelDriver<'_, A, C>
287 {
288 type ID = (adc_channel_t, adc_atten_t);
289
290 fn channel() -> Self::ID {
291 (C::channel(), A)
292 }
293 }
294
295 pub struct AdcDriver<'d, ADCU: AdcUnit> {
296 #[allow(dead_code)]
297 resolution: config::Resolution,
298 #[cfg(all(
299 any(esp32, esp32s2, esp32s3, esp32c3),
300 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
301 ))]
302 cal_characteristics: Option<
303 [Option<esp_adc_cal_characteristics_t>; adc_atten_t_ADC_ATTEN_DB_11 as usize + 1],
304 >,
305 _unit: PhantomData<ADCU>,
306 _t: PhantomData<&'d mut ()>,
307 }
308
309 unsafe impl<ADCU: AdcUnit> Send for AdcDriver<'_, ADCU> {}
310
311 impl<'d, ADCU: AdcUnit> AdcDriver<'d, ADCU> {
312 #[cfg(all(
313 esp32,
314 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
315 ))]
316 const CALIBRATION_SCHEME: esp_adc_cal_value_t =
317 esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_VREF;
318
319 #[cfg(all(
320 any(esp32c3, esp32s2),
321 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
322 ))]
323 const CALIBRATION_SCHEME: esp_adc_cal_value_t =
324 esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP;
325
326 #[cfg(all(
327 esp32s3,
328 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
329 ))]
330 const CALIBRATION_SCHEME: esp_adc_cal_value_t =
331 esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP_FIT;
332
333 pub fn new<ADC: Adc<AdcUnit = ADCU> + 'd>(
334 _adc: ADC,
335 config: &config::Config,
336 ) -> Result<Self, EspError> {
337 #[cfg(all(
338 any(esp32, esp32s2, esp32s3, esp32c3),
339 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
340 ))]
341 if config.calibration {
342 esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?;
343 }
344
345 if ADC::unit() == adc_unit_t_ADC_UNIT_1 {
346 esp!(unsafe { adc1_config_width(config.resolution.into()) })?;
347 }
348
349 Ok(Self {
350 resolution: config.resolution,
351 #[cfg(all(
352 any(esp32, esp32s2, esp32s3, esp32c3),
353 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
354 ))]
355 cal_characteristics: if config.calibration {
356 Some(Default::default())
357 } else {
358 None
359 },
360 _unit: PhantomData,
361 _t: PhantomData,
362 })
363 }
364
365 #[inline(always)]
366 pub fn read<const A: adc_atten_t, C: AdcChannel<AdcUnit = ADCU>>(
367 &mut self,
368 _pin: &mut AdcChannelDriver<'_, A, C>,
369 ) -> Result<u16, EspError> {
370 self.read_internal(C::unit(), C::channel(), A)
371 }
372
373 #[inline(always)]
374 pub fn read_raw<const A: adc_atten_t, C: AdcChannel<AdcUnit = ADCU>>(
375 &mut self,
376 _pin: &mut AdcChannelDriver<'_, A, C>,
377 ) -> Result<u16, EspError> {
378 self.read_internal_raw(C::unit(), C::channel())
379 }
380
381 #[inline(always)]
382 fn read_internal(
383 &mut self,
384 unit: adc_unit_t,
385 channel: adc_channel_t,
386 atten: adc_atten_t,
387 ) -> Result<u16, EspError> {
388 let measurement = self.read_internal_raw(unit, channel)?;
389 self.raw_to_voltage(measurement, atten)
390 }
391
392 #[inline(always)]
393 fn read_internal_raw(
394 &mut self,
395 unit: adc_unit_t,
396 channel: adc_channel_t,
397 ) -> Result<u16, EspError> {
398 if unit == adc_unit_t_ADC_UNIT_1 {
399 Ok(unsafe { adc1_get_raw(channel) } as _)
400 } else {
401 #[cfg(not(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4)))]
402 {
403 let mut measurement = 0;
404 esp!(unsafe {
405 adc2_get_raw(channel, self.resolution.into(), &mut measurement)
406 })?;
407
408 Ok(measurement as _)
409 }
410
411 #[cfg(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4))]
412 unreachable!();
413 }
414 }
415
416 #[inline(always)]
417 fn raw_to_voltage(
418 &mut self,
419 measurement: u16,
420 attenuation: adc_atten_t,
421 ) -> Result<u16, EspError> {
422 #[cfg(all(
423 any(esp32, esp32s2, esp32s3, esp32c3),
424 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
425 ))]
426 let mv = if let Some(cal) = self.get_cal_characteristics(attenuation)? {
427 unsafe { esp_adc_cal_raw_to_voltage(measurement as u32, &cal) as u16 }
428 } else {
429 DirectConverter(attenuation).raw_to_mv(measurement)
430 };
431
432 #[cfg(not(all(
433 any(esp32, esp32s2, esp32s3, esp32c3),
434 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
435 )))]
436 let mv = DirectConverter(attenuation).raw_to_mv(measurement);
437
438 Ok(mv)
439 }
440
441 #[cfg(all(
442 any(esp32, esp32s2, esp32s3, esp32c3),
443 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled)
444 ))]
445 fn get_cal_characteristics(
446 &mut self,
447 attenuation: adc_atten_t,
448 ) -> Result<Option<esp_adc_cal_characteristics_t>, EspError> {
449 if let Some(characteristics) = &mut self.cal_characteristics {
450 if let Some(cal) = characteristics[attenuation as usize] {
451 Ok(Some(cal))
452 } else {
453 esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?;
454
455 let mut cal: esp_adc_cal_characteristics_t = Default::default();
456 unsafe {
457 esp_adc_cal_characterize(
458 ADCU::unit(),
459 attenuation,
460 self.resolution.into(),
461 0,
462 &mut cal,
463 )
464 };
465
466 characteristics[attenuation as usize] = Some(cal);
467
468 Ok(Some(cal))
469 }
470 } else {
471 Ok(None)
472 }
473 }
474 }
475
476 impl<'c, const A: adc_atten_t, C>
477 embedded_hal_0_2::adc::OneShot<C::AdcUnit, u16, AdcChannelDriver<'c, A, C>>
478 for AdcDriver<'_, C::AdcUnit>
479 where
480 C: AdcChannel,
481 {
482 type Error = EspError;
483
484 fn read(&mut self, _pin: &mut AdcChannelDriver<'c, A, C>) -> nb::Result<u16, Self::Error> {
485 self.read_internal(C::unit(), C::channel(), A)
486 .map_err(to_nb_err)
487 }
488 }
489}
490
491fn to_nb_err(err: EspError) -> nb::Error<EspError> {
492 if err.code() == ESP_ERR_INVALID_STATE {
493 nb::Error::WouldBlock
494 } else {
495 nb::Error::Other(err)
496 }
497}
498
499macro_rules! impl_adc {
500 ($adc:ident: $unit:ident) => {
501 crate::impl_peripheral!($adc);
502
503 impl Adc for $adc<'_> {
504 type AdcUnit = $unit;
505 }
506 };
507}
508
509impl_adc!(ADC1: ADCU1);
510#[cfg(not(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61)))] impl_adc!(ADC2: ADCU2);
512
513struct DirectConverter(adc_atten_t);
515
516impl DirectConverter {
517 #[cfg(not(esp32s2))]
518 const MAX_READING: u32 = 4095;
519
520 #[cfg(esp32s2)]
521 const MAX_READING: u32 = 8191;
522
523 fn raw_to_mv(&self, raw: u16) -> u16 {
524 (raw as u32 * self.get_max_mv() as u32 / Self::MAX_READING) as u16
525 }
526
527 #[inline(always)]
528 #[allow(non_upper_case_globals)]
529 fn get_max_mv(&self) -> u16 {
530 let attenuation = self.0;
531
532 #[cfg(esp32)]
533 let mv = match attenuation {
534 attenuation::NONE => 950,
535 attenuation::DB_2_5 => 1250,
536 attenuation::DB_6 => 1750,
537 attenuation::DB_12 => 2450,
538 other => panic!("Unknown attenuation: {other}"),
539 };
540
541 #[cfg(any(
542 esp32c3, esp32s2, esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4
543 ))]
544 let mv = match attenuation {
545 attenuation::NONE => 750,
546 attenuation::DB_2_5 => 1050,
547 attenuation::DB_6 => 1300,
548 attenuation::DB_12 => 2500,
549 other => panic!("Unknown attenuation: {other}"),
550 };
551
552 #[cfg(esp32s3)]
553 let mv = match attenuation {
554 attenuation::NONE => 950,
555 attenuation::DB_2_5 => 1250,
556 attenuation::DB_6 => 1750,
557 attenuation::DB_12 => 3100,
558 other => panic!("Unknown attenuation: {other}"),
559 };
560
561 mv
562 }
563}
564
565#[cfg(all(
596 not(all(feature = "adc-oneshot-legacy", esp_idf_version_major = "5")),
597 not(esp_idf_version_major = "4"),
598 esp_idf_comp_esp_adc_enabled
599))]
600pub mod oneshot {
601 use core::borrow::Borrow;
602 use core::marker::PhantomData;
603
604 use esp_idf_sys::*;
605
606 use crate::adc::to_nb_err;
607 use crate::adc::AdcChannel;
608 use crate::gpio::ADCPin;
609
610 use super::attenuation::adc_atten_t;
611 use super::Adc;
612 use super::AdcUnit;
613 use super::DirectConverter;
614
615 pub mod config {
616 use super::adc_atten_t;
617
618 pub use crate::adc::Resolution;
619
620 #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
621 pub enum Calibration {
622 #[default]
623 None,
624 #[cfg(all(
625 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
626 any(
627 esp32c3,
628 all(
629 esp32c6,
630 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0")),
631 not(esp_idf_version_full = "5.1.0")
632 ),
633 esp32s3,
634 )
635 ))]
636 Curve,
637 #[cfg(all(
638 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
639 any(esp32, esp32c2, esp32s2)
640 ))]
641 Line,
642 }
643
644 #[derive(Debug, Copy, Clone, Default)]
645 pub struct AdcChannelConfig {
646 pub attenuation: adc_atten_t,
647 pub resolution: Resolution,
648 pub calibration: Calibration,
649 }
650
651 impl AdcChannelConfig {
652 pub const fn new() -> Self {
653 Self {
654 attenuation: crate::adc::attenuation::NONE,
655 resolution: Resolution::new(),
656 calibration: Calibration::None,
657 }
658 }
659 }
660 }
661
662 enum Converter {
664 NoCalibration(adc_atten_t),
665 #[cfg(all(
666 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
667 any(
668 esp32c3,
669 all(
670 esp32c6,
671 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0")),
672 not(esp_idf_version_full = "5.1.0")
673 ),
674 esp32s3,
675 )
676 ))]
677 CurveFittingCalibration(adc_cali_handle_t),
678 #[cfg(all(
679 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
680 any(esp32, esp32c2, esp32s2)
681 ))]
682 LineFittingCalibration(adc_cali_handle_t),
683 }
684
685 impl Converter {
686 #[allow(unused_variables)]
687 fn create(
688 unit: adc_unit_t,
689 chan: adc_channel_t,
690 atten: adc_atten_t,
691 #[cfg(esp_idf_version_at_least_6_0_0)] bitwidth: adc_bitwidth_t,
692 #[cfg(not(esp_idf_version_at_least_6_0_0))] bitwidth: adc_bits_width_t,
693 calibration: config::Calibration,
694 ) -> Result<Self, EspError> {
695 match calibration {
696 config::Calibration::None => Ok(Self::NoCalibration(atten)),
697 #[cfg(all(
698 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
699 any(
700 esp32c3,
701 all(
702 esp32c6,
703 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0")),
704 not(esp_idf_version_full = "5.1.0")
705 ),
706 esp32s3,
707 )
708 ))]
709 config::Calibration::Curve => {
710 let cal_config = adc_cali_curve_fitting_config_t {
716 unit_id: unit,
717 #[cfg(esp_idf_version_at_least_5_1_1)]
718 chan,
719 atten,
720 bitwidth,
721 };
722 let mut cal_handle: adc_cali_handle_t = core::ptr::null_mut();
723 esp!(unsafe {
724 esp_idf_sys::adc_cali_create_scheme_curve_fitting(
725 &cal_config,
726 &mut cal_handle,
727 )
728 })?;
729
730 Ok(Self::CurveFittingCalibration(cal_handle))
731 }
732 #[cfg(all(
733 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
734 any(esp32, esp32c2, esp32s2)
735 ))]
736 config::Calibration::Line => {
737 #[allow(clippy::needless_update)]
741 let cal_config = adc_cali_line_fitting_config_t {
742 unit_id: unit,
743 atten,
744 bitwidth,
745 ..Default::default()
746 };
747 let mut cal_handle: adc_cali_handle_t = core::ptr::null_mut();
748 esp!(unsafe {
749 esp_idf_sys::adc_cali_create_scheme_line_fitting(
750 &cal_config,
751 &mut cal_handle,
752 )
753 })?;
754
755 Ok(Self::LineFittingCalibration(cal_handle))
756 }
757 }
758 }
759
760 fn raw_to_mv(&self, raw: u16) -> Result<u16, EspError> {
761 match self {
762 Self::NoCalibration(atten) => Ok(DirectConverter(*atten).raw_to_mv(raw)),
763 #[cfg(all(
764 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
765 any(
766 esp32c3,
767 all(
768 esp32c6,
769 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0")),
770 not(esp_idf_version_full = "5.1.0")
771 ),
772 esp32s3,
773 )
774 ))]
775 Self::CurveFittingCalibration(handle) => {
776 let mut mv = 0i32;
777 esp!(unsafe { adc_cali_raw_to_voltage(*handle, raw as i32, &mut mv) })?;
778
779 Ok(mv as u16)
780 }
781 #[cfg(all(
782 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
783 any(esp32, esp32c2, esp32s2)
784 ))]
785 Self::LineFittingCalibration(handle) => {
786 let mut mv = 0i32;
787 esp!(unsafe { adc_cali_raw_to_voltage(*handle, raw as i32, &mut mv) })?;
788
789 Ok(mv as u16)
790 }
791 }
792 }
793 }
794
795 impl Drop for Converter {
796 fn drop(&mut self) {
797 match self {
798 Self::NoCalibration(_) => (),
799 #[cfg(all(
800 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
801 any(
802 esp32c3,
803 all(
804 esp32c6,
805 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0")),
806 not(esp_idf_version_full = "5.1.0")
807 ),
808 esp32s3,
809 )
810 ))]
811 Self::CurveFittingCalibration(handle) => {
812 esp!(unsafe { esp_idf_sys::adc_cali_delete_scheme_curve_fitting(*handle) })
813 .unwrap()
814 }
815 #[cfg(all(
816 any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled),
817 any(esp32, esp32c2, esp32s2)
818 ))]
819 Self::LineFittingCalibration(handle) => {
820 esp!(unsafe { esp_idf_sys::adc_cali_delete_scheme_line_fitting(*handle) })
821 .unwrap()
822 }
823 }
824 }
825 }
826
827 pub struct AdcChannelDriver<'d, C, M>
828 where
829 C: AdcChannel,
830 M: Borrow<AdcDriver<'d, C::AdcUnit>>,
831 {
832 adc: M,
833 _channel: PhantomData<C>,
834 converter: Converter,
835 _t: PhantomData<&'d mut ()>,
836 }
837
838 impl<'d, C, M> AdcChannelDriver<'d, C, M>
839 where
840 C: AdcChannel,
841 M: Borrow<AdcDriver<'d, C::AdcUnit>>,
842 {
843 pub fn new(
844 adc: M,
845 pin: impl ADCPin<AdcChannel = C> + 'd,
846 config: &config::AdcChannelConfig,
847 ) -> Result<Self, EspError> {
848 unsafe {
849 crate::gpio::rtc_reset_pin(pin.pin() as _)?;
850 }
851
852 let chan_config = adc_oneshot_chan_cfg_t {
853 atten: config.attenuation,
854 bitwidth: config.resolution.into(),
855 };
856
857 let converter = Converter::create(
858 C::unit(),
859 C::channel(),
860 config.attenuation,
861 config.resolution.into(),
862 config.calibration,
863 )?;
864
865 unsafe {
866 esp!(adc_oneshot_config_channel(
867 adc.borrow().handle,
868 C::channel(),
869 &chan_config
870 ))?
871 };
872
873 Ok(Self {
874 adc,
875 _channel: PhantomData,
876 converter,
877 _t: PhantomData,
878 })
879 }
880
881 #[inline(always)]
882 pub fn read(&mut self) -> Result<u16, EspError> {
883 let raw = self.read_raw()?;
884 self.raw_to_mv(raw)
885 }
886
887 #[inline(always)]
888 pub fn read_raw(&mut self) -> Result<u16, EspError> {
889 let channel = C::channel();
890 self.adc.borrow().read_raw_internal(channel)
891 }
892
893 #[inline(always)]
894 pub fn raw_to_mv(&self, raw: u16) -> Result<u16, EspError> {
895 self.converter.raw_to_mv(raw)
896 }
897 }
898
899 impl<'d, C, M> embedded_hal_0_2::adc::Channel<C::AdcUnit> for AdcChannelDriver<'d, C, M>
900 where
901 C: AdcChannel,
902 M: Borrow<AdcDriver<'d, C::AdcUnit>>,
903 {
904 type ID = adc_channel_t;
905
906 fn channel() -> Self::ID {
907 C::channel()
908 }
909 }
910
911 unsafe impl<'d, C, M> Send for AdcChannelDriver<'d, C, M>
912 where
913 C: AdcChannel,
914 M: Borrow<AdcDriver<'d, C::AdcUnit>>,
915 {
916 }
917
918 pub struct AdcDriver<'d, U> {
919 handle: adc_oneshot_unit_handle_t,
920 _unit: PhantomData<U>,
921 _t: PhantomData<&'d mut ()>,
922 }
923
924 impl<'d, U> AdcDriver<'d, U>
925 where
926 U: AdcUnit + 'd,
927 {
928 pub fn new<ADC: Adc<AdcUnit = U> + 'd>(_adc: ADC) -> Result<Self, EspError> {
929 let config = adc_oneshot_unit_init_cfg_t {
930 unit_id: ADC::unit(),
931 ..Default::default()
932 };
933 let mut handle: adc_oneshot_unit_handle_t = core::ptr::null_mut();
934 unsafe { esp!(adc_oneshot_new_unit(&config, &mut handle))? };
935 Ok(Self {
936 handle,
937 _unit: PhantomData,
938 _t: PhantomData,
939 })
940 }
941
942 #[inline(always)]
943 pub fn read<C, M>(&self, channel: &mut AdcChannelDriver<'d, C, M>) -> Result<u16, EspError>
944 where
945 C: AdcChannel<AdcUnit = U>,
946 M: Borrow<AdcDriver<'d, U>>,
947 {
948 let raw = self.read_raw(channel)?;
949 self.raw_to_mv(channel, raw)
950 }
951
952 #[inline(always)]
953 pub fn read_raw<C, M>(
954 &self,
955 _channel: &mut AdcChannelDriver<'d, C, M>,
956 ) -> Result<u16, EspError>
957 where
958 C: AdcChannel<AdcUnit = U>,
959 M: Borrow<AdcDriver<'d, U>>,
960 {
961 self.read_raw_internal(C::channel())
962 }
963
964 #[inline(always)]
965 fn read_raw_internal(&self, channel: adc_channel_t) -> Result<u16, EspError> {
966 let mut measurement = 0;
967 unsafe { esp!(adc_oneshot_read(self.handle, channel, &mut measurement)) }?;
968 Ok(measurement as u16)
969 }
970
971 #[inline(always)]
972 pub fn raw_to_mv<C, M>(
973 &self,
974 channel: &AdcChannelDriver<'d, C, M>,
975 raw: u16,
976 ) -> Result<u16, EspError>
977 where
978 C: AdcChannel<AdcUnit = U>,
979 M: Borrow<AdcDriver<'d, U>>,
980 {
981 channel.converter.raw_to_mv(raw)
982 }
983 }
984
985 impl<U> Drop for AdcDriver<'_, U> {
986 fn drop(&mut self) {
987 unsafe { esp!(adc_oneshot_del_unit(self.handle)) }.unwrap();
988 }
989 }
990
991 impl<'d, C, M> embedded_hal_0_2::adc::OneShot<C::AdcUnit, u16, AdcChannelDriver<'d, C, M>>
992 for AdcDriver<'d, C::AdcUnit>
993 where
994 C: AdcChannel,
995 M: Borrow<AdcDriver<'d, C::AdcUnit>>,
996 {
997 type Error = EspError;
998
999 fn read(&mut self, pin: &mut AdcChannelDriver<'d, C, M>) -> nb::Result<u16, Self::Error> {
1000 AdcDriver::read(self, pin).map_err(to_nb_err)
1001 }
1002 }
1003
1004 unsafe impl<U: AdcUnit> Send for AdcDriver<'_, U> {}
1005 unsafe impl<U: AdcUnit> Sync for AdcDriver<'_, U> {}
1006}
1007
1008#[cfg(all(
1044 not(esp_idf_version_major = "4"),
1045 not(esp32c2),
1046 esp_idf_comp_esp_adc_enabled
1047))]
1048pub mod continuous {
1049 use core::ffi::c_void;
1050 use core::fmt::{self, Debug, Display};
1051 use core::marker::PhantomData;
1052
1053 use esp_idf_sys::*;
1054
1055 use crate::adc::AdcChannel;
1056 use crate::delay::{self, TickType};
1057 use crate::gpio::ADCPin;
1058 use crate::interrupt::asynch::HalIsrNotification;
1059 use crate::io::EspIOError;
1060
1061 use super::{attenuation, Adc, AdcUnit};
1062
1063 pub struct Attenuated<const A: adc_atten_t, T>(T);
1066
1067 impl<T> Attenuated<{ attenuation::NONE }, T> {
1068 pub const fn none(t: T) -> Self {
1069 Self(t)
1070 }
1071 }
1072
1073 impl<T> Attenuated<{ attenuation::DB_2_5 }, T> {
1074 pub const fn db2_5(t: T) -> Self {
1075 Self(t)
1076 }
1077 }
1078
1079 impl<T> Attenuated<{ attenuation::DB_6 }, T> {
1080 pub const fn db6(t: T) -> Self {
1081 Self(t)
1082 }
1083 }
1084
1085 #[allow(deprecated)]
1086 impl<T> Attenuated<{ attenuation::DB_11 }, T> {
1087 #[cfg_attr(
1088 not(esp_idf_version_major = "4"),
1089 deprecated(since = "0.45.3", note = "Use `Attenuated::db12` instead")
1090 )]
1091 pub const fn db11(t: T) -> Self {
1092 Self(t)
1093 }
1094 }
1095
1096 #[cfg(not(esp_idf_version_major = "4"))]
1097 impl<T> Attenuated<{ attenuation::DB_12 }, T> {
1098 pub const fn db12(t: T) -> Self {
1099 Self(t)
1100 }
1101 }
1102
1103 impl<const A: adc_atten_t, T> Attenuated<A, T> {
1104 pub fn atten(channel: (adc_channel_t, adc_atten_t)) -> (adc_channel_t, adc_atten_t) {
1105 (channel.0, A)
1106 }
1107 }
1108
1109 pub type AttenNone<T> = Attenuated<{ attenuation::NONE }, T>;
1110 pub type Atten2p5dB<T> = Attenuated<{ attenuation::DB_2_5 }, T>;
1111 pub type Atten6dB<T> = Attenuated<{ attenuation::DB_6 }, T>;
1112 #[deprecated(since = "0.45.3", note = "Use `Atten12dB` instead")]
1113 #[allow(deprecated)]
1114 pub type Atten11dB<T> = Attenuated<{ attenuation::DB_11 }, T>;
1115 pub type Atten12dB<T> = Attenuated<{ attenuation::DB_12 }, T>;
1116
1117 pub trait AdcChannels {
1118 type AdcUnit: AdcUnit;
1119
1120 type Iterator<'a>: Iterator<Item = (adc_channel_t, adc_atten_t)>
1121 where
1122 Self: 'a;
1123
1124 fn iter(&self) -> Self::Iterator<'_>;
1125 }
1126
1127 impl<P> AdcChannels for P
1128 where
1129 P: ADCPin,
1130 {
1131 type AdcUnit = <P::AdcChannel as AdcChannel>::AdcUnit;
1132
1133 type Iterator<'a>
1134 = core::iter::Once<(adc_channel_t, adc_atten_t)>
1135 where
1136 Self: 'a;
1137
1138 fn iter(&self) -> Self::Iterator<'_> {
1139 core::iter::once((P::AdcChannel::channel(), attenuation::NONE))
1140 }
1141 }
1142
1143 impl<const A: adc_atten_t, C> AdcChannels for Attenuated<A, C>
1144 where
1145 C: AdcChannels,
1146 {
1147 type AdcUnit = C::AdcUnit;
1148
1149 type Iterator<'a>
1150 = core::iter::Map<
1151 C::Iterator<'a>,
1152 fn((adc_channel_t, adc_atten_t)) -> (adc_channel_t, adc_atten_t),
1153 >
1154 where
1155 Self: 'a;
1156
1157 fn iter(&self) -> Self::Iterator<'_> {
1158 self.0.iter().map(Attenuated::<A, C>::atten)
1159 }
1160 }
1161
1162 pub struct AdcChannelsArray<C, const N: usize>(pub [C; N]);
1163
1164 impl<C, const N: usize> AdcChannels for AdcChannelsArray<C, N>
1165 where
1166 C: AdcChannels,
1167 {
1168 type AdcUnit = C::AdcUnit;
1169
1170 type Iterator<'a>
1171 = core::iter::FlatMap<
1172 core::slice::Iter<'a, C>,
1173 <C as AdcChannels>::Iterator<'a>,
1174 fn(&'a C) -> C::Iterator<'a>,
1175 >
1176 where
1177 Self: 'a;
1178
1179 fn iter(&self) -> Self::Iterator<'_> {
1180 self.0.iter().flat_map(AdcChannels::iter)
1181 }
1182 }
1183
1184 pub struct EmptyAdcChannels<A>(PhantomData<A>);
1185
1186 impl<A> EmptyAdcChannels<A> {
1187 pub fn chain<O>(other: O) -> ChainedAdcChannels<Self, O>
1188 where
1189 A: Adc,
1190 O: AdcChannels<AdcUnit = A>,
1191 {
1192 ChainedAdcChannels {
1193 first: Self(PhantomData),
1194 second: other,
1195 }
1196 }
1197 }
1198
1199 impl<A> AdcChannels for EmptyAdcChannels<A>
1200 where
1201 A: AdcUnit,
1202 {
1203 type AdcUnit = A;
1204
1205 type Iterator<'a>
1206 = core::iter::Empty<(adc_channel_t, adc_atten_t)>
1207 where
1208 Self: 'a;
1209
1210 fn iter(&self) -> Self::Iterator<'_> {
1211 core::iter::empty()
1212 }
1213 }
1214
1215 pub struct ChainedAdcChannels<F, S> {
1216 first: F,
1217 second: S,
1218 }
1219
1220 impl<F, S> ChainedAdcChannels<F, S> {
1221 pub fn chain<O>(self, other: O) -> ChainedAdcChannels<Self, O>
1222 where
1223 F: AdcChannels,
1224 S: AdcChannels<AdcUnit = F::AdcUnit>,
1225 O: AdcChannels<AdcUnit = F::AdcUnit>,
1226 {
1227 ChainedAdcChannels {
1228 first: self,
1229 second: other,
1230 }
1231 }
1232 }
1233
1234 impl<F, S> AdcChannels for ChainedAdcChannels<F, S>
1235 where
1236 F: AdcChannels,
1237 S: AdcChannels<AdcUnit = F::AdcUnit>,
1238 {
1239 type AdcUnit = F::AdcUnit;
1240
1241 type Iterator<'a>
1242 = core::iter::Chain<F::Iterator<'a>, S::Iterator<'a>>
1243 where
1244 Self: 'a;
1245
1246 fn iter(&self) -> Self::Iterator<'_> {
1247 self.first.iter().chain(self.second.iter())
1248 }
1249 }
1250
1251 #[derive(Copy, Clone)]
1252 #[repr(transparent)]
1253 pub struct AdcMeasurement(adc_digi_output_data_t);
1254
1255 impl Default for AdcMeasurement {
1256 fn default() -> Self {
1257 Self::new()
1258 }
1259 }
1260
1261 impl AdcMeasurement {
1262 pub const INIT: Self = AdcMeasurement(unsafe {
1263 core::mem::transmute::<
1264 [u8; core::mem::size_of::<adc_digi_output_data_t>()],
1265 adc_digi_output_data_t,
1266 >([0u8; core::mem::size_of::<adc_digi_output_data_t>()])
1267 });
1268
1269 pub const fn new() -> Self {
1270 Self::INIT
1271 }
1272
1273 #[cfg(any(esp32, esp32s2))]
1274 pub fn data(&self) -> u16 {
1275 unsafe { self.0.__bindgen_anon_1.type1.data() as _ }
1276 }
1277
1278 #[cfg(any(esp32, esp32s2))]
1279 pub fn channel(&self) -> adc_channel_t {
1280 unsafe { self.0.__bindgen_anon_1.type1.channel() as _ }
1281 }
1282
1283 #[cfg(not(any(esp32, esp32s2)))]
1284 pub fn data(&self) -> u16 {
1285 unsafe { self.0.__bindgen_anon_1.type2.data() as _ }
1286 }
1287
1288 #[cfg(not(any(esp32, esp32s2)))]
1289 pub fn channel(&self) -> adc_channel_t {
1290 unsafe { self.0.__bindgen_anon_1.type2.channel() as _ }
1291 }
1292
1293 #[cfg(not(any(esp32, esp32s2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61)))]
1294 pub fn unit(&self) -> adc_unit_t {
1295 unsafe { self.0.__bindgen_anon_1.type2.unit() as _ }
1296 }
1297
1298 #[cfg(any(esp32, esp32s2))]
1299 pub fn nullify(&mut self) {
1300 self.0.__bindgen_anon_1.val = self.data();
1301 }
1302
1303 #[cfg(not(any(esp32, esp32s2)))]
1304 pub fn nullify(&mut self) {
1305 self.0.__bindgen_anon_1.val = self.data() as _;
1306 }
1307
1308 #[cfg(any(esp32, esp32s2))]
1309 pub fn as_pcm16(data: &mut [AdcMeasurement]) -> &mut [u16] {
1310 for measurement in data.iter_mut() {
1311 measurement.nullify();
1312 }
1313
1314 unsafe { core::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut _, data.len()) }
1315 }
1316
1317 #[cfg(not(any(esp32, esp32s2)))]
1318 pub fn as_pcm32(data: &mut [AdcMeasurement]) -> &mut [u32] {
1319 for measurement in data.iter_mut() {
1320 measurement.nullify();
1321 }
1322
1323 unsafe { core::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut _, data.len()) }
1324 }
1325 }
1326
1327 impl Display for AdcMeasurement {
1328 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1329 write!(
1330 f,
1331 "ADC Reading {{channel={}, data={}}}",
1332 self.channel(),
1333 self.data()
1334 )
1335 }
1336 }
1337
1338 impl Debug for AdcMeasurement {
1339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1340 write!(
1341 f,
1342 "AdcMeasurement {{channel: {}, data: {}}}",
1343 self.channel(),
1344 self.data()
1345 )
1346 }
1347 }
1348
1349 pub mod config {
1350 use crate::units::*;
1351
1352 #[derive(Debug, Copy, Clone)]
1358 pub struct Config {
1359 pub sample_freq: Hertz,
1360 pub frame_measurements: usize,
1361 pub frames_count: usize,
1362 }
1363
1364 impl Config {
1365 pub const fn new() -> Self {
1366 Self {
1367 sample_freq: Hertz(20000),
1368 frame_measurements: 100,
1369 frames_count: 10,
1370 }
1371 }
1372
1373 #[must_use]
1374 pub fn sample_freq(mut self, sample_freq: Hertz) -> Self {
1375 self.sample_freq = sample_freq;
1376 self
1377 }
1378
1379 #[must_use]
1380 pub fn frame_measurements(mut self, frame_measurements: usize) -> Self {
1381 self.frame_measurements = frame_measurements;
1382 self
1383 }
1384
1385 #[must_use]
1386 pub fn frames_count(mut self, frames_count: usize) -> Self {
1387 self.frames_count = frames_count;
1388 self
1389 }
1390 }
1391
1392 impl Default for Config {
1393 fn default() -> Self {
1394 Self::new()
1395 }
1396 }
1397 }
1398
1399 pub struct AdcDriver<'d> {
1400 handle: adc_continuous_handle_t,
1401 adc: u8,
1402 _ref: PhantomData<&'d ()>,
1403 }
1404
1405 impl<'d> AdcDriver<'d> {
1406 #[cfg(esp32)]
1408 pub fn new(
1409 adc: super::ADC1<'d>,
1410 _i2s: crate::i2s::I2S0<'d>,
1411 config: &config::Config,
1412 channels: impl AdcChannels<AdcUnit = super::ADCU1> + 'd,
1413 ) -> Result<Self, EspError> {
1414 Self::internal_new(adc, config, channels)
1415 }
1416
1417 #[cfg(esp32s2)]
1419 pub fn new(
1420 adc: super::ADC1<'d>,
1421 _spi: crate::spi::SPI3<'d>,
1422 config: &config::Config,
1423 channels: impl AdcChannels<AdcUnit = super::ADCU1> + 'd,
1424 ) -> Result<Self, EspError> {
1425 Self::internal_new(adc, config, channels)
1426 }
1427
1428 #[cfg(not(any(esp32, esp32s2)))]
1430 pub fn new<A: Adc + 'd>(
1431 adc: A,
1432 config: &config::Config,
1433 channels: impl AdcChannels<AdcUnit = A::AdcUnit> + 'd,
1434 ) -> Result<Self, EspError> {
1435 Self::internal_new(adc, config, channels)
1436 }
1437
1438 fn internal_new<A: Adc + 'd>(
1439 _adc: A,
1440 config: &config::Config,
1441 channels: impl AdcChannels<AdcUnit = A::AdcUnit> + 'd,
1442 ) -> Result<Self, EspError> {
1443 let mut patterns = [adc_digi_pattern_config_t::default(); 32];
1444
1445 for (index, (channel, atten)) in channels.iter().enumerate() {
1446 if index >= patterns.len() {
1447 return Err(EspError::from_infallible::<ESP_ERR_INVALID_ARG>());
1448 }
1449
1450 patterns[index].atten = atten as _;
1451 patterns[index].channel = channel as _;
1452 patterns[index].unit = A::unit() as _;
1453 patterns[index].bit_width = 12; }
1455
1456 let mut handle: adc_continuous_handle_t = core::ptr::null_mut();
1457
1458 #[allow(clippy::needless_update)]
1459 esp!(unsafe {
1460 adc_continuous_new_handle(
1461 &adc_continuous_handle_cfg_t {
1462 max_store_buf_size: SOC_ADC_DIGI_DATA_BYTES_PER_CONV
1463 * (config.frame_measurements as u32)
1464 * (config.frames_count as u32),
1465 conv_frame_size: SOC_ADC_DIGI_DATA_BYTES_PER_CONV
1466 * (config.frame_measurements as u32),
1467 ..Default::default()
1468 },
1469 &mut handle,
1470 )
1471 })?;
1472
1473 let conv_mode = if A::unit() == 0 {
1474 adc_digi_convert_mode_t_ADC_CONV_SINGLE_UNIT_1
1475 } else {
1476 adc_digi_convert_mode_t_ADC_CONV_SINGLE_UNIT_2
1477 };
1478
1479 #[cfg(any(esp32, esp32s2))]
1480 let format = adc_digi_output_format_t_ADC_DIGI_OUTPUT_FORMAT_TYPE1;
1481
1482 #[cfg(not(any(esp32, esp32s2)))]
1483 let format = adc_digi_output_format_t_ADC_DIGI_OUTPUT_FORMAT_TYPE2;
1484
1485 esp!(unsafe {
1486 adc_continuous_config(
1487 handle,
1488 &adc_continuous_config_t {
1489 pattern_num: channels.iter().count() as _,
1490 adc_pattern: &patterns as *const _ as *mut _,
1491 sample_freq_hz: config.sample_freq.into(),
1492 conv_mode,
1493 format,
1494 },
1495 )
1496 })?;
1497
1498 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1499 {
1500 esp!(unsafe {
1501 adc_continuous_register_event_callbacks(
1502 handle,
1503 &adc_continuous_evt_cbs_t {
1504 on_conv_done: Some(Self::handle_isr),
1505 on_pool_ovf: Some(Self::handle_isr),
1506 },
1507 &NOTIFIER[A::unit() as usize] as *const _ as *mut _,
1508 )
1509 })?;
1510 }
1511
1512 Ok(Self {
1513 handle,
1514 adc: A::unit() as _,
1515 _ref: PhantomData,
1516 })
1517 }
1518
1519 pub fn handle(&self) -> adc_continuous_handle_t {
1521 self.handle
1522 }
1523
1524 pub fn unit(&self) -> adc_unit_t {
1526 self.adc as _
1527 }
1528
1529 pub fn start(&mut self) -> Result<(), EspError> {
1531 esp!(unsafe { adc_continuous_start(self.handle) })
1532 }
1533
1534 pub fn stop(&mut self) -> Result<(), EspError> {
1536 esp!(unsafe { adc_continuous_stop(self.handle) })
1537 }
1538
1539 pub fn read(
1541 &mut self,
1542 buf: &mut [AdcMeasurement],
1543 timeout: TickType_t,
1544 ) -> Result<usize, EspError> {
1545 let mut read: u32 = 0;
1546
1547 esp!(unsafe {
1548 adc_continuous_read(
1549 self.handle,
1550 buf.as_mut_ptr() as *mut _,
1551 core::mem::size_of_val(buf) as _,
1552 &mut read,
1553 TickType(timeout).as_millis_u32(),
1554 )
1555 })?;
1556
1557 Ok(read as usize / core::mem::size_of::<AdcMeasurement>())
1558 }
1559
1560 pub fn read_bytes(
1562 &mut self,
1563 buf: &mut [u8],
1564 timeout: TickType_t,
1565 ) -> Result<usize, EspError> {
1566 let mut read: u32 = 0;
1567
1568 esp!(unsafe {
1569 adc_continuous_read(
1570 self.handle,
1571 buf.as_mut_ptr() as *mut _,
1572 core::mem::size_of_val(buf) as _,
1573 &mut read,
1574 TickType(timeout).as_millis_u32(),
1575 )
1576 })?;
1577
1578 Ok(read as usize)
1579 }
1580
1581 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1582 pub async fn read_async(&mut self, buf: &mut [AdcMeasurement]) -> Result<usize, EspError> {
1583 loop {
1584 match self.read(buf, delay::NON_BLOCK) {
1585 Ok(len) if len > 0 => return Ok(len),
1586 Err(e) if e.code() != ESP_ERR_TIMEOUT => return Err(e),
1587 _ => {
1588 NOTIFIER[self.adc as usize].wait().await;
1589 }
1590 }
1591 }
1592 }
1593
1594 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1595 pub async fn read_bytes_async(&mut self, buf: &mut [u8]) -> Result<usize, EspError> {
1596 loop {
1597 match self.read_bytes(buf, delay::NON_BLOCK) {
1598 Ok(len) if len > 0 => return Ok(len),
1599 Err(e) if e.code() != ESP_ERR_TIMEOUT => return Err(e),
1600 _ => {
1601 NOTIFIER[self.adc as usize].wait().await;
1602 }
1603 }
1604 }
1605 }
1606
1607 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1608 extern "C" fn handle_isr(
1609 _handle: adc_continuous_handle_t,
1610 _data: *const adc_continuous_evt_data_t,
1611 user_data: *mut c_void,
1612 ) -> bool {
1613 let notifier: &HalIsrNotification =
1614 unsafe { (user_data as *const HalIsrNotification).as_ref() }.unwrap();
1615
1616 notifier.notify_lsb()
1617 }
1618 }
1619
1620 impl Drop for AdcDriver<'_> {
1621 fn drop(&mut self) {
1622 let _ = self.stop();
1623
1624 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1625 {
1626 esp!(unsafe {
1627 adc_continuous_register_event_callbacks(
1628 self.handle,
1629 &adc_continuous_evt_cbs_t {
1630 on_conv_done: None,
1631 on_pool_ovf: None,
1632 },
1633 core::ptr::null_mut(),
1634 )
1635 })
1636 .unwrap();
1637 }
1638
1639 esp!(unsafe { adc_continuous_deinit(self.handle) }).unwrap();
1640
1641 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1642 NOTIFIER[self.adc as usize].reset();
1643 }
1644 }
1645
1646 unsafe impl Send for AdcDriver<'_> {}
1647
1648 impl embedded_io::ErrorType for AdcDriver<'_> {
1649 type Error = EspIOError;
1650 }
1651
1652 impl embedded_io::Read for AdcDriver<'_> {
1653 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1654 self.read_bytes(buf, delay::BLOCK).map_err(EspIOError)
1655 }
1656 }
1657
1658 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1659 impl embedded_io_async::Read for AdcDriver<'_> {
1660 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1661 self.read_bytes_async(buf).await.map_err(EspIOError)
1662 }
1663 }
1664
1665 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1666 #[cfg(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4))] static NOTIFIER: [HalIsrNotification; 1] = [HalIsrNotification::new()];
1668
1669 #[cfg(not(esp_idf_adc_continuous_isr_iram_safe))]
1670 #[cfg(not(any(esp32c2, esp32h2, esp32h4, esp32c5, esp32c6, esp32c61, esp32p4)))] static NOTIFIER: [HalIsrNotification; 2] =
1672 [HalIsrNotification::new(), HalIsrNotification::new()];
1673}