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 || self.coeff.is_empty() {
96 0
97 } else {
98 let val_i64 = val as i64;
99 let mut poly = 0i64;
100
101 for &coeff in self.coeff.iter().rev() {
103 poly = poly * val_i64 + coeff;
104 }
105
106 (poly / COEFF_MUL) as i32
107 };
108
109 (val as i32 - err) as u16
110 }
111}
112
113macro_rules! coeff_tables {
114 ($($(#[$($meta:meta)*])* $name:ident [ $($att:ident => [ $($val:literal,)* ],)* ];)*) => {
115 $(
116 $(#[$($meta)*])*
117 const $name: CurvesCoeffs = &[
118 $(CurveCoeffs {
119 atten: Attenuation::$att,
120 coeff: &[
121 $(($val as f64 * COEFF_MUL as f64) as CurveCoeff,)*
122 ],
123 },)*
124 ];
125 )*
126 };
127}
128
129#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
130mod impls {
131 use super::*;
132
133 impl AdcHasCurveCal for crate::peripherals::ADC1<'_> {
134 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
135 }
136
137 #[cfg(esp32c3)]
138 impl AdcHasCurveCal for crate::peripherals::ADC2<'_> {
139 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
140 }
141
142 #[cfg(esp32s3)]
143 impl AdcHasCurveCal for crate::peripherals::ADC2<'_> {
144 const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2;
145 }
146
147 coeff_tables! {
148 #[cfg(esp32c3)]
150 CURVES_COEFFS1 [
151 _0dB => [
152 -0.225966470500043,
153 -0.0007265418501948,
154 0.0000109410402681,
155 ],
156 _2p5dB => [
157 0.4229623392600516,
158 -0.0000731527490903,
159 0.0000088166562521,
160 ],
161 _6dB => [
162 -1.017859239236435,
163 -0.0097159265299153,
164 0.0000149794028038,
165 ],
166 _11dB => [
167 -1.4912262772850453,
168 -0.0228549975564099,
169 0.0000356391935717,
170 -0.0000000179964582,
171 0.0000000000042046,
172 ],
173 ];
174
175 #[cfg(esp32c6)]
177 CURVES_COEFFS1 [
178 _0dB => [
179 -0.0487166399931449,
180 0.0006436483033201,
181 0.0000030410131806,
182 ],
183 _2p5dB => [
184 -0.8665498165817785,
185 0.0015239070452946,
186 0.0000013818878844,
187 ],
188 _6dB => [
189 -1.2277821756674387,
190 0.0022275554717885,
191 0.0000005924302667,
192 ],
193 _11dB => [
194 -0.3801417550380255,
195 -0.0006020352420772,
196 0.0000012442478488,
197 ],
198 ];
199
200 #[cfg(esp32h2)]
202 CURVES_COEFFS1 [
203 _0dB => [
204 -0.5081991760658888,
205 0.0000007858995319,
206 0,
207 ],
208 _2p5dB => [
209 -0.8359230818901277,
210 0.0000009025419089,
211 0,
212 ],
213 _6dB => [
214 -1.165668771581976,
215 0.0000008294679249,
216 0,
217 ],
218 _11dB => [
219 -0.3637329628677273,
220 -0.0000196072597389,
221 0.0000007871689227,
222 ],
223 ];
224
225 #[cfg(esp32s3)]
227 CURVES_COEFFS1 [
228 _0dB => [
229 -2.7856531419538344,
230 -0.0050871540569528,
231 0.0000097982495890,
232 ],
233 _2p5dB => [
234 -2.9831022915028695,
235 -0.0049393185868806,
236 0.0000101379430548,
237 ],
238 _6dB => [
239 -2.3285545746296417,
240 -0.0147640181047414,
241 0.0000208385525314,
242 ],
243 _11dB => [
244 -0.644403418269478,
245 -0.0644334888647536,
246 0.0001297891447611,
247 -0.0000000707697180,
248 0.0000000000135150,
249 ],
250 ];
251
252 #[cfg(esp32s3)]
254 CURVES_COEFFS2 [
255 _0dB => [
256 -2.5668651654328927,
257 0.0001353548869615,
258 0.0000036615265189,
259 ],
260 _2p5dB => [
261 -2.3690184690298404,
262 -0.0066319894226185,
263 0.0000118964995959,
264 ],
265 _6dB => [
266 -0.9452499397020617,
267 -0.0200996773954387,
268 0.00000259011467956,
269 ],
270 _11dB => [
271 1.2247719764336924,
272 -0.0755717904943462,
273 0.0001478791187119,
274 -0.0000000796725280,
275 0.0000000000150380,
276 ],
277 ];
278 }
279}