Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions esp-hal/src/analog/adc/calibration/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ pub struct AdcCalLine<ADCI> {
/// number with 16 fractional bits.
gain: u32,

#[cfg(esp32s2)]
offset: i32,

_phantom: PhantomData<ADCI>,
}

Expand All @@ -63,7 +66,7 @@ where
.map(|code| (code, ADCI::cal_mv(atten)))
.unwrap_or_else(|| {
// As a fallback try to calibrate using reference voltage source.
// This method is not too good because actual reference voltage may varies
// This method is not too good because actual reference voltage varies
// in range 1000..=1200 mV and this value currently cannot be read from efuse.
(
AdcConfig::<ADCI>::adc_calibrate(atten, AdcCalSource::Ref),
Expand All @@ -82,6 +85,8 @@ where
Self {
basic,
gain,
#[cfg(esp32s2)]
offset: ADCI::coeff_b(atten).unwrap_or(0),
_phantom: PhantomData,
}
}
Expand All @@ -93,12 +98,17 @@ where
fn adc_val(&self, val: u16) -> u16 {
let val = self.basic.adc_val(val);

(val as u32 * self.gain / GAIN_SCALE) as u16
let transformed = val as u32 * self.gain / GAIN_SCALE;

#[cfg(esp32s2)]
let transformed = { i32::max(transformed as i32 + self.offset, 0) };

transformed as u16
}
}

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))]
impl AdcHasLineCal for crate::peripherals::ADC1<'_> {}

#[cfg(any(esp32c3, esp32s3))]
#[cfg(any(esp32c3, esp32s2, esp32s3))]
impl AdcHasLineCal for crate::peripherals::ADC2<'_> {}
8 changes: 4 additions & 4 deletions esp-hal/src/analog/adc/calibration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))]
pub use self::basic::AdcCalBasic;
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
pub use self::curve::{AdcCalCurve, AdcHasCurveCal};
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))]
pub use self::line::{AdcCalLine, AdcHasLineCal};

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))]
mod basic;
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
mod curve;
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))]
mod line;
7 changes: 6 additions & 1 deletion esp-hal/src/analog/adc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl<ADCI> AdcCalScheme<ADCI> for () {
}

/// A helper trait to get access to ADC calibration efuses.
#[cfg(not(any(esp32, esp32s2)))]
#[cfg(not(any(esp32, esp32h2)))]
trait AdcCalEfuse {
/// Get ADC calibration init code
///
Expand All @@ -241,6 +241,11 @@ trait AdcCalEfuse {
///
/// Returns digital value for reference voltage for a given attenuation
fn cal_code(atten: Attenuation) -> Option<u16>;

#[cfg(esp32s2)]
/// Get the coeff_b from efuse.
/// Use in the equation: millivolts = coeff_a*adc + coeff_b
fn coeff_b(atten: Attenuation) -> Option<i32>;
}

macro_rules! impl_adc_interface {
Expand Down
33 changes: 22 additions & 11 deletions esp-hal/src/analog/adc/xtensa.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use core::marker::PhantomData;

#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
pub use self::calibration::*;
use super::{AdcCalScheme, AdcCalSource, AdcChannel, AdcConfig, AdcPin, Attenuation};
#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
use crate::efuse::Efuse;
use crate::{
peripherals::{APB_SARADC, SENS},
Expand All @@ -16,10 +16,10 @@ mod calibration;
pub(super) const NUM_ATTENS: usize = 10;

cfg_if::cfg_if! {
if #[cfg(esp32s3)] {
if #[cfg(any(esp32s2, esp32s3))] {
const ADC_VAL_MASK: u16 = 0xfff;
const ADC_CAL_CNT_MAX: u16 = 32;
const ADC_CAL_CHANNEL: u16 = 15;
const ADC_CAL_CHANNEL: u16 = 0;
}
}

Expand Down Expand Up @@ -61,7 +61,7 @@ where
// Trigger ADC sampling
ADCI::start_sample();

// Wait until ADC1 sampling is done
// Wait until ADCI sampling is done
while !ADCI::is_done() {}

let adc = ADCI::read_data() & ADCI::ADC_VAL_MASK;
Expand Down Expand Up @@ -193,14 +193,16 @@ impl RegisterAccess for crate::peripherals::ADC1<'_> {
}
}

#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
impl super::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;

fn enable_vdef(enable: bool) {
regi2c::ADC_SAR1_DREF.write_field(enable as u8);
// For enable value 4, see <https://github.com/espressif/esp-idf/blob/a25e7ab59ed197817d4a78e139220b2707481f67/components/hal/esp32s3/include/hal/adc_ll.h#L812>
// For disable value 1, see <https://github.com/espressif/esp-idf/blob/a25e7ab59ed197817d4a78e139220b2707481f67/components/bootloader_support/src/bootloader_random_esp32s2.c#L81>
regi2c::ADC_SAR1_DREF.write_field(if enable { 4 } else { 1 });
}

fn connect_cal(source: AdcCalSource, enable: bool) {
Expand Down Expand Up @@ -296,14 +298,14 @@ impl RegisterAccess for crate::peripherals::ADC2<'_> {
}
}

#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
impl super::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;

fn enable_vdef(enable: bool) {
regi2c::ADC_SAR2_DREF.write_field(enable as u8);
regi2c::ADC_SAR2_DREF.write_field(if enable { 4 } else { 1 });
}

fn connect_cal(source: AdcCalSource, enable: bool) {
Expand Down Expand Up @@ -395,6 +397,8 @@ where
.sar_amp_ctrl2()
.modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });

// TODO: ADC2 arbiter: https://github.com/espressif/esp-idf/blob/84df38aab927d50f7ee22d34516d7263f3e96068/components/hal/adc_oneshot_hal.c#L92

Adc {
_adc: adc_instance,
active_channel: None,
Expand Down Expand Up @@ -489,7 +493,7 @@ where
}
}

#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
fn init_code(atten: Attenuation) -> Option<u16> {
Efuse::rtc_calib_init_code(1, atten)
Expand All @@ -502,9 +506,13 @@ impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
fn cal_code(atten: Attenuation) -> Option<u16> {
Efuse::rtc_calib_cal_code(1, atten)
}

fn coeff_b(atten: Attenuation) -> Option<i32> {
Efuse::rtc_calib_coeff_b(1, atten)
}
}

#[cfg(esp32s3)]
#[cfg(any(esp32s2, esp32s3))]
impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
fn init_code(atten: Attenuation) -> Option<u16> {
Efuse::rtc_calib_init_code(2, atten)
Expand All @@ -517,6 +525,9 @@ impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
fn cal_code(atten: Attenuation) -> Option<u16> {
Efuse::rtc_calib_cal_code(2, atten)
}
fn coeff_b(atten: Attenuation) -> Option<i32> {
Efuse::rtc_calib_coeff_b(2, atten)
}
}

mod adc_implementation {
Expand Down
Loading
Loading