This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/esp-hal/src/analog/adc/calibration/curve.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

253 lines
7.5 KiB
Rust

use core::marker::PhantomData;
use crate::analog::adc::{
AdcCalEfuse,
AdcCalLine,
AdcCalScheme,
AdcHasLineCal,
Attenuation,
CalibrationAccess,
};
const COEFF_MUL: i64 = 1 << 52;
/// Integer type for the error polynomial's coefficients. Despite
/// the type, this is a fixed-point number with 52 fractional bits.
type CurveCoeff = i64;
/// Polynomial coefficients for specified attenuation.
pub struct CurveCoeffs {
/// Attenuation
atten: Attenuation,
/// Polynomial coefficients
coeff: &'static [CurveCoeff],
}
type CurvesCoeffs = &'static [CurveCoeffs];
/// Marker trait for ADC which support curve fitting
///
/// See also [`AdcCalCurve`].
pub trait AdcHasCurveCal {
/// Coefficients for calculating the reading voltage error.
///
/// A sets of coefficients for each attenuation.
const CURVES_COEFFS: CurvesCoeffs;
}
/// Curve fitting ADC calibration scheme
///
/// This scheme implements polynomial error correction using predefined
/// coefficient sets for each attenuation. It returns readings in mV.
///
/// This scheme also includes basic calibration ([`super::AdcCalBasic`]) and
/// line fitting ([`AdcCalLine`]).
#[derive(Clone, Copy)]
pub struct AdcCalCurve<ADCI> {
line: AdcCalLine<ADCI>,
/// Coefficients of the error estimation polynomial.
///
/// The constant coefficient comes first; the error polynomial is
/// `coeff[0] + coeff[1] * x + ... + coeff[n] * x^n`.
///
/// This calibration works by first applying linear calibration. Then
/// the error polynomial is applied to the output of linear calibration.
/// The output of the polynomial is our estimate of the error; it gets
/// subtracted from linear calibration's output to get the final reading.
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 {
0
} else {
// err = coeff[0] + coeff[1] * val + coeff[2] * val^2 + ... + coeff[n] * val^n
let mut var = 1i64;
let mut err = (var * self.coeff[0] / COEFF_MUL) as i32;
for coeff in &self.coeff[1..] {
var *= val as i64;
err += (var * *coeff / COEFF_MUL) as i32;
}
err
};
(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, esp32c6, 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! {
/// Error curve coefficients derived from <https://github.com/espressif/esp-idf/blob/903af13e8/components/esp_adc/esp32c3/curve_fitting_coefficients.c>
#[cfg(esp32c3)]
CURVES_COEFFS1 [
Attenuation0dB => [
-0.225966470500043,
-0.0007265418501948,
0.0000109410402681,
],
Attenuation2p5dB => [
0.4229623392600516,
-0.0000731527490903,
0.0000088166562521,
],
Attenuation6dB => [
-1.017859239236435,
-0.0097159265299153,
0.0000149794028038,
],
Attenuation11dB => [
-1.4912262772850453,
-0.0228549975564099,
0.0000356391935717,
-0.0000000179964582,
0.0000000000042046,
],
];
/// Error curve coefficients derived from <https://github.com/espressif/esp-idf/blob/903af13e8/components/esp_adc/esp32c6/curve_fitting_coefficients.c>
#[cfg(esp32c6)]
CURVES_COEFFS1 [
Attenuation0dB => [
-0.0487166399931449,
0.0006436483033201,
0.0000030410131806,
],
Attenuation2p5dB => [
-0.8665498165817785,
0.0015239070452946,
0.0000013818878844,
],
Attenuation6dB => [
-1.2277821756674387,
0.0022275554717885,
0.0000005924302667,
],
Attenuation11dB => [
-0.3801417550380255,
-0.0006020352420772,
0.0000012442478488,
],
];
/// Error curve coefficients derived from <https://github.com/espressif/esp-idf/blob/903af13e8/components/esp_adc/esp32s3/curve_fitting_coefficients.c>
#[cfg(esp32s3)]
CURVES_COEFFS1 [
Attenuation0dB => [
-2.7856531419538344,
-0.0050871540569528,
0.0000097982495890,
],
Attenuation2p5dB => [
-2.9831022915028695,
-0.0049393185868806,
0.0000101379430548,
],
Attenuation6dB => [
-2.3285545746296417,
-0.0147640181047414,
0.0000208385525314,
],
Attenuation11dB => [
-0.644403418269478,
-0.0644334888647536,
0.0001297891447611,
-0.0000000707697180,
0.0000000000135150,
],
];
/// Error curve coefficients derived from <https://github.com/espressif/esp-idf/blob/903af13e8/components/esp_adc/esp32s3/curve_fitting_coefficients.c>
#[cfg(esp32s3)]
CURVES_COEFFS2 [
Attenuation0dB => [
-2.5668651654328927,
0.0001353548869615,
0.0000036615265189,
],
Attenuation2p5dB => [
-2.3690184690298404,
-0.0066319894226185,
0.0000118964995959,
],
Attenuation6dB => [
-0.9452499397020617,
-0.0200996773954387,
0.00000259011467956,
],
Attenuation11dB => [
1.2247719764336924,
-0.0755717904943462,
0.0001478791187119,
-0.0000000796725280,
0.0000000000150380,
],
];
}
}