diff --git a/Cargo.toml b/Cargo.toml index 553c0a4e3..3b44892c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,11 @@ alloc = [] nightly = [] wake-from-isr = [] # Only enable if you plan to use the `edge-executor` crate embassy-sync = [] # For now, the dependecy on the `embassy-sync` crate is non-optional, but this might change in future - +# Temporary, until (https://github.com/espressif/esp-idf/issues/13938) is addressed +# - When enabled, the code for the legacy ADC oneshot driver will be compiled; +# - When not enabled (default) the code for the new ADC oneshot driver will be compiled; +# - Since we don't wrap the legacy _continuous_ ADC driver, the new _continuous_ ADC driver is always compiled. +adc-oneshot-legacy = [] # Propagated esp-idf-sys features native = ["esp-idf-sys/native"] pio = ["esp-idf-sys/pio"] diff --git a/examples/adc.rs b/examples/adc.rs index 2d27a1571..d1a805711 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -6,11 +6,12 @@ use esp_idf_sys::{self as _}; // If using the `binstart` feature of `esp-idf-sys use std::thread; use std::time::Duration; -use esp_idf_hal::adc::config::Config; -use esp_idf_hal::adc::*; -use esp_idf_hal::peripherals::Peripherals; - +#[cfg(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4"))] fn main() -> anyhow::Result<()> { + use esp_idf_hal::adc::config::Config; + use esp_idf_hal::adc::*; + use esp_idf_hal::peripherals::Peripherals; + let peripherals = Peripherals::take()?; #[cfg(not(esp32))] @@ -35,3 +36,12 @@ fn main() -> anyhow::Result<()> { println!("ADC value: {}", adc.read(&mut adc_pin)?); } } + +#[cfg(not(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4")))] +fn main() -> anyhow::Result<()> { + println!("This example requires feature `adc-oneshot-legacy` enabled or using ESP-IDF v4.4.X"); + + loop { + thread::sleep(Duration::from_millis(1000)); + } +} diff --git a/examples/adc_oneshot.rs b/examples/adc_oneshot.rs index 5cef9d4c7..542dba4fd 100644 --- a/examples/adc_oneshot.rs +++ b/examples/adc_oneshot.rs @@ -4,7 +4,7 @@ use std::thread; use std::time::Duration; -#[cfg(not(esp_idf_version_major = "4"))] +#[cfg(not(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4")))] fn main() -> anyhow::Result<()> { use esp_idf_hal::adc::attenuation::DB_11; use esp_idf_hal::adc::oneshot::config::AdcChannelConfig; @@ -40,9 +40,11 @@ fn main() -> anyhow::Result<()> { } } -#[cfg(esp_idf_version_major = "4")] +#[cfg(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4"))] fn main() -> anyhow::Result<()> { - println!("This example requires ESP-IDF v5.0 or newer"); + println!( + "This example requires ESP-IDF v5.X or newer and feature `adc-oneshot-legacy` disabled" + ); loop { thread::sleep(Duration::from_millis(1000)); diff --git a/src/adc.rs b/src/adc.rs index 30f3bcf95..fcb9c1c73 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,11 +1,5 @@ use esp_idf_sys::*; -use crate::gpio::ADCPin; - -use crate::peripheral::{Peripheral, PeripheralRef}; - -pub type AdcConfig = config::Config; - #[cfg(all( not(esp_idf_version_major = "4"), not(esp32c2), @@ -17,6 +11,9 @@ pub use continuous::{ Attenuated, ChainedAdcChannels, EmptyAdcChannels, }; +#[cfg(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4"))] +pub use oneshot_legacy::*; + pub trait Adc: Send { fn unit() -> adc_unit_t; } @@ -34,381 +31,403 @@ pub mod attenuation { pub const DB_11: adc_atten_t = adc_atten_t_ADC_ATTEN_DB_11; } -/// ADC configuration -pub mod config { +/// The sampling/readout resolution of the ADC +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Resolution { + #[cfg(esp32)] + Resolution9Bit, + #[cfg(esp32)] + Resolution10Bit, + #[cfg(esp32)] + Resolution11Bit, + #[cfg(any(esp32, esp32c3, esp32s3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + Resolution12Bit, + #[cfg(esp32s2)] + Resolution13Bit, +} + +impl Default for Resolution { + #[cfg(any(esp32, esp32c3, esp32s3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + fn default() -> Self { + Self::Resolution12Bit + } + + #[cfg(esp32s2)] + fn default() -> Self { + Self::Resolution13Bit + } +} + +impl From for adc_bits_width_t { + fn from(resolution: Resolution) -> Self { + match resolution { + #[cfg(esp32)] + Resolution::Resolution9Bit => adc_bits_width_t_ADC_WIDTH_BIT_9, + #[cfg(esp32)] + Resolution::Resolution10Bit => adc_bits_width_t_ADC_WIDTH_BIT_10, + #[cfg(esp32)] + Resolution::Resolution11Bit => adc_bits_width_t_ADC_WIDTH_BIT_11, + #[cfg(any(esp32, esp32s3, esp32c3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + Resolution::Resolution12Bit => adc_bits_width_t_ADC_WIDTH_BIT_12, + #[cfg(esp32s2)] + Resolution::Resolution13Bit => adc_bits_width_t_ADC_WIDTH_BIT_13, + } + } +} + +#[cfg(any(feature = "adc-oneshot-legacy", esp_idf_version_major = "4"))] +mod oneshot_legacy { use esp_idf_sys::*; - /// The sampling/readout resolution of the ADC - #[derive(Debug, PartialEq, Eq, Clone, Copy)] - pub enum Resolution { - #[cfg(esp32)] - Resolution9Bit, - #[cfg(esp32)] - Resolution10Bit, - #[cfg(esp32)] - Resolution11Bit, - #[cfg(any(esp32, esp32c3, esp32s3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - Resolution12Bit, - #[cfg(esp32s2)] - Resolution13Bit, - } + use crate::gpio::ADCPin; - impl Default for Resolution { - #[cfg(any(esp32, esp32c3, esp32s3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - fn default() -> Self { - Self::Resolution12Bit + use crate::peripheral::{Peripheral, PeripheralRef}; + + use super::{to_nb_err, Adc}; + + pub type AdcConfig = config::Config; + + /// ADC configuration + pub mod config { + pub use crate::adc::Resolution; + + #[derive(Debug, Copy, Clone, Default)] + pub struct Config { + pub resolution: Resolution, + #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))] + pub calibration: bool, } - #[cfg(esp32s2)] - fn default() -> Self { - Self::Resolution13Bit - } - } + impl Config { + pub fn new() -> Self { + Default::default() + } - impl From for adc_bits_width_t { - fn from(resolution: Resolution) -> Self { - match resolution { - #[cfg(esp32)] - Resolution::Resolution9Bit => adc_bits_width_t_ADC_WIDTH_BIT_9, - #[cfg(esp32)] - Resolution::Resolution10Bit => adc_bits_width_t_ADC_WIDTH_BIT_10, - #[cfg(esp32)] - Resolution::Resolution11Bit => adc_bits_width_t_ADC_WIDTH_BIT_11, - #[cfg(any(esp32, esp32s3, esp32c3, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - Resolution::Resolution12Bit => adc_bits_width_t_ADC_WIDTH_BIT_12, - #[cfg(esp32s2)] - Resolution::Resolution13Bit => adc_bits_width_t_ADC_WIDTH_BIT_13, + #[must_use] + pub fn resolution(mut self, resolution: Resolution) -> Self { + self.resolution = resolution; + self + } + + #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))] + #[must_use] + pub fn calibration(mut self, calibration: bool) -> Self { + self.calibration = calibration; + self } } } - #[derive(Debug, Copy, Clone, Default)] - pub struct Config { - pub resolution: Resolution, - #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))] - pub calibration: bool, + pub struct AdcChannelDriver<'d, const A: adc_atten_t, T: ADCPin> { + pin: PeripheralRef<'d, T>, } - impl Config { - pub fn new() -> Self { - Default::default() + impl<'d, const A: adc_atten_t, T: ADCPin> AdcChannelDriver<'d, A, T> { + pub fn new(pin: impl Peripheral

+ 'd) -> Result { + crate::into_ref!(pin); + + unsafe { + crate::gpio::rtc_reset_pin(pin.pin())?; + } + + if T::Adc::unit() == adc_unit_t_ADC_UNIT_1 { + esp!(unsafe { adc1_config_channel_atten(pin.adc_channel(), A) })?; + } else { + #[cfg(not(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4)))] + esp!(unsafe { adc2_config_channel_atten(pin.adc_channel(), A) })?; + + #[cfg(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + unreachable!(); + } + + Ok(Self { pin }) } - #[must_use] - pub fn resolution(mut self, resolution: Resolution) -> Self { - self.resolution = resolution; - self - } - - #[cfg(any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled))] - #[must_use] - pub fn calibration(mut self, calibration: bool) -> Self { - self.calibration = calibration; - self + fn pin(&mut self) -> &mut PeripheralRef<'d, T> { + &mut self.pin } } -} -pub struct AdcChannelDriver<'d, const A: adc_atten_t, T: ADCPin> { - pin: PeripheralRef<'d, T>, -} + impl<'d, const A: adc_atten_t, T: ADCPin> embedded_hal_0_2::adc::Channel + for AdcChannelDriver<'d, A, T> + { + type ID = (adc_channel_t, adc_atten_t); -impl<'d, const A: adc_atten_t, T: ADCPin> AdcChannelDriver<'d, A, T> { - pub fn new(pin: impl Peripheral

+ 'd) -> Result { - crate::into_ref!(pin); - - unsafe { - crate::gpio::rtc_reset_pin(pin.pin())?; + fn channel() -> Self::ID { + (T::CHANNEL, A) } - - if T::Adc::unit() == adc_unit_t_ADC_UNIT_1 { - esp!(unsafe { adc1_config_channel_atten(pin.adc_channel(), A) })?; - } else { - #[cfg(not(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4)))] - esp!(unsafe { adc2_config_channel_atten(pin.adc_channel(), A) })?; - - #[cfg(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - unreachable!(); - } - - Ok(Self { pin }) } - fn pin(&mut self) -> &mut PeripheralRef<'d, T> { - &mut self.pin - } -} - -impl<'d, const A: adc_atten_t, T: ADCPin> embedded_hal_0_2::adc::Channel - for AdcChannelDriver<'d, A, T> -{ - type ID = (adc_channel_t, adc_atten_t); - - fn channel() -> Self::ID { - (T::CHANNEL, A) - } -} - -pub struct AdcDriver<'d, ADC: Adc> { - _adc: PeripheralRef<'d, ADC>, - #[allow(dead_code)] - resolution: config::Resolution, - #[cfg(all( - any(esp32, esp32s2, esp32s3, esp32c3), - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - ))] - cal_characteristics: - Option<[Option; adc_atten_t_ADC_ATTEN_DB_11 as usize + 1]>, -} - -unsafe impl<'d, ADC: Adc> Send for AdcDriver<'d, ADC> {} - -impl<'d, ADC: Adc> AdcDriver<'d, ADC> { - #[cfg(all( - esp32, - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - ))] - const CALIBRATION_SCHEME: esp_adc_cal_value_t = esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_VREF; - - #[cfg(all( - any(esp32c3, esp32s2), - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - ))] - const CALIBRATION_SCHEME: esp_adc_cal_value_t = esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP; - - #[cfg(all( - esp32s3, - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - ))] - const CALIBRATION_SCHEME: esp_adc_cal_value_t = - esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP_FIT; - - #[cfg(not(esp32s2))] - const MAX_READING: u32 = 4095; - - #[cfg(esp32s2)] - const MAX_READING: u32 = 8191; - - pub fn new( - adc: impl Peripheral

+ 'd, - config: &config::Config, - ) -> Result { - crate::into_ref!(adc); - + pub struct AdcDriver<'d, ADC: Adc> { + _adc: PeripheralRef<'d, ADC>, + #[allow(dead_code)] + resolution: config::Resolution, #[cfg(all( any(esp32, esp32s2, esp32s3, esp32c3), any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) ))] - if config.calibration { - esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?; - } + cal_characteristics: Option< + [Option; adc_atten_t_ADC_ATTEN_DB_11 as usize + 1], + >, + } - if ADC::unit() == adc_unit_t_ADC_UNIT_1 { - esp!(unsafe { adc1_config_width(config.resolution.into()) })?; - } + unsafe impl<'d, ADC: Adc> Send for AdcDriver<'d, ADC> {} + + impl<'d, ADC: Adc> AdcDriver<'d, ADC> { + #[cfg(all( + esp32, + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + ))] + const CALIBRATION_SCHEME: esp_adc_cal_value_t = + esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_VREF; + + #[cfg(all( + any(esp32c3, esp32s2), + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + ))] + const CALIBRATION_SCHEME: esp_adc_cal_value_t = + esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP; + + #[cfg(all( + esp32s3, + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + ))] + const CALIBRATION_SCHEME: esp_adc_cal_value_t = + esp_adc_cal_value_t_ESP_ADC_CAL_VAL_EFUSE_TP_FIT; + + #[cfg(not(esp32s2))] + const MAX_READING: u32 = 4095; + + #[cfg(esp32s2)] + const MAX_READING: u32 = 8191; + + pub fn new( + adc: impl Peripheral

+ 'd, + config: &config::Config, + ) -> Result { + crate::into_ref!(adc); - Ok(Self { - _adc: adc, - resolution: config.resolution, #[cfg(all( any(esp32, esp32s2, esp32s3, esp32c3), any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) ))] - cal_characteristics: if config.calibration { - Some(Default::default()) - } else { - None - }, - }) - } - - #[inline(always)] - pub fn read( - &mut self, - pin: &mut AdcChannelDriver<'_, A, T>, - ) -> Result - where - T: ADCPin, - { - self.read_internal(ADC::unit(), pin.pin().adc_channel(), A) - } - - #[inline(always)] - pub fn read_raw( - &mut self, - pin: &mut AdcChannelDriver<'_, A, T>, - ) -> Result - where - T: ADCPin, - { - self.read_internal_raw(ADC::unit(), pin.pin().adc_channel()) - } - - #[inline(always)] - #[cfg(all(esp32, esp_idf_version_major = "4"))] - pub fn read_hall( - &mut self, - hall_sensor: &mut crate::hall::HallSensor, - ) -> Result { - let measurement = self.read_hall_raw(hall_sensor); - - self.raw_to_voltage(measurement, adc_atten_t_ADC_ATTEN_DB_0) - } - - #[inline(always)] - #[cfg(all(esp32, esp_idf_version_major = "4"))] - pub fn read_hall_raw(&mut self, _hall_sensor: &mut crate::hall::HallSensor) -> u16 { - unsafe { hall_sensor_read() as u16 } - } - - #[inline(always)] - fn read_internal( - &mut self, - unit: adc_unit_t, - channel: adc_channel_t, - atten: adc_atten_t, - ) -> Result { - let measurement = self.read_internal_raw(unit, channel)?; - self.raw_to_voltage(measurement, atten) - } - - #[inline(always)] - fn read_internal_raw( - &mut self, - unit: adc_unit_t, - channel: adc_channel_t, - ) -> Result { - if unit == adc_unit_t_ADC_UNIT_1 { - Ok(unsafe { adc1_get_raw(channel) } as _) - } else { - #[cfg(not(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4)))] - { - let mut measurement = 0; - esp!(unsafe { adc2_get_raw(channel, self.resolution.into(), &mut measurement) })?; - - Ok(measurement as _) + if config.calibration { + esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?; } - #[cfg(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - unreachable!(); - } - } + if ADC::unit() == adc_unit_t_ADC_UNIT_1 { + esp!(unsafe { adc1_config_width(config.resolution.into()) })?; + } + + Ok(Self { + _adc: adc, + resolution: config.resolution, + #[cfg(all( + any(esp32, esp32s2, esp32s3, esp32c3), + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + ))] + cal_characteristics: if config.calibration { + Some(Default::default()) + } else { + None + }, + }) + } + + #[inline(always)] + pub fn read( + &mut self, + pin: &mut AdcChannelDriver<'_, A, T>, + ) -> Result + where + T: ADCPin, + { + self.read_internal(ADC::unit(), pin.pin().adc_channel(), A) + } + + #[inline(always)] + pub fn read_raw( + &mut self, + pin: &mut AdcChannelDriver<'_, A, T>, + ) -> Result + where + T: ADCPin, + { + self.read_internal_raw(ADC::unit(), pin.pin().adc_channel()) + } + + #[inline(always)] + #[cfg(all(esp32, esp_idf_version_major = "4"))] + pub fn read_hall( + &mut self, + hall_sensor: &mut crate::hall::HallSensor, + ) -> Result { + let measurement = self.read_hall_raw(hall_sensor); + + self.raw_to_voltage(measurement, adc_atten_t_ADC_ATTEN_DB_0) + } + + #[inline(always)] + #[cfg(all(esp32, esp_idf_version_major = "4"))] + pub fn read_hall_raw(&mut self, _hall_sensor: &mut crate::hall::HallSensor) -> u16 { + unsafe { hall_sensor_read() as u16 } + } + + #[inline(always)] + fn read_internal( + &mut self, + unit: adc_unit_t, + channel: adc_channel_t, + atten: adc_atten_t, + ) -> Result { + let measurement = self.read_internal_raw(unit, channel)?; + self.raw_to_voltage(measurement, atten) + } + + #[inline(always)] + fn read_internal_raw( + &mut self, + unit: adc_unit_t, + channel: adc_channel_t, + ) -> Result { + if unit == adc_unit_t_ADC_UNIT_1 { + Ok(unsafe { adc1_get_raw(channel) } as _) + } else { + #[cfg(not(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4)))] + { + let mut measurement = 0; + esp!(unsafe { + adc2_get_raw(channel, self.resolution.into(), &mut measurement) + })?; + + Ok(measurement as _) + } + + #[cfg(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + unreachable!(); + } + } + + #[inline(always)] + fn raw_to_voltage( + &mut self, + measurement: u16, + attenuation: adc_atten_t, + ) -> Result { + #[cfg(all( + any(esp32, esp32s2, esp32s3, esp32c3), + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + ))] + let mv = if let Some(cal) = self.get_cal_characteristics(attenuation)? { + unsafe { esp_adc_cal_raw_to_voltage(measurement as u32, &cal) as u16 } + } else { + (measurement as u32 * Self::get_max_mv(attenuation) / Self::MAX_READING) as u16 + }; + + #[cfg(not(all( + any(esp32, esp32s2, esp32s3, esp32c3), + any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) + )))] + let mv = + (measurement as u32 * Self::get_max_mv(attenuation) / Self::MAX_READING) as u16; + + Ok(mv) + } + + #[inline(always)] + #[allow(non_upper_case_globals)] + fn get_max_mv(attenuation: adc_atten_t) -> u32 { + #[cfg(esp32)] + let mv = match attenuation { + adc_atten_t_ADC_ATTEN_DB_0 => 950, + adc_atten_t_ADC_ATTEN_DB_2_5 => 1250, + adc_atten_t_ADC_ATTEN_DB_6 => 1750, + adc_atten_t_ADC_ATTEN_DB_11 => 2450, + other => panic!("Unknown attenuation: {}", other), + }; + + #[cfg(any(esp32c3, esp32s2, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] + let mv = match attenuation { + adc_atten_t_ADC_ATTEN_DB_0 => 750, + adc_atten_t_ADC_ATTEN_DB_2_5 => 1050, + adc_atten_t_ADC_ATTEN_DB_6 => 1300, + adc_atten_t_ADC_ATTEN_DB_11 => 2500, + other => panic!("Unknown attenuation: {}", other), + }; + + #[cfg(esp32s3)] + let mv = match attenuation { + adc_atten_t_ADC_ATTEN_DB_0 => 950, + adc_atten_t_ADC_ATTEN_DB_2_5 => 1250, + adc_atten_t_ADC_ATTEN_DB_6 => 1750, + adc_atten_t_ADC_ATTEN_DB_11 => 3100, + other => panic!("Unknown attenuation: {}", other), + }; + + mv + } - #[inline(always)] - fn raw_to_voltage( - &mut self, - measurement: u16, - attenuation: adc_atten_t, - ) -> Result { #[cfg(all( any(esp32, esp32s2, esp32s3, esp32c3), any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) ))] - let mv = if let Some(cal) = self.get_cal_characteristics(attenuation)? { - unsafe { esp_adc_cal_raw_to_voltage(measurement as u32, &cal) as u16 } - } else { - (measurement as u32 * Self::get_max_mv(attenuation) / Self::MAX_READING) as u16 - }; + fn get_cal_characteristics( + &mut self, + attenuation: adc_atten_t, + ) -> Result, EspError> { + if let Some(characteristics) = &mut self.cal_characteristics { + if let Some(cal) = characteristics[attenuation as usize] { + Ok(Some(cal)) + } else { + esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?; - #[cfg(not(all( - any(esp32, esp32s2, esp32s3, esp32c3), - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - )))] - let mv = (measurement as u32 * Self::get_max_mv(attenuation) / Self::MAX_READING) as u16; + let mut cal: esp_adc_cal_characteristics_t = Default::default(); + unsafe { + esp_adc_cal_characterize( + ADC::unit(), + attenuation, + self.resolution.into(), + 0, + &mut cal, + ) + }; - Ok(mv) - } + characteristics[attenuation as usize] = Some(cal); - #[inline(always)] - #[allow(non_upper_case_globals)] - fn get_max_mv(attenuation: adc_atten_t) -> u32 { - #[cfg(esp32)] - let mv = match attenuation { - adc_atten_t_ADC_ATTEN_DB_0 => 950, - adc_atten_t_ADC_ATTEN_DB_2_5 => 1250, - adc_atten_t_ADC_ATTEN_DB_6 => 1750, - adc_atten_t_ADC_ATTEN_DB_11 => 2450, - other => panic!("Unknown attenuation: {}", other), - }; - - #[cfg(any(esp32c3, esp32s2, esp32c2, esp32h2, esp32c5, esp32c6, esp32p4))] - let mv = match attenuation { - adc_atten_t_ADC_ATTEN_DB_0 => 750, - adc_atten_t_ADC_ATTEN_DB_2_5 => 1050, - adc_atten_t_ADC_ATTEN_DB_6 => 1300, - adc_atten_t_ADC_ATTEN_DB_11 => 2500, - other => panic!("Unknown attenuation: {}", other), - }; - - #[cfg(esp32s3)] - let mv = match attenuation { - adc_atten_t_ADC_ATTEN_DB_0 => 950, - adc_atten_t_ADC_ATTEN_DB_2_5 => 1250, - adc_atten_t_ADC_ATTEN_DB_6 => 1750, - adc_atten_t_ADC_ATTEN_DB_11 => 3100, - other => panic!("Unknown attenuation: {}", other), - }; - - mv - } - - #[cfg(all( - any(esp32, esp32s2, esp32s3, esp32c3), - any(esp_idf_comp_esp_adc_cal_enabled, esp_idf_comp_esp_adc_enabled) - ))] - fn get_cal_characteristics( - &mut self, - attenuation: adc_atten_t, - ) -> Result, EspError> { - if let Some(characteristics) = &mut self.cal_characteristics { - if let Some(cal) = characteristics[attenuation as usize] { - Ok(Some(cal)) + Ok(Some(cal)) + } } else { - esp!(unsafe { esp_adc_cal_check_efuse(Self::CALIBRATION_SCHEME) })?; - - let mut cal: esp_adc_cal_characteristics_t = Default::default(); - unsafe { - esp_adc_cal_characterize( - ADC::unit(), - attenuation, - self.resolution.into(), - 0, - &mut cal, - ) - }; - - characteristics[attenuation as usize] = Some(cal); - - Ok(Some(cal)) + Ok(None) } - } else { - Ok(None) } } -} -impl<'d, 'c, const A: adc_atten_t, T> - embedded_hal_0_2::adc::OneShot> - for AdcDriver<'d, T::Adc> -where - T: ADCPin, -{ - type Error = EspError; + impl<'d, 'c, const A: adc_atten_t, T> + embedded_hal_0_2::adc::OneShot> + for AdcDriver<'d, T::Adc> + where + T: ADCPin, + { + type Error = EspError; - fn read(&mut self, pin: &mut AdcChannelDriver<'c, A, T>) -> nb::Result { - self.read_internal(T::Adc::unit(), pin.pin.adc_channel(), A) - .map_err(to_nb_err) + fn read(&mut self, pin: &mut AdcChannelDriver<'c, A, T>) -> nb::Result { + self.read_internal(T::Adc::unit(), pin.pin.adc_channel(), A) + .map_err(to_nb_err) + } } -} -#[cfg(all(esp32, esp_idf_version_major = "4"))] -impl<'d> embedded_hal_0_2::adc::OneShot - for AdcDriver<'d, ADC1> -{ - type Error = EspError; + #[cfg(all(esp32, esp_idf_version_major = "4"))] + impl<'d> embedded_hal_0_2::adc::OneShot + for AdcDriver<'d, super::ADC1> + { + type Error = EspError; - fn read(&mut self, hall_sensor: &mut crate::hall::HallSensor) -> nb::Result { - AdcDriver::read_hall(self, hall_sensor).map_err(to_nb_err) + fn read( + &mut self, + hall_sensor: &mut crate::hall::HallSensor, + ) -> nb::Result { + AdcDriver::read_hall(self, hall_sensor).map_err(to_nb_err) + } } } @@ -437,7 +456,11 @@ impl_adc!(ADC1: adc_unit_t_ADC_UNIT_1); #[cfg(not(any(esp32c2, esp32h2, esp32c5, esp32c6, esp32p4)))] // TODO: Check for esp32c5 and esp32p4 impl_adc!(ADC2: adc_unit_t_ADC_UNIT_2); -#[cfg(all(not(esp_idf_version_major = "4"), esp_idf_comp_esp_adc_enabled))] +#[cfg(all( + not(feature = "adc-oneshot-legacy"), + not(esp_idf_version_major = "4"), + esp_idf_comp_esp_adc_enabled +))] pub mod oneshot { use core::borrow::Borrow; @@ -448,13 +471,13 @@ pub mod oneshot { use crate::peripheral::PeripheralRef; use super::attenuation::adc_atten_t; - use super::config::Resolution; use super::to_nb_err; use super::Adc; pub mod config { use super::adc_atten_t; - use super::Resolution; + + pub use crate::adc::Resolution; #[derive(Debug, Copy, Clone, Default)] pub struct AdcChannelConfig {