From f52aa1351c85a428c4ea6bbd874844a4516510ab Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 25 Jan 2024 16:46:27 +0000 Subject: [PATCH] Refactor the analog module (#1100) * Create virtual peripherals for `ADC`/`DAC` * Refactor the `analog::dac` module * Refactor the `analog::adc` module * Decouple the ADC driver from the `embedded-hal` traits * Update `CHANGELOG.md` * Seal the `AdcCalScheme` trait, reduce visibility of `AdcCalEfuse` trait * Remove `APB_SARADC`/`SENS` peripherals from the `Peripherals` struct --- CHANGELOG.md | 5 + .../{cal_basic.rs => calibration/basic.rs} | 3 + .../{cal_curve.rs => calibration/curve.rs} | 9 +- .../adc/{cal_line.rs => calibration/line.rs} | 7 +- .../src/analog/adc/calibration/mod.rs | 14 + esp-hal-common/src/analog/adc/esp32.rs | 188 +++++-------- esp-hal-common/src/analog/adc/mod.rs | 108 ++++++++ esp-hal-common/src/analog/adc/riscv.rs | 231 +++------------- esp-hal-common/src/analog/adc/xtensa.rs | 219 +++------------ esp-hal-common/src/analog/dac.rs | 228 +++++++-------- esp-hal-common/src/analog/mod.rs | 260 +----------------- esp-hal-common/src/prelude.rs | 2 - esp-hal-common/src/soc/esp32/peripherals.rs | 12 +- esp-hal-common/src/soc/esp32c2/peripherals.rs | 8 +- esp-hal-common/src/soc/esp32c3/peripherals.rs | 9 +- esp-hal-common/src/soc/esp32c6/peripherals.rs | 11 +- esp-hal-common/src/soc/esp32h2/peripherals.rs | 9 +- esp-hal-common/src/soc/esp32s2/peripherals.rs | 14 +- esp-hal-common/src/soc/esp32s3/peripherals.rs | 14 +- esp32-hal/examples/adc.rs | 8 +- esp32-hal/examples/dac.rs | 14 +- esp32c2-hal/examples/adc.rs | 10 +- esp32c2-hal/examples/adc_cal.rs | 19 +- esp32c3-hal/examples/adc.rs | 10 +- esp32c3-hal/examples/adc_cal.rs | 19 +- esp32c6-hal/examples/adc.rs | 10 +- esp32c6-hal/examples/adc_cal.rs | 19 +- esp32h2-hal/examples/adc.rs | 10 +- esp32s2-hal/examples/adc.rs | 10 +- esp32s2-hal/examples/dac.rs | 7 +- esp32s3-hal/examples/adc.rs | 10 +- esp32s3-hal/examples/adc_cal.rs | 19 +- 32 files changed, 482 insertions(+), 1034 deletions(-) rename esp-hal-common/src/analog/adc/{cal_basic.rs => calibration/basic.rs} (95%) rename esp-hal-common/src/analog/adc/{cal_curve.rs => calibration/curve.rs} (96%) rename esp-hal-common/src/analog/adc/{cal_line.rs => calibration/line.rs} (95%) create mode 100644 esp-hal-common/src/analog/adc/calibration/mod.rs create mode 100644 esp-hal-common/src/analog/adc/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index bbbcc920a..e836dde7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +### Breaking + +- `ADC` and `DAC` drivers now take virtual peripherals in their constructors, instead of splitting `APB_SARADC`/`SENS` (#1100) +- The `DAC` driver's constructor is now `new` instead of `dac`, to be more consistent with other APIs (#1100) + ## [0.15.0] - 2024-01-19 ### Added diff --git a/esp-hal-common/src/analog/adc/cal_basic.rs b/esp-hal-common/src/analog/adc/calibration/basic.rs similarity index 95% rename from esp-hal-common/src/analog/adc/cal_basic.rs rename to esp-hal-common/src/analog/adc/calibration/basic.rs index 1dce929a7..392fb4f14 100644 --- a/esp-hal-common/src/analog/adc/cal_basic.rs +++ b/esp-hal-common/src/analog/adc/calibration/basic.rs @@ -1,6 +1,7 @@ use core::marker::PhantomData; use crate::adc::{ + private, AdcCalEfuse, AdcCalScheme, AdcCalSource, @@ -27,6 +28,8 @@ pub struct AdcCalBasic { _phantom: PhantomData, } +impl private::Sealed for AdcCalBasic {} + impl AdcCalScheme for AdcCalBasic where ADCI: AdcCalEfuse + CalibrationAccess, diff --git a/esp-hal-common/src/analog/adc/cal_curve.rs b/esp-hal-common/src/analog/adc/calibration/curve.rs similarity index 96% rename from esp-hal-common/src/analog/adc/cal_curve.rs rename to esp-hal-common/src/analog/adc/calibration/curve.rs index 85432352b..30d8802dd 100644 --- a/esp-hal-common/src/analog/adc/cal_curve.rs +++ b/esp-hal-common/src/analog/adc/calibration/curve.rs @@ -1,6 +1,7 @@ use core::marker::PhantomData; use crate::adc::{ + private, AdcCalEfuse, AdcCalLine, AdcCalScheme, @@ -60,6 +61,8 @@ pub struct AdcCalCurve { _phantom: PhantomData, } +impl private::Sealed for AdcCalCurve {} + impl AdcCalScheme for AdcCalCurve where ADCI: AdcCalEfuse + AdcHasLineCal + AdcHasCurveCal + CalibrationAccess, @@ -126,17 +129,17 @@ macro_rules! coeff_tables { mod impls { use super::*; - impl AdcHasCurveCal for crate::adc::ADC1 { + impl AdcHasCurveCal for crate::peripherals::ADC1 { const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1; } #[cfg(esp32c3)] - impl AdcHasCurveCal for crate::adc::ADC2 { + impl AdcHasCurveCal for crate::peripherals::ADC2 { const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1; } #[cfg(esp32s3)] - impl AdcHasCurveCal for crate::adc::ADC2 { + impl AdcHasCurveCal for crate::peripherals::ADC2 { const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2; } diff --git a/esp-hal-common/src/analog/adc/cal_line.rs b/esp-hal-common/src/analog/adc/calibration/line.rs similarity index 95% rename from esp-hal-common/src/analog/adc/cal_line.rs rename to esp-hal-common/src/analog/adc/calibration/line.rs index 354f59205..f5b9c4459 100644 --- a/esp-hal-common/src/analog/adc/cal_line.rs +++ b/esp-hal-common/src/analog/adc/calibration/line.rs @@ -1,6 +1,7 @@ use core::marker::PhantomData; use crate::adc::{ + private, AdcCalBasic, AdcCalEfuse, AdcCalScheme, @@ -48,6 +49,8 @@ pub struct AdcCalLine { _phantom: PhantomData, } +impl private::Sealed for AdcCalLine {} + impl AdcCalScheme for AdcCalLine where ADCI: AdcCalEfuse + AdcHasLineCal + CalibrationAccess, @@ -96,7 +99,7 @@ where } #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] -impl AdcHasLineCal for crate::adc::ADC1 {} +impl AdcHasLineCal for crate::peripherals::ADC1 {} #[cfg(any(esp32c3, esp32s3))] -impl AdcHasLineCal for crate::adc::ADC2 {} +impl AdcHasLineCal for crate::peripherals::ADC2 {} diff --git a/esp-hal-common/src/analog/adc/calibration/mod.rs b/esp-hal-common/src/analog/adc/calibration/mod.rs new file mode 100644 index 000000000..b28ea47e9 --- /dev/null +++ b/esp-hal-common/src/analog/adc/calibration/mod.rs @@ -0,0 +1,14 @@ +#[cfg(any(esp32c3, esp32c6, esp32s3))] +pub use self::curve::{AdcCalCurve, AdcHasCurveCal}; +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] +pub use self::{ + basic::AdcCalBasic, + line::{AdcCalLine, AdcHasLineCal}, +}; + +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] +mod basic; +#[cfg(any(esp32c3, esp32c6, esp32s3))] +mod curve; +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] +mod line; diff --git a/esp-hal-common/src/analog/adc/esp32.rs b/esp-hal-common/src/analog/adc/esp32.rs index 81222c29e..d05823bf8 100644 --- a/esp-hal-common/src/analog/adc/esp32.rs +++ b/esp-hal-common/src/analog/adc/esp32.rs @@ -1,14 +1,12 @@ use core::marker::PhantomData; -use embedded_hal::adc::{Channel, OneShot}; - -pub use crate::analog::{ADC1, ADC2}; +use super::{AdcChannel, Attenuation}; use crate::{ peripheral::PeripheralRef, - peripherals::{RTC_IO, SENS}, + peripherals::{ADC1, ADC2, RTC_IO, SENS}, }; -/// The sampling/readout resolution of the ADC +/// The sampling/readout resolution of the ADC. #[derive(PartialEq, Eq, Clone, Copy)] pub enum Resolution { Resolution9Bit = 0b00, @@ -17,20 +15,16 @@ pub enum Resolution { Resolution12Bit = 0b11, } -#[derive(PartialEq, Eq, Clone, Copy)] -pub enum Attenuation { - Attenuation0dB = 0b00, - Attenuation2p5dB = 0b01, - Attenuation6dB = 0b10, - Attenuation11dB = 0b11, -} - +/// An I/O pin which can be read using the ADC. pub struct AdcPin { pub pin: PIN, _phantom: PhantomData, } -impl, ADCI> Channel for AdcPin { +impl embedded_hal::adc::Channel for AdcPin +where + PIN: embedded_hal::adc::Channel, +{ type ID = u8; fn channel() -> Self::ID { @@ -38,6 +32,7 @@ impl, ADCI> Channel for AdcPin { } } +/// Configuration for the ADC. pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; 10], @@ -49,16 +44,14 @@ where ADCI: RegisterAccess, { pub fn new() -> AdcConfig { - crate::into_ref!(); Self::default() } - pub fn enable_pin>( - &mut self, - pin: PIN, - attenuation: Attenuation, - ) -> AdcPin { - self.attenuations[PIN::channel() as usize] = Some(attenuation); + pub fn enable_pin(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin + where + PIN: AdcChannel, + { + self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { pin, @@ -77,6 +70,7 @@ impl Default for AdcConfig { } } +#[doc(hidden)] pub trait RegisterAccess { fn set_bit_width(resolution: u8); @@ -101,25 +95,21 @@ pub trait RegisterAccess { fn read_data_sar() -> u16; } -#[doc(hidden)] impl RegisterAccess for ADC1 { fn set_bit_width(resolution: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_start_force() .modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) }); } fn set_sample_bit(resolution: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_read_ctrl() .modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) }); } fn set_attenuation(channel: usize, attenuation: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors.sar_atten1().modify(|r, w| { + unsafe { &*SENS::ptr() }.sar_atten1().modify(|r, w| { let new_value = (r.bits() & !(0b11 << (channel * 2))) | (((attenuation as u8 & 0b11) as u32) << (channel * 2)); @@ -128,50 +118,43 @@ impl RegisterAccess for ADC1 { } fn clear_dig_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_read_ctrl() .modify(|_, w| w.sar1_dig_force().clear_bit()); } fn set_start_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .modify(|_, w| w.meas1_start_force().set_bit()); } fn set_en_pad_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .modify(|_, w| w.sar1_en_pad_force().set_bit()); } fn set_en_pad(channel: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) }); } fn clear_start_sar() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .modify(|_, w| w.meas1_start_sar().clear_bit()); } fn set_start_sar() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .modify(|_, w| w.meas1_start_sar().set_bit()); } fn read_done_sar() -> bool { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start1() .read() .meas1_done_sar() @@ -179,29 +162,29 @@ impl RegisterAccess for ADC1 { } fn read_data_sar() -> u16 { - let sensors = unsafe { &*SENS::ptr() }; - sensors.sar_meas_start1().read().meas1_data_sar().bits() as u16 + unsafe { &*SENS::ptr() } + .sar_meas_start1() + .read() + .meas1_data_sar() + .bits() as u16 } } impl RegisterAccess for ADC2 { fn set_bit_width(resolution: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_start_force() .modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) }); } fn set_sample_bit(resolution: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_read_ctrl2() .modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) }); } fn set_attenuation(channel: usize, attenuation: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors.sar_atten2().modify(|r, w| { + unsafe { &*SENS::ptr() }.sar_atten2().modify(|r, w| { let new_value = (r.bits() & !(0b11 << (channel * 2))) | (((attenuation as u8 & 0b11) as u32) << (channel * 2)); @@ -210,50 +193,43 @@ impl RegisterAccess for ADC2 { } fn clear_dig_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_read_ctrl2() .modify(|_, w| w.sar2_dig_force().clear_bit()); } fn set_start_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .modify(|_, w| w.meas2_start_force().set_bit()); } fn set_en_pad_force() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .modify(|_, w| w.sar2_en_pad_force().set_bit()); } fn set_en_pad(channel: u8) { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) }); } fn clear_start_sar() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .modify(|_, w| w.meas2_start_sar().clear_bit()); } fn set_start_sar() { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .modify(|_, w| w.meas2_start_sar().set_bit()); } fn read_done_sar() -> bool { - let sensors = unsafe { &*SENS::ptr() }; - sensors + unsafe { &*SENS::ptr() } .sar_meas_start2() .read() .meas2_done_sar() @@ -261,11 +237,15 @@ impl RegisterAccess for ADC2 { } fn read_data_sar() -> u16 { - let sensors = unsafe { &*SENS::ptr() }; - sensors.sar_meas_start2().read().meas2_data_sar().bits() as u16 + unsafe { &*SENS::ptr() } + .sar_meas_start2() + .read() + .meas2_data_sar() + .bits() as u16 } } +/// Analog-to-Digital Converter peripheral driver. pub struct ADC<'d, ADC> { _adc: PeripheralRef<'d, ADC>, attenuations: [Option; 10], @@ -355,25 +335,29 @@ where impl<'d, ADC1> ADC<'d, ADC1> { pub fn enable_hall_sensor() { // Connect hall sensor - let rtcio = unsafe { &*RTC_IO::ptr() }; - rtcio.hall_sens().modify(|_, w| w.xpd_hall().set_bit()); + unsafe { &*RTC_IO::ptr() } + .hall_sens() + .modify(|_, w| w.xpd_hall().set_bit()); } pub fn disable_hall_sensor() { // Disconnect hall sensor - let rtcio = unsafe { &*RTC_IO::ptr() }; - rtcio.hall_sens().modify(|_, w| w.xpd_hall().clear_bit()); + unsafe { &*RTC_IO::ptr() } + .hall_sens() + .modify(|_, w| w.xpd_hall().clear_bit()); } } -impl<'d, ADCI, PIN> OneShot> for ADC<'d, ADCI> +impl<'d, ADCI, PIN> embedded_hal::adc::OneShot> for ADC<'d, ADCI> where - PIN: Channel, + PIN: embedded_hal::adc::Channel, ADCI: RegisterAccess, { type Error = (); fn read(&mut self, _pin: &mut AdcPin) -> nb::Result { + use embedded_hal::adc::Channel; + if self.attenuations[AdcPin::::channel() as usize] == None { panic!( "Channel {} is not configured reading!", @@ -418,8 +402,11 @@ macro_rules! impl_adc_interface { ($adc:ident [ $( ($pin:ident, $channel:expr) ,)+ ]) => { - $( + impl $crate::analog::adc::AdcChannel for crate::gpio::$pin { + const CHANNEL: u8 = $channel; + } + impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin { type ID = u8; @@ -430,54 +417,7 @@ macro_rules! impl_adc_interface { } mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32: `ADC1` and `ADC2`. - //! - //! The following pins can be configured for analog readout: - //! - //! | Channel | ADC1 | ADC2 | - //! |---------|----------------------|---------------| - //! | 0 | GPIO36 (SENSOR_VP) | GPIO4 | - //! | 1 | GPIO37 (SENSOR_CAPP) | GPIO0 | - //! | 2 | GPIO38 (SENSOR_CAPN) | GPIO2 | - //! | 3 | GPIO39 (SENSOR_VN) | GPIO15 (MTDO) | - //! | 4 | GPIO33 (32K_XP) | GPIO13 (MTCK) | - //! | 5 | GPIO32 (32K_XN) | GPIO12 (MTDI) | - //! | 6 | GPIO34 (VDET_1) | GPIO14 (MTMS) | - //! | 7 | GPIO35 (VDET_2) | GPIO27 | - //! | 8 | | GPIO25 | - //! | 9 | | GPIO26 | - //! - //! ## Example - //! #### ADC on Xtensa architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.SENS.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin3 = - //! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap(); - //! println!("PIN3 ADC reading = {}", pin3_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::{ADC1, ADC2}; + use crate::peripherals::{ADC1, ADC2}; impl_adc_interface! { ADC1 [ @@ -494,9 +434,9 @@ mod implementation { impl_adc_interface! { ADC2 [ - (Gpio4, 0), - (Gpio0, 1), - (Gpio2, 2), + (Gpio4, 0), + (Gpio0, 1), + (Gpio2, 2), (Gpio15, 3), // Alt. name: MTDO (Gpio13, 4), // Alt. name: MTCK (Gpio12, 5), // Alt. name: MTDI diff --git a/esp-hal-common/src/analog/adc/mod.rs b/esp-hal-common/src/analog/adc/mod.rs new file mode 100644 index 000000000..061f272a2 --- /dev/null +++ b/esp-hal-common/src/analog/adc/mod.rs @@ -0,0 +1,108 @@ +//! # Analog to Digital Converter (ADC) +//! +//! The Analog to Digital Converter (ADC) is integrated on the chip, and is +//! capable of measuring analog signals from specific analog I/O pins. One or +//! more ADC units are available, depending on the device being used. +//! +//! ## Example +//! +//! ```no_run +//! let mut adc1_config = AdcConfig::new(); +//! let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); +//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); +//! +//! let mut delay = Delay::new(&clocks); +//! +//! loop { +//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); +//! println!("PIN2 ADC reading = {}", pin_value); +//! +//! delay.delay_ms(1500u32); +//! } +//! ``` + +pub use self::implementation::*; + +#[cfg_attr(esp32, path = "esp32.rs")] +#[cfg_attr(riscv, path = "riscv.rs")] +#[cfg_attr(any(esp32s2, esp32s3), path = "xtensa.rs")] +mod implementation; + +mod private { + pub trait Sealed {} +} + +/// The attenuation of the ADC pin. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Attenuation { + /// 0dB attenuation, measurement range: 0-800mV + Attenuation0dB = 0b00, + /// 2.5dB attenuation, measurement range: 0-1100mV + #[cfg(not(esp32c2))] + Attenuation2p5dB = 0b01, + /// 6dB attenuation, measurement range: 0-1350mV + #[cfg(not(esp32c2))] + Attenuation6dB = 0b10, + /// 11dB attenuation, measurement range: 0-2600mV + Attenuation11dB = 0b11, +} + +/// Calibration source of the ADC. +#[cfg(not(esp32))] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AdcCalSource { + Gnd, + Ref, +} + +/// A helper trait to get the ADC channel of a compatible GPIO pin. +pub trait AdcChannel { + const CHANNEL: u8; +} + +/// A trait abstracting over calibration methods. +/// +/// The methods in this trait are mostly for internal use. To get +/// calibrated ADC reads, all you need to do is call `enable_pin_with_cal` +/// and specify some implementor of this trait. +pub trait AdcCalScheme: Sized + private::Sealed { + /// Create a new calibration scheme for the given attenuation. + fn new_cal(atten: Attenuation) -> Self; + + /// Return the basic ADC bias value. See [`AdcCalBasic`] for + /// details. + fn adc_cal(&self) -> u16 { + 0 + } + + /// Convert ADC value + fn adc_val(&self, val: u16) -> u16 { + val + } +} + +impl private::Sealed for () {} + +impl AdcCalScheme for () { + fn new_cal(_atten: Attenuation) -> Self { + () + } +} + +/// A helper trait to get access to ADC calibration efuses. +trait AdcCalEfuse { + /// Get ADC calibration init code + /// + /// Returns digital value for zero voltage for a given attenuation + fn get_init_code(atten: Attenuation) -> Option; + + /// Get ADC calibration reference point voltage + /// + /// Returns reference voltage (millivolts) for a given attenuation + fn get_cal_mv(atten: Attenuation) -> u16; + + /// Get ADC calibration reference point digital value + /// + /// Returns digital value for reference voltage for a given attenuation + fn get_cal_code(atten: Attenuation) -> Option; +} diff --git a/esp-hal-common/src/analog/adc/riscv.rs b/esp-hal-common/src/analog/adc/riscv.rs index 60c2c7782..7d5ba1aa0 100644 --- a/esp-hal-common/src/analog/adc/riscv.rs +++ b/esp-hal-common/src/analog/adc/riscv.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; -use embedded_hal::adc::{Channel, OneShot}; - -pub use crate::analog::ADC1; -#[cfg(esp32c3)] -pub use crate::analog::ADC2; +pub use self::calibration::*; +use super::{AdcCalEfuse, AdcCalScheme, AdcCalSource, AdcChannel, Attenuation}; #[cfg(any(esp32c6, esp32h2))] use crate::clock::clocks_ll::regi2c_write_mask; #[cfg(any(esp32c2, esp32c3, esp32c6))] @@ -15,21 +12,7 @@ use crate::{ system::{Peripheral, PeripheralClockControl}, }; -#[cfg(any(esp32c2, esp32c3, esp32c6))] -mod cal_basic; -#[cfg(any(esp32c3, esp32c6))] -mod cal_curve; -#[cfg(any(esp32c2, esp32c3, esp32c6))] -mod cal_line; - -#[cfg(any(esp32c2, esp32c3, esp32c6))] -pub use cal_basic::AdcCalBasic; -#[cfg(any(esp32c3, esp32c6))] -pub use cal_curve::{AdcCalCurve, AdcHasCurveCal}; -#[cfg(any(esp32c2, esp32c3, esp32c6))] -pub use cal_line::{AdcCalLine, AdcHasLineCal}; - -pub use crate::analog::{AdcCalEfuse, AdcCalScheme}; +mod calibration; // polyfill for c2 and c3 #[cfg(any(esp32c2, esp32c3))] @@ -118,48 +101,22 @@ cfg_if::cfg_if! { } } -/// The sampling/readout resolution of the ADC +/// The sampling/readout resolution of the ADC. #[derive(PartialEq, Eq, Clone, Copy)] pub enum Resolution { Resolution12Bit, } -/// The attenuation of the ADC pin -#[derive(PartialEq, Eq, Clone, Copy)] -pub enum Attenuation { - /// 0 dB attenuation, measurement range: 0 - 800 mV - Attenuation0dB = 0b00, - /// 2.5 dB attenuation, measurement range: 0 - 1100 mV - #[cfg(not(esp32c2))] - Attenuation2p5dB = 0b01, - /// 6 dB attenuation, measurement range: 0 - 1350 mV - #[cfg(not(esp32c2))] - Attenuation6dB = 0b10, - /// 11 dB attenuation, measurement range: 0 - 2600 mV - Attenuation11dB = 0b11, -} - -impl Attenuation { - /// List of all supported attenuations - pub const ALL: &'static [Attenuation] = &[ - Attenuation::Attenuation0dB, - #[cfg(not(esp32c2))] - Attenuation::Attenuation2p5dB, - #[cfg(not(esp32c2))] - Attenuation::Attenuation6dB, - Attenuation::Attenuation11dB, - ]; -} - +/// An I/O pin which can be read using the ADC. pub struct AdcPin { pub pin: PIN, pub cal_scheme: CS, _phantom: PhantomData, } -impl Channel for AdcPin +impl embedded_hal::adc::Channel for AdcPin where - PIN: Channel, + PIN: embedded_hal::adc::Channel, { type ID = u8; @@ -168,6 +125,7 @@ where } } +/// Configuration for the ADC. pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; NUM_ATTENS], @@ -184,9 +142,9 @@ where pub fn enable_pin(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin where - PIN: Channel, + PIN: AdcChannel, { - self.attenuations[PIN::channel() as usize] = Some(attenuation); + self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { pin, @@ -202,10 +160,10 @@ where ) -> AdcPin where ADCI: CalibrationAccess, - PIN: Channel, + PIN: AdcChannel, CS: AdcCalScheme, { - self.attenuations[PIN::channel() as usize] = Some(attenuation); + self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { pin, @@ -268,12 +226,6 @@ impl Default for AdcConfig { } } -#[derive(Clone, Copy)] -pub enum AdcCalSource { - Gnd, - Ref, -} - #[doc(hidden)] pub trait RegisterAccess { /// Configure onetime sampling parameters @@ -295,6 +247,7 @@ pub trait RegisterAccess { fn set_init_code(data: u16); } +#[doc(hidden)] pub trait CalibrationAccess: RegisterAccess { const ADC_CAL_CNT_MAX: u16; const ADC_CAL_CHANNEL: u16; @@ -306,7 +259,7 @@ pub trait CalibrationAccess: RegisterAccess { fn connect_cal(source: AdcCalSource, enable: bool); } -impl RegisterAccess for ADC1 { +impl RegisterAccess for crate::peripherals::ADC1 { fn config_onetime_sample(channel: u8, attenuation: u8) { let sar_adc = unsafe { &*APB_SARADC::PTR }; @@ -376,7 +329,7 @@ impl RegisterAccess for ADC1 { } } -impl CalibrationAccess for ADC1 { +impl CalibrationAccess for crate::peripherals::ADC1 { const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX; const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL; const ADC_VAL_MASK: u16 = ADC_VAL_MASK; @@ -417,7 +370,7 @@ impl CalibrationAccess for ADC1 { } #[cfg(esp32c3)] -impl RegisterAccess for ADC2 { +impl RegisterAccess for crate::peripherals::ADC2 { fn config_onetime_sample(channel: u8, attenuation: u8) { let sar_adc = unsafe { &*APB_SARADC::PTR }; @@ -486,7 +439,7 @@ impl RegisterAccess for ADC2 { } #[cfg(esp32c3)] -impl CalibrationAccess for ADC2 { +impl CalibrationAccess for crate::peripherals::ADC2 { const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX; const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL; const ADC_VAL_MASK: u16 = ADC_VAL_MASK; @@ -526,6 +479,7 @@ impl CalibrationAccess for ADC2 { } } +/// Analog-to-Digital Converter peripheral driver. pub struct ADC<'d, ADCI> { _adc: PeripheralRef<'d, ADCI>, attenuations: [Option; NUM_ATTENS], @@ -564,7 +518,7 @@ where } #[cfg(any(esp32c2, esp32c3, esp32c6))] -impl AdcCalEfuse for ADC1 { +impl AdcCalEfuse for crate::peripherals::ADC1 { fn get_init_code(atten: Attenuation) -> Option { Efuse::get_rtc_calib_init_code(1, atten) } @@ -579,7 +533,7 @@ impl AdcCalEfuse for ADC1 { } #[cfg(esp32c3)] -impl AdcCalEfuse for ADC2 { +impl AdcCalEfuse for crate::peripherals::ADC2 { fn get_init_code(atten: Attenuation) -> Option { Efuse::get_rtc_calib_init_code(2, atten) } @@ -593,15 +547,18 @@ impl AdcCalEfuse for ADC2 { } } -impl<'d, ADCI, PIN, CS> OneShot> for ADC<'d, ADCI> +impl<'d, ADCI, PIN, CS> embedded_hal::adc::OneShot> + for ADC<'d, ADCI> where - PIN: Channel, + PIN: embedded_hal::adc::Channel, ADCI: RegisterAccess, CS: AdcCalScheme, { type Error = (); fn read(&mut self, pin: &mut AdcPin) -> nb::Result { + use embedded_hal::adc::Channel; + if self.attenuations[AdcPin::::channel() as usize] == None { panic!( "Channel {} is not configured reading!", @@ -676,8 +633,11 @@ macro_rules! impl_adc_interface { ($adc:ident [ $( ($pin:ident, $channel:expr) ,)+ ]) => { - $( + impl $crate::analog::adc::AdcChannel for crate::gpio::$pin { + const CHANNEL: u8 = $channel; + } + impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin { type ID = u8; @@ -689,38 +649,7 @@ macro_rules! impl_adc_interface { #[cfg(esp32c2)] mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-C2: `ADC1`. - //! - //! ## Example - //! #### ADC on Risc-V architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.APB_SARADC.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); - //! println!("PIN2 ADC reading = {}", pin_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::ADC1; + use crate::peripherals::ADC1; impl_adc_interface! { ADC1 [ @@ -735,39 +664,7 @@ mod implementation { #[cfg(esp32c3)] mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-C3: `ADC1` and - //! `ADC2`. - //! - //! ## Example - //! #### ADC on Risc-V architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.APB_SARADC.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); - //! println!("PIN2 ADC reading = {}", pin_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::{ADC1, ADC2}; + use crate::peripherals::{ADC1, ADC2}; impl_adc_interface! { ADC1 [ @@ -788,38 +685,7 @@ mod implementation { #[cfg(esp32c6)] mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-C6: `ADC1`. - //! - //! ## Example - //! #### ADC on Risc-V architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.APB_SARADC.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); - //! println!("PIN2 ADC reading = {}", pin_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::ADC1; + use crate::peripherals::ADC1; impl_adc_interface! { ADC1 [ @@ -836,38 +702,7 @@ mod implementation { #[cfg(esp32h2)] mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-H2: `ADC1`. - //! - //! ## Example - //! #### ADC on Risc-V architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.APB_SARADC.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); - //! println!("PIN2 ADC reading = {}", pin_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::ADC1; + use crate::peripherals::ADC1; impl_adc_interface! { ADC1 [ diff --git a/esp-hal-common/src/analog/adc/xtensa.rs b/esp-hal-common/src/analog/adc/xtensa.rs index 50aa139de..f279813f7 100644 --- a/esp-hal-common/src/analog/adc/xtensa.rs +++ b/esp-hal-common/src/analog/adc/xtensa.rs @@ -1,8 +1,9 @@ use core::marker::PhantomData; -use embedded_hal::adc::{Channel, OneShot}; - -pub use crate::analog::{ADC1, ADC2}; +pub use self::calibration::*; +#[cfg(esp32s3)] +use super::AdcCalEfuse; +use super::{AdcCalScheme, AdcCalSource, AdcChannel, Attenuation}; #[cfg(esp32s3)] use crate::efuse::Efuse; use crate::{ @@ -10,21 +11,7 @@ use crate::{ peripherals::{APB_SARADC, SENS}, }; -#[cfg(esp32s3)] -mod cal_basic; -#[cfg(esp32s3)] -mod cal_curve; -#[cfg(esp32s3)] -mod cal_line; - -#[cfg(esp32s3)] -pub use cal_basic::AdcCalBasic; -#[cfg(esp32s3)] -pub use cal_curve::{AdcCalCurve, AdcHasCurveCal}; -#[cfg(esp32s3)] -pub use cal_line::{AdcCalLine, AdcHasLineCal}; - -pub use crate::analog::{AdcCalEfuse, AdcCalScheme}; +mod calibration; // Constants taken from: // https://github.com/espressif/esp-idf/blob/903af13e8/components/soc/esp32s2/include/soc/regi2c_saradc.h @@ -85,44 +72,22 @@ cfg_if::cfg_if! { } } -/// The sampling/readout resolution of the ADC +/// The sampling/readout resolution of the ADC. #[derive(PartialEq, Eq, Clone, Copy)] pub enum Resolution { Resolution13Bit, } -/// The attenuation of the ADC pin -#[derive(PartialEq, Eq, Clone, Copy)] -pub enum Attenuation { - /// 0 dB attenuation, measurement range: 0 - 800 mV - Attenuation0dB = 0b00, - /// 2.5 dB attenuation, measurement range: 0 - 1100 mV - Attenuation2p5dB = 0b01, - /// 6 dB attenuation, measurement range: 0 - 1350 mV - Attenuation6dB = 0b10, - /// 11 dB attenuation, measurement range: 0 - 2600 mV - Attenuation11dB = 0b11, -} - -impl Attenuation { - /// List of all supported attenuations - pub const ALL: &'static [Attenuation] = &[ - Attenuation::Attenuation0dB, - Attenuation::Attenuation2p5dB, - Attenuation::Attenuation6dB, - Attenuation::Attenuation11dB, - ]; -} - +/// An I/O pin which can be read using the ADC. pub struct AdcPin { pub pin: PIN, pub cal_scheme: CS, _phantom: PhantomData, } -impl Channel for AdcPin +impl embedded_hal::adc::Channel for AdcPin where - PIN: Channel, + PIN: embedded_hal::adc::Channel, { type ID = u8; @@ -131,6 +96,7 @@ where } } +/// Configuration for the ADC. pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; 10], @@ -147,9 +113,9 @@ where pub fn enable_pin(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin where - PIN: Channel, + PIN: AdcChannel, { - self.attenuations[PIN::channel() as usize] = Some(attenuation); + self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { pin, @@ -165,10 +131,10 @@ where ) -> AdcPin where ADCI: CalibrationAccess, - PIN: Channel, + PIN: AdcChannel, CS: AdcCalScheme, { - self.attenuations[PIN::channel() as usize] = Some(attenuation); + self.attenuations[PIN::CHANNEL as usize] = Some(attenuation); AdcPin { pin, @@ -233,12 +199,6 @@ impl Default for AdcConfig { } } -#[derive(Clone, Copy)] -pub enum AdcCalSource { - Gnd, - Ref, -} - #[doc(hidden)] pub trait RegisterAccess { fn adc_samplecfg(channel: u16); @@ -270,6 +230,7 @@ pub trait RegisterAccess { fn reset(); } +#[doc(hidden)] pub trait CalibrationAccess: RegisterAccess { const ADC_CAL_CNT_MAX: u16; const ADC_CAL_CHANNEL: u16; @@ -281,7 +242,7 @@ pub trait CalibrationAccess: RegisterAccess { fn connect_cal(source: AdcCalSource, enable: bool); } -impl RegisterAccess for ADC1 { +impl RegisterAccess for crate::peripherals::ADC1 { fn adc_samplecfg(channel: u16) { let sensors = unsafe { &*SENS::ptr() }; @@ -395,7 +356,7 @@ impl RegisterAccess for ADC1 { } #[cfg(esp32s3)] -impl CalibrationAccess for ADC1 { +impl CalibrationAccess for crate::peripherals::ADC1 { const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX; const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL; const ADC_VAL_MASK: u16 = ADC_VAL_MASK; @@ -416,7 +377,7 @@ impl CalibrationAccess for ADC1 { } } -impl RegisterAccess for ADC2 { +impl RegisterAccess for crate::peripherals::ADC2 { fn adc_samplecfg(channel: u16) { let sensors = unsafe { &*SENS::ptr() }; @@ -531,7 +492,7 @@ impl RegisterAccess for ADC2 { } #[cfg(esp32s3)] -impl CalibrationAccess for ADC2 { +impl CalibrationAccess for crate::peripherals::ADC2 { const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX; const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL; const ADC_VAL_MASK: u16 = ADC_VAL_MASK; @@ -552,6 +513,7 @@ impl CalibrationAccess for ADC2 { } } +/// Analog-to-Digital Converter peripheral driver. pub struct ADC<'d, ADC> { _adc: PeripheralRef<'d, ADC>, attenuations: [Option; 10], @@ -641,7 +603,7 @@ where } #[cfg(esp32s3)] -impl AdcCalEfuse for ADC1 { +impl AdcCalEfuse for crate::peripherals::ADC1 { fn get_init_code(atten: Attenuation) -> Option { Efuse::get_rtc_calib_init_code(1, atten) } @@ -656,7 +618,7 @@ impl AdcCalEfuse for ADC1 { } #[cfg(esp32s3)] -impl AdcCalEfuse for ADC2 { +impl AdcCalEfuse for crate::peripherals::ADC2 { fn get_init_code(atten: Attenuation) -> Option { Efuse::get_rtc_calib_init_code(2, atten) } @@ -670,15 +632,18 @@ impl AdcCalEfuse for ADC2 { } } -impl<'d, ADCI, PIN, CS> OneShot> for ADC<'d, ADCI> +impl<'d, ADCI, PIN, CS> embedded_hal::adc::OneShot> + for ADC<'d, ADCI> where - PIN: Channel, + PIN: embedded_hal::adc::Channel, ADCI: RegisterAccess, CS: AdcCalScheme, { type Error = (); fn read(&mut self, pin: &mut AdcPin) -> nb::Result { + use embedded_hal::adc::Channel; + if self.attenuations[AdcPin::::channel() as usize] == None { panic!( "Channel {} is not configured reading!", @@ -732,6 +697,10 @@ macro_rules! impl_adc_interface { ]) => { $( + impl $crate::analog::adc::AdcChannel for crate::gpio::$pin { + const CHANNEL: u8 = $channel; + } + impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin { type ID = u8; @@ -741,125 +710,21 @@ macro_rules! impl_adc_interface { } } -pub use implementation::*; - -#[cfg(esp32s3)] mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-S3: `ADC1` and - //! `ADC2`. - //! - //! ## Example - //! #### ADC on Xtensa architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.SENS.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin3 = - //! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap(); - //! println!("PIN3 ADC reading = {}", pin3_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::{ADC1, ADC2}; + use crate::peripherals::{ADC1, ADC2}; impl_adc_interface! { ADC1 [ - (Gpio1, 0), - (Gpio2, 1), - (Gpio3, 2), - (Gpio4, 3), - (Gpio5, 4), - (Gpio6, 5), - (Gpio7, 6), - (Gpio8, 7), - (Gpio9, 8), - (Gpio10,9), - ] - } - - impl_adc_interface! { - ADC2 [ - (Gpio11, 0), - (Gpio12, 1), - (Gpio13, 2), - (Gpio14, 3), - (Gpio15, 4), - (Gpio16, 5), - (Gpio17, 6), - (Gpio18, 7), - (Gpio19, 8), - (Gpio20, 9), - ] - } -} - -#[cfg(esp32s2)] -mod implementation { - //! # Analog to digital (ADC) conversion support. - //! - //! ## Overview - //! The `ADC` module in the `analog` driver enables users to perform - //! analog-to-digital conversions, allowing them to measure real-world - //! analog signals with high accuracy. - //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-S2: `ADC1` and - //! `ADC2`. - //! - //! ## Example - //! #### ADC on Xtensa architecture - //! ```no_run - //! // Create ADC instances - //! let analog = peripherals.SENS.split(); - //! - //! let mut adc1_config = AdcConfig::new(); - //! - //! let mut pin3 = - //! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); - //! - //! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); - //! - //! let mut delay = Delay::new(&clocks); - //! - //! loop { - //! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap(); - //! println!("PIN3 ADC reading = {}", pin3_value); - //! delay.delay_ms(1500u32); - //! } - //! ``` - - use crate::analog::{ADC1, ADC2}; - - impl_adc_interface! { - ADC1 [ - (Gpio1, 0), - (Gpio2, 1), - (Gpio3, 2), - (Gpio4, 3), - (Gpio5, 4), - (Gpio6, 5), - (Gpio7, 6), - (Gpio8, 7), - (Gpio9, 8), - (Gpio10,9), + (Gpio1, 0), + (Gpio2, 1), + (Gpio3, 2), + (Gpio4, 3), + (Gpio5, 4), + (Gpio6, 5), + (Gpio7, 6), + (Gpio8, 7), + (Gpio9, 8), + (Gpio10, 9), ] } diff --git a/esp-hal-common/src/analog/dac.rs b/esp-hal-common/src/analog/dac.rs index bb579df89..e7ff5492f 100644 --- a/esp-hal-common/src/analog/dac.rs +++ b/esp-hal-common/src/analog/dac.rs @@ -1,159 +1,127 @@ -//! # Analog peripherals - Digital to Analog Converter +//! # Digital to Analog Converter (DAC) //! -//! ## Overview -//! The `DAC` module is part of the `Analog` driver designed for ESP -//! microcontrollers, providing functionalities for `digital-to-analog` -//! conversion. +//! The `dac` module enables users to generate analog output signals with +//! precise control over voltage levels using one of the onboard +//! digital-to-analog converters (DAC). //! -//! This module simplifies digital-to-analog conversion on ESP microcontrollers, -//! enabling precise control over analog output signals. Developers can choose -//! the `DAC` channel they want to use based on the GPIO pin assignments for -//! each channel. By providing a unified interface for DAC control, the module -//! makes it easier for users to generate accurate analog voltages in their -//! applications, such as audio generation, sensor calibration, and analog -//! signal synthesis. -use crate::peripherals::{RTC_IO, SENS}; -pub trait DAC { - fn write(&mut self, value: u8); +//! Two 8-bit DAC channels are available. Each DAC channel can convert the +//! digital value 0-255 to the analog voltage 0-3.3v. Developers can choose the +//! DAC channel they want to use based on the GPIO pin assignments for each +//! channel. +//! +//! ## Example +//! +//! ```no_run +//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); +//! let gpio25 = io.pins.gpio25.into_analog(); +//! let gpio26 = io.pins.gpio26.into_analog(); +//! +//! let mut dac1 = DAC1::new(peripherals.DAC1, gpio25); +//! let mut dac2 = DAC2::new(peripherals.DAC2, gpio26); +//! +//! let mut delay = Delay::new(&clocks); +//! +//! let mut voltage_dac1 = 200u8; +//! let mut voltage_dac2 = 255u8; +//! +//! // Change voltage on the pins using write function: +//! loop { +//! voltage_dac1 = voltage_dac1.wrapping_add(1); +//! dac1.write(voltage_dac1); +//! +//! voltage_dac2 = voltage_dac2.wrapping_sub(1); +//! dac2.write(voltage_dac2); +//! +//! delay.delay_ms(50u32); +//! } +//! ``` + +use crate::{ + gpio, + peripheral::{Peripheral, PeripheralRef}, + peripherals, +}; + +cfg_if::cfg_if! { + if #[cfg(esp32)] { + type Dac1Gpio = gpio::Gpio25; + type Dac2Gpio = gpio::Gpio26; + } else if #[cfg(esp32s2)] { + type Dac1Gpio = gpio::Gpio17; + type Dac2Gpio = gpio::Gpio18; + } } -trait DAC1Impl { - fn set_power(self) -> Self - where - Self: Sized, - { +/// Digital-to-Analog Converter (DAC) Channel 1 +pub struct DAC1<'d> { + _inner: PeripheralRef<'d, peripherals::DAC1>, +} + +impl<'d> DAC1<'d> { + /// Constructs a new DAC instance. + pub fn new(dac: impl Peripheral

+ 'd, _pin: Dac1Gpio) -> Self { + crate::into_ref!(dac); + #[cfg(esp32s2)] - { - let sensors = unsafe { &*SENS::ptr() }; - sensors - .sar_dac_ctrl1() - .modify(|_, w| w.dac_clkgate_en().set_bit()); - } + unsafe { &*peripherals::SENS::PTR } + .sar_dac_ctrl1() + .modify(|_, w| w.dac_clkgate_en().set_bit()); - let rtcio = unsafe { &*RTC_IO::ptr() }; + unsafe { &*peripherals::RTC_IO::PTR } + .pad_dac1() + .modify(|_, w| w.pdac1_dac_xpd_force().set_bit().pdac1_xpd_dac().set_bit()); - rtcio.pad_dac1().modify(|_, w| { - w.pdac1_dac_xpd_force().set_bit(); - w.pdac1_xpd_dac().set_bit() - }); - - self + Self { _inner: dac } } - fn write(&mut self, value: u8) { - let rtcio = unsafe { &*RTC_IO::ptr() }; - - let sensors = unsafe { &*SENS::ptr() }; - sensors + /// Writes the given value. + /// + /// For each DAC channel, the output analog voltage can be calculated as + /// follows: DACn_OUT = VDD3P3_RTC * PDACn_DAC/256 + pub fn write(&mut self, value: u8) { + unsafe { &*crate::peripherals::SENS::PTR } .sar_dac_ctrl2() .modify(|_, w| w.dac_cw_en1().clear_bit()); - rtcio + unsafe { &*crate::peripherals::RTC_IO::PTR } .pad_dac1() .modify(|_, w| unsafe { w.pdac1_dac().bits(value) }); } } -trait DAC2Impl { - fn set_power(self) -> Self - where - Self: Sized, - { +/// Digital-to-Analog Converter (DAC) Channel 2 +pub struct DAC2<'d> { + _inner: PeripheralRef<'d, peripherals::DAC2>, +} + +impl<'d> DAC2<'d> { + /// Constructs a new DAC instance. + pub fn new(dac: impl Peripheral

+ 'd, _pin: Dac2Gpio) -> Self { + crate::into_ref!(dac); + #[cfg(esp32s2)] - { - let sensors = unsafe { &*SENS::ptr() }; - sensors - .sar_dac_ctrl1() - .modify(|_, w| w.dac_clkgate_en().set_bit()); - } + unsafe { &*peripherals::SENS::PTR } + .sar_dac_ctrl1() + .modify(|_, w| w.dac_clkgate_en().set_bit()); - let rtcio = unsafe { &*RTC_IO::ptr() }; + unsafe { &*peripherals::RTC_IO::PTR } + .pad_dac2() + .modify(|_, w| w.pdac2_dac_xpd_force().set_bit().pdac2_xpd_dac().set_bit()); - rtcio.pad_dac2().modify(|_, w| { - w.pdac2_dac_xpd_force().set_bit(); - w.pdac2_xpd_dac().set_bit() - }); - - self + Self { _inner: dac } } - fn write(&mut self, value: u8) { - let rtcio = unsafe { &*RTC_IO::ptr() }; - - let sensors = unsafe { &*SENS::ptr() }; - sensors + /// Writes the given value. + /// + /// For each DAC channel, the output analog voltage can be calculated as + /// follows: DACn_OUT = VDD3P3_RTC * PDACn_DAC/256 + pub fn write(&mut self, value: u8) { + unsafe { &*crate::peripherals::SENS::PTR } .sar_dac_ctrl2() .modify(|_, w| w.dac_cw_en2().clear_bit()); - rtcio + unsafe { &*crate::peripherals::RTC_IO::PTR } .pad_dac2() .modify(|_, w| unsafe { w.pdac2_dac().bits(value) }); } } - -macro_rules! impl_dac { - ($($number:literal => $gpio:ident),+) => { - $( - paste::paste! { - use $crate::analog::dac::[]; - - #[doc = "DAC channel " $number] - pub struct []<'d, DAC> { - _dac: $crate::peripheral::PeripheralRef<'d, DAC>, - _private: ::core::marker::PhantomData<()>, - } - - impl<'d, DAC> [] for []<'d, DAC> {} - - impl<'d, DAC> []<'d, DAC> { - /// Constructs a new DAC instance - pub fn dac( - dac: impl $crate::peripheral::Peripheral

+'d, - _pin: $crate::gpio::$gpio<$crate::gpio::Analog>, - ) -> Result { - let dac = Self { - _dac: dac.into_ref(), - _private: ::core::marker::PhantomData, - } - .set_power(); - Ok(dac) - } - - /// Writes the given value - /// - /// For each DAC channel, the output analog voltage can be calculated as follows: - /// DACn_OUT = VDD3P3_RTC * PDACn_DAC/256 - pub fn write(&mut self, value: u8) { - []::write(self, value) - } - } - } - )+ - }; -} - -pub use implementation::*; - -#[cfg(esp32)] -mod implementation { - //! Digital to analog (DAC) conversion. - //! - //! This module provides functions for controlling two digital to - //! analog converters, available on ESP32: `DAC1` and `DAC2`. - //! - //! The DAC1 is available on the GPIO pin 25, and DAC2 on pin 26. - - impl_dac!(1 => Gpio25, 2 => Gpio26); -} - -#[cfg(esp32s2)] -mod implementation { - //! Digital to analog (DAC) conversion. - //! - //! This module provides functions for controlling two digital to - //! analog converters, available on ESP32-S2: `DAC1` and `DAC2`. - //! - //! The DAC1 is available on the GPIO pin 17, and DAC2 on pin 18. - - impl_dac!(1 => Gpio17, 2 => Gpio18); -} diff --git a/esp-hal-common/src/analog/mod.rs b/esp-hal-common/src/analog/mod.rs index 73c3ce935..6508baabc 100644 --- a/esp-hal-common/src/analog/mod.rs +++ b/esp-hal-common/src/analog/mod.rs @@ -1,260 +1,10 @@ -//! # Analog peripherals +//! # Analog Peripherals //! -//! ## Overview -//! The `Analog` Driver is a module designed for ESP microcontrollers, that -//! provides an interface to interact with analog peripherals on the chip. The -//! module includes support for `Analog-to-Digital Converters (ADC)` and -//! `Digital-to-Analog Converters (DAC)`, offering functionality for precise -//! analog measurements and generating analog output signals. -//! -//! The `ADC` module in the `analog` driver enables users to perform -//! analog-to-digital conversions, allowing them to measure real-world analog -//! signals with high accuracy. The module provides access to multiple ADC -//! units, such as `ADC1` and `ADC2`, which may differ based on the specific ESP -//! microcontroller being used. -//! -//! The `DAC` module in the `analog` driver enables users to generate -//! analog output signals with precise control over voltage levels. The module -//! supports multiple DAC units, such as `DAC1` and `DAC2`, which may vary -//! depending on the specific ESP microcontroller. -//! -//! #### Xtensa architecture -//! For ESP microcontrollers using the `Xtensa` architecture, the driver -//! provides access to the `SENS` peripheral, allowing users to split it into -//! independent parts using the [`AnalogExt`] trait. This extension trait -//! provides access to the following analog peripherals: -//! * ADC1 -//! * ADC2 -//! * DAC1 -//! * DAC2 -//! -//! #### RISC-V architecture -//! For ESP microcontrollers using the `RISC-V` architecture, the driver -//! provides access to the `APB_SARADC` peripheral. The `AnalogExt` trait allows -//! users to split this peripheral into independent parts, providing access to -//! the following analog peripheral: -//! * ADC1 -//! * ADC2 -//! -//! ## Examples -//! #### ADC on Risc-V architecture -//! ```no_run -//! // Create ADC instances -//! let analog = peripherals.APB_SARADC.split(); -//! -//! let mut adc1_config = AdcConfig::new(); -//! -//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); -//! -//! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); -//! -//! let mut delay = Delay::new(&clocks); -//! -//! loop { -//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); -//! println!("PIN2 ADC reading = {}", pin_value); -//! delay.delay_ms(1500u32); -//! } -//! ``` -//! #### ADC on Xtensa architecture -//! ```no_run -//! // Create ADC instances -//! let analog = peripherals.SENS.split(); -//! -//! let mut adc1_config = AdcConfig::new(); -//! -//! let mut pin3 = -//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); -//! -//! let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); -//! -//! let mut delay = Delay::new(&clocks); -//! -//! loop { -//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap(); -//! println!("PIN3 ADC reading = {}", pin3_value); -//! delay.delay_ms(1500u32); -//! } -//! ``` +//! The `analog` module provides drivers for the various analog peripherals +//! available on the device. For more information about a peripheral driver, +//! please refer to the relevant module documentation. -#[cfg_attr(esp32, path = "adc/esp32.rs")] -#[cfg_attr(riscv, path = "adc/riscv.rs")] -#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")] +#[cfg(adc)] pub mod adc; #[cfg(dac)] pub mod dac; - -/// A trait abstracting over calibration methods. -/// -/// The methods in this trait are mostly for internal use. To get -/// calibrated ADC reads, all you need to do is call `enable_pin_with_cal` -/// and specify some implementor of this trait. -pub trait AdcCalScheme: Sized { - /// Create a new calibration scheme for the given attenuation. - fn new_cal(atten: adc::Attenuation) -> Self; - - /// Return the basic ADC bias value. See [`adc::AdcCalBasic`] for - /// details. - fn adc_cal(&self) -> u16 { - 0 - } - - /// Convert ADC value - fn adc_val(&self, val: u16) -> u16 { - val - } -} - -impl AdcCalScheme for () { - fn new_cal(_atten: adc::Attenuation) -> Self { - () - } -} - -/// A helper trait to get access to ADC calibration efuses -pub trait AdcCalEfuse { - /// Get ADC calibration init code - /// - /// Returns digital value for zero voltage for a given attenuation - fn get_init_code(atten: adc::Attenuation) -> Option; - - /// Get ADC calibration reference point voltage - /// - /// Returns reference voltage (millivolts) for a given attenuation - fn get_cal_mv(atten: adc::Attenuation) -> u16; - - /// Get ADC calibration reference point digital value - /// - /// Returns digital value for reference voltage for a given attenuation - fn get_cal_code(atten: adc::Attenuation) -> Option; -} - -pub struct ADC1 { - _private: (), -} - -pub struct ADC2 { - _private: (), -} - -pub struct DAC1 { - _private: (), -} - -pub struct DAC2 { - _private: (), -} - -impl core::ops::Deref for ADC1 { - type Target = ADC1; - - fn deref(&self) -> &Self::Target { - self - } -} - -impl core::ops::DerefMut for ADC1 { - fn deref_mut(&mut self) -> &mut Self::Target { - self - } -} - -impl crate::peripheral::Peripheral for ADC1 { - type P = ADC1; - #[inline] - unsafe fn clone_unchecked(&mut self) -> Self::P { - ADC1 { _private: () } - } -} - -impl crate::peripheral::sealed::Sealed for ADC1 {} - -impl crate::peripheral::Peripheral for ADC2 { - type P = ADC2; - #[inline] - unsafe fn clone_unchecked(&mut self) -> Self::P { - ADC2 { _private: () } - } -} - -impl crate::peripheral::sealed::Sealed for ADC2 {} - -impl crate::peripheral::Peripheral for DAC1 { - type P = DAC1; - #[inline] - unsafe fn clone_unchecked(&mut self) -> Self::P { - DAC1 { _private: () } - } -} - -impl crate::peripheral::sealed::Sealed for DAC1 {} - -impl crate::peripheral::Peripheral for DAC2 { - type P = DAC2; - - #[inline] - unsafe fn clone_unchecked(&mut self) -> Self::P { - DAC2 { _private: () } - } -} - -impl crate::peripheral::sealed::Sealed for DAC2 {} - -/// Extension trait to split a SENS peripheral in independent parts -pub trait AnalogExt { - fn split(self) -> AvailableAnalog; -} - -cfg_if::cfg_if! { - if #[cfg(xtensa)] { - pub struct AvailableAnalog { - pub adc1: ADC1, - pub adc2: ADC2, - pub dac1: DAC1, - pub dac2: DAC2, - } - - impl AnalogExt for crate::peripherals::SENS { - fn split(self) -> AvailableAnalog { - AvailableAnalog { - adc1: ADC1 { - _private: (), - }, - adc2: ADC2 { - _private: (), - }, - dac1: DAC1 { - _private: (), - }, - dac2: DAC2 { - _private: (), - }, - } - } - } - } -} - -cfg_if::cfg_if! { - if #[cfg(riscv)] { - pub struct AvailableAnalog { - pub adc1: ADC1, - #[cfg(esp32c3)] - pub adc2: ADC2, - } - - impl AnalogExt for crate::peripherals::APB_SARADC { - fn split(self) -> AvailableAnalog { - AvailableAnalog { - adc1: ADC1 { - _private: (), - }, - #[cfg(esp32c3)] - adc2: ADC2 { - _private: (), - }, - } - } - } - } -} diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 690b0981f..21b3a36b5 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -27,8 +27,6 @@ pub use fugit::{ }; pub use nb; -#[cfg(any(apb_saradc, sens))] -pub use crate::analog::AnalogExt as _esp_hal_analog_AnalogExt; #[cfg(any(dport, pcr, system))] pub use crate::clock::Clock as _esp_hal_clock_Clock; #[cfg(any(gdma, pdma))] diff --git a/esp-hal-common/src/soc/esp32/peripherals.rs b/esp-hal-common/src/soc/esp32/peripherals.rs index 743a979f1..dcbf8d6ef 100644 --- a/esp-hal-common/src/soc/esp32/peripherals.rs +++ b/esp-hal-common/src/soc/esp32/peripherals.rs @@ -20,9 +20,14 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, + ADC2 <= virtual, AES <= AES, APB_CTRL <= APB_CTRL, BB <= BB, + BT <= virtual, + DAC1 <= virtual, + DAC2 <= virtual, EFUSE <= EFUSE, FLASH_ENCRYPTION <= FLASH_ENCRYPTION, FRC_TIMER <= FRC_TIMER, @@ -39,6 +44,7 @@ crate::peripherals! { MCPWM1 <= MCPWM1, NRX <= NRX, PCNT <= PCNT, + PSRAM <= virtual, RMT <= RMT, RNG <= RNG, RSA <= RSA, @@ -46,7 +52,6 @@ crate::peripherals! { RTC_IO <= RTC_IO, RTC_I2C <= RTC_I2C, SDHOST <= SDHOST, - SENS <= SENS, SHA <= SHA, SLC <= SLC, SLCHOST <= SLCHOST, @@ -54,7 +59,6 @@ crate::peripherals! { SPI1 <= SPI1, SPI2 <= SPI2, SPI3 <= SPI3, - // SYSTEM is derived from DPORT: SYSTEM <= DPORT, TIMG0 <= TIMG0, TIMG1 <= TIMG1, @@ -64,9 +68,5 @@ crate::peripherals! { UART2 <= UART2, UHCI0 <= UHCI0, UHCI1 <= UHCI1, - - // Virtual peripherals: - BT <= virtual, - PSRAM <= virtual, WIFI <= virtual, } diff --git a/esp-hal-common/src/soc/esp32c2/peripherals.rs b/esp-hal-common/src/soc/esp32c2/peripherals.rs index ee13a4646..6b60c1318 100644 --- a/esp-hal-common/src/soc/esp32c2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c2/peripherals.rs @@ -20,9 +20,10 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, APB_CTRL <= APB_CTRL, - APB_SARADC <= APB_SARADC, ASSIST_DEBUG <= ASSIST_DEBUG, + BT <= virtual, DMA <= DMA, ECC <= ECC, EFUSE <= EFUSE, @@ -44,9 +45,6 @@ crate::peripherals! { TIMG0 <= TIMG0, UART0 <= UART0, UART1 <= UART1, - XTS_AES <= XTS_AES, - - // Virtual peripherals: - BT <= virtual, WIFI <= virtual, + XTS_AES <= XTS_AES, } diff --git a/esp-hal-common/src/soc/esp32c3/peripherals.rs b/esp-hal-common/src/soc/esp32c3/peripherals.rs index 6446609a9..0a744d6ae 100644 --- a/esp-hal-common/src/soc/esp32c3/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c3/peripherals.rs @@ -20,10 +20,12 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, + ADC2 <= virtual, AES <= AES, APB_CTRL <= APB_CTRL, - APB_SARADC <= APB_SARADC, ASSIST_DEBUG <= ASSIST_DEBUG, + BT <= virtual, DMA <= DMA, DS <= DS, EFUSE <= EFUSE, @@ -55,9 +57,6 @@ crate::peripherals! { UHCI0 <= UHCI0, UHCI1 <= UHCI1, USB_DEVICE <= USB_DEVICE, - XTS_AES <= XTS_AES, - - // Virtual peripherals: - BT <= virtual, WIFI <= virtual, + XTS_AES <= XTS_AES, } diff --git a/esp-hal-common/src/soc/esp32c6/peripherals.rs b/esp-hal-common/src/soc/esp32c6/peripherals.rs index fd7e41fa8..7f23ecae7 100644 --- a/esp-hal-common/src/soc/esp32c6/peripherals.rs +++ b/esp-hal-common/src/soc/esp32c6/peripherals.rs @@ -20,10 +20,11 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, AES <= AES, - APB_SARADC <= APB_SARADC, ASSIST_DEBUG <= ASSIST_DEBUG, ATOMIC <= ATOMIC, + BT <= virtual, DMA <= DMA, DS <= DS, ECC <= ECC, @@ -37,11 +38,13 @@ crate::peripherals! { HP_SYS <= HP_SYS, I2C0 <= I2C0, I2S0 <= I2S0, + IEEE802154 <= virtual, INTERRUPT_CORE0 <= INTERRUPT_CORE0, INTPRI <= INTPRI, IO_MUX <= IO_MUX, LEDC <= LEDC, LPWR <= LP_CLKRST, + LP_CORE <= virtual, LP_PERI <= LP_PERI, LP_ANA <= LP_ANA, LP_AON <= LP_AON, @@ -70,7 +73,6 @@ crate::peripherals! { SPI0 <= SPI0, SPI1 <= SPI1, SPI2 <= SPI2, - // SYSTEM is derived from PCR SYSTEM <= PCR, SYSTIMER <= SYSTIMER, TEE <= TEE, @@ -83,10 +85,5 @@ crate::peripherals! { UART1 <= UART1, UHCI0 <= UHCI0, USB_DEVICE <= USB_DEVICE, - - // Virtual peripherals: - BT <= virtual, - IEEE802154 <= virtual, - LP_CORE <= virtual, WIFI <= virtual, } diff --git a/esp-hal-common/src/soc/esp32h2/peripherals.rs b/esp-hal-common/src/soc/esp32h2/peripherals.rs index e40d9de3f..d9ce69e4c 100644 --- a/esp-hal-common/src/soc/esp32h2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32h2/peripherals.rs @@ -20,9 +20,10 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, AES <= AES, - APB_SARADC <= APB_SARADC, ASSIST_DEBUG <= ASSIST_DEBUG, + BT <= virtual, DMA <= DMA, DS <= DS, ECC <= ECC, @@ -35,6 +36,7 @@ crate::peripherals! { I2C0 <= I2C0, I2C1 <= I2C1, I2S0 <= I2S0, + IEEE802154 <= virtual, INTERRUPT_CORE0 <= INTERRUPT_CORE0, INTPRI <= INTPRI, IO_MUX <= IO_MUX, @@ -63,7 +65,6 @@ crate::peripherals! { SPI0 <= SPI0, SPI1 <= SPI1, SPI2 <= SPI2, - // SYSTEM is derived from PCR: SYSTEM <= PCR, SYSTIMER <= SYSTIMER, TEE <= TEE, @@ -75,8 +76,4 @@ crate::peripherals! { UART1 <= UART1, UHCI0 <= UHCI0, USB_DEVICE <= USB_DEVICE, - - // Virtual peripherals: - BT <= virtual, - IEEE802154 <= virtual, } diff --git a/esp-hal-common/src/soc/esp32s2/peripherals.rs b/esp-hal-common/src/soc/esp32s2/peripherals.rs index 5c5a7ef02..5e38be84b 100644 --- a/esp-hal-common/src/soc/esp32s2/peripherals.rs +++ b/esp-hal-common/src/soc/esp32s2/peripherals.rs @@ -20,8 +20,11 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, + ADC2 <= virtual, AES <= AES, - APB_SARADC <= APB_SARADC, + DAC1 <= virtual, + DAC2 <= virtual, DEDICATED_GPIO <= DEDICATED_GPIO, DS <= DS, EFUSE <= EFUSE, @@ -38,12 +41,12 @@ crate::peripherals! { LPWR <= RTC_CNTL, PCNT <= PCNT, PMS <= PMS, + PSRAM <= virtual, RMT <= RMT, RNG <= RNG, RSA <= RSA, RTC_IO <= RTC_IO, RTC_I2C <= RTC_I2C, - SENS <= SENS, SHA <= SHA, SPI0 <= SPI0, SPI1 <= SPI1, @@ -59,12 +62,9 @@ crate::peripherals! { UART0 <= UART0, UART1 <= UART1, UHCI0 <= UHCI0, + ULP_RISCV_CORE <= virtual, USB0 <= USB0, USB_WRAP <= USB_WRAP, - XTS_AES <= XTS_AES, - - // Virtual peripherals: - PSRAM <= virtual, - ULP_RISCV_CORE <= virtual, WIFI <= virtual, + XTS_AES <= XTS_AES, } diff --git a/esp-hal-common/src/soc/esp32s3/peripherals.rs b/esp-hal-common/src/soc/esp32s3/peripherals.rs index 52ef5534f..123f65708 100644 --- a/esp-hal-common/src/soc/esp32s3/peripherals.rs +++ b/esp-hal-common/src/soc/esp32s3/peripherals.rs @@ -20,10 +20,12 @@ pub(crate) use self::peripherals::*; // peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're // creating "virtual peripherals" for them. crate::peripherals! { + ADC1 <= virtual, + ADC2 <= virtual, AES <= AES, APB_CTRL <= APB_CTRL, - APB_SARADC <= APB_SARADC, ASSIST_DEBUG <= ASSIST_DEBUG, + BT <= virtual, DMA <= DMA, DS <= DS, EFUSE <= EFUSE, @@ -43,6 +45,7 @@ crate::peripherals! { LPWR <= RTC_CNTL, PCNT <= PCNT, PERI_BACKUP <= PERI_BACKUP, + PSRAM <= virtual, MCPWM0 <= MCPWM0, MCPWM1 <= MCPWM1, RMT <= RMT, @@ -50,7 +53,6 @@ crate::peripherals! { RSA <= RSA, RTC_I2C <= RTC_I2C, RTC_IO <= RTC_IO, - SENS <= SENS, SENSITIVE <= SENSITIVE, SHA <= SHA, SPI0 <= SPI0, @@ -67,15 +69,11 @@ crate::peripherals! { UART2 <= UART2, UHCI0 <= UHCI0, UHCI1 <= UHCI1, + ULP_RISCV_CORE <= virtual, USB0 <= USB0, USB_DEVICE <= USB_DEVICE, USB_WRAP <= USB_WRAP, WCL <= WCL, - XTS_AES <= XTS_AES, - - // Virtual peripherals: - BT <= virtual, - PSRAM <= virtual, - ULP_RISCV_CORE <= virtual, WIFI <= virtual, + XTS_AES <= XTS_AES, } diff --git a/esp32-hal/examples/adc.rs b/esp32-hal/examples/adc.rs index aa630552f..088de5a71 100644 --- a/esp32-hal/examples/adc.rs +++ b/esp32-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC2}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC2}, prelude::*, Delay, }; @@ -25,12 +25,10 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.SENS.split(); - let mut adc2_config = AdcConfig::new(); let mut pin25 = adc2_config.enable_pin(io.pins.gpio25.into_analog(), Attenuation::Attenuation11dB); - let mut adc2 = ADC::::adc(analog.adc2, adc2_config).unwrap(); + let mut adc2 = ADC::::adc(peripherals.ADC2, adc2_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32-hal/examples/dac.rs b/esp32-hal/examples/dac.rs index eec8c029d..71825ac69 100644 --- a/esp32-hal/examples/dac.rs +++ b/esp32-hal/examples/dac.rs @@ -5,7 +5,14 @@ #![no_std] #![no_main] -use esp32_hal::{clock::ClockControl, dac, gpio::IO, peripherals::Peripherals, prelude::*, Delay}; +use esp32_hal::{ + clock::ClockControl, + dac::{DAC1, DAC2}, + gpio::IO, + peripherals::Peripherals, + prelude::*, + Delay, +}; use esp_backtrace as _; #[entry] @@ -19,9 +26,8 @@ fn main() -> ! { let pin26 = io.pins.gpio26.into_analog(); // Create DAC instances - let analog = peripherals.SENS.split(); - let mut dac1 = dac::DAC1::dac(analog.dac1, pin25).unwrap(); - let mut dac2 = dac::DAC2::dac(analog.dac2, pin26).unwrap(); + let mut dac1 = DAC1::new(peripherals.DAC1, pin25); + let mut dac2 = DAC2::new(peripherals.DAC2, pin26); let mut delay = Delay::new(&clocks); diff --git a/esp32c2-hal/examples/adc.rs b/esp32c2-hal/examples/adc.rs index ad8e04069..ee2af6fe1 100644 --- a/esp32c2-hal/examples/adc.rs +++ b/esp32c2-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32c2_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,13 +25,9 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c2-hal/examples/adc_cal.rs b/esp32c2-hal/examples/adc_cal.rs index 23a52a8f8..05c2b584f 100644 --- a/esp32c2-hal/examples/adc_cal.rs +++ b/esp32c2-hal/examples/adc_cal.rs @@ -7,10 +7,10 @@ use esp32c2_hal::{ adc, - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -26,12 +26,6 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - - let mut adc1_config = AdcConfig::new(); - - let atten = Attenuation::Attenuation11dB; - // You can try any of the following calibration methods by uncommenting // them. Note that only AdcCalLine returns readings in mV; the other two // return raw readings in some unspecified scale. @@ -40,9 +34,12 @@ fn main() -> ! { // type AdcCal = adc::AdcCalBasic; type AdcCal = adc::AdcCalLine; - let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1_config = AdcConfig::new(); + let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>( + io.pins.gpio2.into_analog(), + Attenuation::Attenuation11dB, + ); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c3-hal/examples/adc.rs b/esp32c3-hal/examples/adc.rs index 5c42f58f5..e004ff4dc 100644 --- a/esp32c3-hal/examples/adc.rs +++ b/esp32c3-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32c3_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,13 +25,9 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c3-hal/examples/adc_cal.rs b/esp32c3-hal/examples/adc_cal.rs index 2558c455e..e83e128a4 100644 --- a/esp32c3-hal/examples/adc_cal.rs +++ b/esp32c3-hal/examples/adc_cal.rs @@ -7,10 +7,10 @@ use esp32c3_hal::{ adc, - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -26,12 +26,6 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - - let mut adc1_config = AdcConfig::new(); - - let atten = Attenuation::Attenuation11dB; - // You can try any of the following calibration methods by uncommenting them. // Note that only AdcCalLine and AdcCalCurve return readings in mV; the other // two return raw readings in some unspecified scale. @@ -41,9 +35,12 @@ fn main() -> ! { // type AdcCal = adc::AdcCalLine; type AdcCal = adc::AdcCalCurve; - let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1_config = AdcConfig::new(); + let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>( + io.pins.gpio2.into_analog(), + Attenuation::Attenuation11dB, + ); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c6-hal/examples/adc.rs b/esp32c6-hal/examples/adc.rs index f0db57cef..1c5c2229a 100644 --- a/esp32c6-hal/examples/adc.rs +++ b/esp32c6-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32c6_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,13 +25,9 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c6-hal/examples/adc_cal.rs b/esp32c6-hal/examples/adc_cal.rs index 55d6431e8..4d491a3b1 100644 --- a/esp32c6-hal/examples/adc_cal.rs +++ b/esp32c6-hal/examples/adc_cal.rs @@ -7,10 +7,10 @@ use esp32c6_hal::{ adc, - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -26,12 +26,6 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - - let mut adc1_config = AdcConfig::new(); - - let atten = Attenuation::Attenuation11dB; - // You can try any of the following calibration methods by uncommenting them. // Note that only AdcCalLine and AdcCalCurve return readings in mV; the other // two return raw readings in some unspecified scale. @@ -41,9 +35,12 @@ fn main() -> ! { // type AdcCal = adc::AdcCalLine; type AdcCal = adc::AdcCalCurve; - let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1_config = AdcConfig::new(); + let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>( + io.pins.gpio2.into_analog(), + Attenuation::Attenuation11dB, + ); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32h2-hal/examples/adc.rs b/esp32h2-hal/examples/adc.rs index c9b4c8b88..4c1a4e410 100644 --- a/esp32h2-hal/examples/adc.rs +++ b/esp32h2-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32h2_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,13 +25,9 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.APB_SARADC.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32s2-hal/examples/adc.rs b/esp32s2-hal/examples/adc.rs index eb5d1ac2f..cf960acb5 100644 --- a/esp32s2-hal/examples/adc.rs +++ b/esp32s2-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32s2_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,14 +25,10 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.SENS.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin3 = adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32s2-hal/examples/dac.rs b/esp32s2-hal/examples/dac.rs index 1f1874987..a179b01ee 100644 --- a/esp32s2-hal/examples/dac.rs +++ b/esp32s2-hal/examples/dac.rs @@ -7,7 +7,7 @@ use esp32s2_hal::{ clock::ClockControl, - dac, + dac::{DAC1, DAC2}, gpio::IO, peripherals::Peripherals, prelude::*, @@ -26,9 +26,8 @@ fn main() -> ! { let pin18 = io.pins.gpio18.into_analog(); // Create DAC instances - let analog = peripherals.SENS.split(); - let mut dac1 = dac::DAC1::dac(analog.dac1, pin17).unwrap(); - let mut dac2 = dac::DAC2::dac(analog.dac2, pin18).unwrap(); + let mut dac1 = DAC1::new(peripherals.DAC1, pin17); + let mut dac2 = DAC2::new(peripherals.DAC2, pin18); let mut delay = Delay::new(&clocks); diff --git a/esp32s3-hal/examples/adc.rs b/esp32s3-hal/examples/adc.rs index 8b6a19ec5..8423160b7 100644 --- a/esp32s3-hal/examples/adc.rs +++ b/esp32s3-hal/examples/adc.rs @@ -6,10 +6,10 @@ #![no_main] use esp32s3_hal::{ - adc::{AdcConfig, Attenuation, ADC, ADC1}, + adc::{AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,14 +25,10 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.SENS.split(); - let mut adc1_config = AdcConfig::new(); - let mut pin3 = adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32s3-hal/examples/adc_cal.rs b/esp32s3-hal/examples/adc_cal.rs index ba1ed35a5..6b9ca9a64 100644 --- a/esp32s3-hal/examples/adc_cal.rs +++ b/esp32s3-hal/examples/adc_cal.rs @@ -6,10 +6,10 @@ #![no_main] use esp32s3_hal::{ - adc::{self, AdcConfig, Attenuation, ADC, ADC1}, + adc::{self, AdcConfig, Attenuation, ADC}, clock::ClockControl, gpio::IO, - peripherals::Peripherals, + peripherals::{Peripherals, ADC1}, prelude::*, Delay, }; @@ -25,12 +25,6 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); // Create ADC instances - let analog = peripherals.SENS.split(); - - let mut adc1_config = AdcConfig::new(); - - let atten = Attenuation::Attenuation11dB; - // You can try any of the following calibration methods by uncommenting them. // Note that only AdcCalLine and AdcCalCurve return readings in mV; the other // two return raw readings in some unspecified scale. @@ -40,9 +34,12 @@ fn main() -> ! { // type AdcCal = adc::AdcCalLine; type AdcCal = adc::AdcCalCurve; - let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio3.into_analog(), atten); - - let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); + let mut adc1_config = AdcConfig::new(); + let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>( + io.pins.gpio3.into_analog(), + Attenuation::Attenuation11dB, + ); + let mut adc1 = ADC::::adc(peripherals.ADC1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks);