use core::marker::PhantomData;
use crate::analog::adc::{
AdcCalEfuse,
AdcCalLine,
AdcCalScheme,
AdcHasLineCal,
Attenuation,
CalibrationAccess,
};
const COEFF_MUL: i64 = 1 << 52;
type CurveCoeff = i64;
pub struct CurveCoeffs {
atten: Attenuation,
coeff: &'static [CurveCoeff],
}
type CurvesCoeffs = &'static [CurveCoeffs];
pub trait AdcHasCurveCal {
const CURVES_COEFFS: CurvesCoeffs;
}
#[derive(Clone, Copy)]
pub struct AdcCalCurve<ADCI> {
line: AdcCalLine<ADCI>,
coeff: &'static [CurveCoeff],
_phantom: PhantomData<ADCI>,
}
impl<ADCI> crate::private::Sealed for AdcCalCurve<ADCI> {}
impl<ADCI> AdcCalScheme<ADCI> for AdcCalCurve<ADCI>
where
ADCI: AdcCalEfuse + AdcHasLineCal + AdcHasCurveCal + CalibrationAccess,
{
fn new_cal(atten: Attenuation) -> Self {
let line = AdcCalLine::<ADCI>::new_cal(atten);
let coeff = ADCI::CURVES_COEFFS
.iter()
.find(|item| item.atten == atten)
.expect("No curve coefficients for given attenuation")
.coeff;
Self {
line,
coeff,
_phantom: PhantomData,
}
}
fn adc_cal(&self) -> u16 {
self.line.adc_cal()
}
fn adc_val(&self, val: u16) -> u16 {
let val = self.line.adc_val(val);
let err = if val == 0 || self.coeff.is_empty() {
0
} else {
let val_i64 = val as i64;
let mut poly = 0i64;
for &coeff in self.coeff.iter().rev() {
poly = poly * val_i64 + coeff;
}
(poly / COEFF_MUL) as i32
};
(val as i32 - err) as u16
}
}
macro_rules! coeff_tables {
($($(#[$($meta:meta)*])* $name:ident [ $($att:ident => [ $($val:literal,)* ],)* ];)*) => {
$(
$(#[$($meta)*])*
const $name: CurvesCoeffs = &[
$(CurveCoeffs {
atten: Attenuation::$att,
coeff: &[
$(($val as f64 * COEFF_MUL as f64) as CurveCoeff,)*
],
},)*
];
)*
};
}
#[cfg(any(esp32c3, esp32c5, esp32c6, esp32h2, esp32s3))]
mod impls {
use super::*;
impl AdcHasCurveCal for crate::peripherals::ADC1<'_> {
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
}
#[cfg(esp32c3)]
impl AdcHasCurveCal for crate::peripherals::ADC2<'_> {
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
}
#[cfg(esp32s3)]
impl AdcHasCurveCal for crate::peripherals::ADC2<'_> {
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2;
}
coeff_tables! {
#[cfg(esp32c3)]
CURVES_COEFFS1 [
_0dB => [
-0.225966470500043,
-0.0007265418501948,
0.0000109410402681,
],
_2p5dB => [
0.4229623392600516,
-0.0000731527490903,
0.0000088166562521,
],
_6dB => [
-1.017859239236435,
-0.0097159265299153,
0.0000149794028038,
],
_11dB => [
-1.4912262772850453,
-0.0228549975564099,
0.0000356391935717,
-0.0000000179964582,
0.0000000000042046,
],
];
#[cfg(esp32c5)]
CURVES_COEFFS1 [
_0dB => [
-0.2941017829027464,
0.0007368674918527,
0.0,
],
_2p5dB => [
-0.3224276125615327,
0.0005325658467636,
0.0,
],
_6dB => [
-0.3307554632960901,
0.000409244304226,
0.0,
],
_11dB => [
1.463642578413965,
-0.003349642363147,
0.0000011676836451,
],
];
#[cfg(esp32c6)]
CURVES_COEFFS1 [
_0dB => [
-0.0487166399931449,
0.0006436483033201,
0.0000030410131806,
],
_2p5dB => [
-0.8665498165817785,
0.0015239070452946,
0.0000013818878844,
],
_6dB => [
-1.2277821756674387,
0.0022275554717885,
0.0000005924302667,
],
_11dB => [
-0.3801417550380255,
-0.0006020352420772,
0.0000012442478488,
],
];
#[cfg(esp32h2)]
CURVES_COEFFS1 [
_0dB => [
-0.5081991760658888,
0.0000007858995319,
0,
],
_2p5dB => [
-0.8359230818901277,
0.0000009025419089,
0,
],
_6dB => [
-1.165668771581976,
0.0000008294679249,
0,
],
_11dB => [
-0.3637329628677273,
-0.0000196072597389,
0.0000007871689227,
],
];
#[cfg(esp32s3)]
CURVES_COEFFS1 [
_0dB => [
-2.7856531419538344,
-0.0050871540569528,
0.0000097982495890,
],
_2p5dB => [
-2.9831022915028695,
-0.0049393185868806,
0.0000101379430548,
],
_6dB => [
-2.3285545746296417,
-0.0147640181047414,
0.0000208385525314,
],
_11dB => [
-0.644403418269478,
-0.0644334888647536,
0.0001297891447611,
-0.0000000707697180,
0.0000000000135150,
],
];
#[cfg(esp32s3)]
CURVES_COEFFS2 [
_0dB => [
-2.5668651654328927,
0.0001353548869615,
0.0000036615265189,
],
_2p5dB => [
-2.3690184690298404,
-0.0066319894226185,
0.0000118964995959,
],
_6dB => [
-0.9452499397020617,
-0.0200996773954387,
0.00000259011467956,
],
_11dB => [
1.2247719764336924,
-0.0755717904943462,
0.0001478791187119,
-0.0000000796725280,
0.0000000000150380,
],
];
}
}