esp_hal/analog/adc/calibration/
curve.rs1use core::marker::PhantomData;
2
3use crate::analog::adc::{
4 AdcCalEfuse,
5 AdcCalLine,
6 AdcCalScheme,
7 AdcHasLineCal,
8 Attenuation,
9 CalibrationAccess,
10};
11
12const COEFF_MUL: i64 = 1 << 52;
13
14type CurveCoeff = i64;
17
18pub struct CurveCoeffs {
20 atten: Attenuation,
22 coeff: &'static [CurveCoeff],
24}
25
26type CurvesCoeffs = &'static [CurveCoeffs];
27
28pub trait AdcHasCurveCal {
32 const CURVES_COEFFS: CurvesCoeffs;
36}
37
38#[derive(Clone, Copy)]
46pub struct AdcCalCurve<ADCI> {
47 line: AdcCalLine<ADCI>,
48
49 coeff: &'static [CurveCoeff],
59
60 _phantom: PhantomData<ADCI>,
61}
62
63impl<ADCI> crate::private::Sealed for AdcCalCurve<ADCI> {}
64
65impl<ADCI> AdcCalScheme<ADCI> for AdcCalCurve<ADCI>
66where
67 ADCI: AdcCalEfuse + AdcHasLineCal + AdcHasCurveCal + CalibrationAccess,
68{
69 fn new_cal(atten: Attenuation) -> Self {
70 let line = AdcCalLine::<ADCI>::new_cal(atten);
71
72 let coeff = ADCI::CURVES_COEFFS
73 .iter()
74 .find(|item| item.atten == atten)
75 .expect("No curve coefficients for given attenuation")
76 .coeff;
77
78 Self {
79 line,
80 coeff,
81 _phantom: PhantomData,
82 }
83 }
84
85 fn adc_cal(&self) -> u16 {
86 self.line.adc_cal()
87 }
88
89 fn adc_val(&self, val: u16) -> u16 {
90 let val = self.line.adc_val(val);
91
92 let err = if val == 0 {
93 0
94 } else {
95 let mut var = 1i64;
97 let mut err = (var * self.coeff[0] / COEFF_MUL) as i32;
98
99 for coeff in &self.coeff[1..] {
100 var *= val as i64;
101 err += (var * *coeff / COEFF_MUL) as i32;
102 }
103
104 err
105 };
106
107 (val as i32 - err) as u16
108 }
109}
110
111macro_rules! coeff_tables {
112 ($($(#[$($meta:meta)*])* $name:ident [ $($att:ident => [ $($val:literal,)* ],)* ];)*) => {
113 $(
114 $(#[$($meta)*])*
115 const $name: CurvesCoeffs = &[
116 $(CurveCoeffs {
117 atten: Attenuation::$att,
118 coeff: &[
119 $(($val as f64 * COEFF_MUL as f64) as CurveCoeff,)*
120 ],
121 },)*
122 ];
123 )*
124 };
125}
126
127#[cfg(any(esp32c3, esp32c6, esp32s3))]
128mod impls {
129 use super::*;
130
131 impl AdcHasCurveCal for crate::peripherals::ADC1 {
132 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
133 }
134
135 #[cfg(esp32c3)]
136 impl AdcHasCurveCal for crate::peripherals::ADC2 {
137 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
138 }
139
140 #[cfg(esp32s3)]
141 impl AdcHasCurveCal for crate::peripherals::ADC2 {
142 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2;
143 }
144
145 coeff_tables! {
146 #[cfg(esp32c3)]
148 CURVES_COEFFS1 [
149 _0dB => [
150 -0.225966470500043,
151 -0.0007265418501948,
152 0.0000109410402681,
153 ],
154 _2p5dB => [
155 0.4229623392600516,
156 -0.0000731527490903,
157 0.0000088166562521,
158 ],
159 _6dB => [
160 -1.017859239236435,
161 -0.0097159265299153,
162 0.0000149794028038,
163 ],
164 _11dB => [
165 -1.4912262772850453,
166 -0.0228549975564099,
167 0.0000356391935717,
168 -0.0000000179964582,
169 0.0000000000042046,
170 ],
171 ];
172
173 #[cfg(esp32c6)]
175 CURVES_COEFFS1 [
176 _0dB => [
177 -0.0487166399931449,
178 0.0006436483033201,
179 0.0000030410131806,
180 ],
181 _2p5dB => [
182 -0.8665498165817785,
183 0.0015239070452946,
184 0.0000013818878844,
185 ],
186 _6dB => [
187 -1.2277821756674387,
188 0.0022275554717885,
189 0.0000005924302667,
190 ],
191 _11dB => [
192 -0.3801417550380255,
193 -0.0006020352420772,
194 0.0000012442478488,
195 ],
196 ];
197
198 #[cfg(esp32s3)]
200 CURVES_COEFFS1 [
201 _0dB => [
202 -2.7856531419538344,
203 -0.0050871540569528,
204 0.0000097982495890,
205 ],
206 _2p5dB => [
207 -2.9831022915028695,
208 -0.0049393185868806,
209 0.0000101379430548,
210 ],
211 _6dB => [
212 -2.3285545746296417,
213 -0.0147640181047414,
214 0.0000208385525314,
215 ],
216 _11dB => [
217 -0.644403418269478,
218 -0.0644334888647536,
219 0.0001297891447611,
220 -0.0000000707697180,
221 0.0000000000135150,
222 ],
223 ];
224
225 #[cfg(esp32s3)]
227 CURVES_COEFFS2 [
228 _0dB => [
229 -2.5668651654328927,
230 0.0001353548869615,
231 0.0000036615265189,
232 ],
233 _2p5dB => [
234 -2.3690184690298404,
235 -0.0066319894226185,
236 0.0000118964995959,
237 ],
238 _6dB => [
239 -0.9452499397020617,
240 -0.0200996773954387,
241 0.00000259011467956,
242 ],
243 _11dB => [
244 1.2247719764336924,
245 -0.0755717904943462,
246 0.0001478791187119,
247 -0.0000000796725280,
248 0.0000000000150380,
249 ],
250 ];
251 }
252}