1use core::marker::PhantomData;
2
3#[cfg(esp32s3)]
4pub use self::calibration::*;
5use super::{AdcCalScheme, AdcCalSource, AdcChannel, AdcConfig, AdcPin, Attenuation};
6#[cfg(esp32s3)]
7use crate::efuse::{AdcCalibUnit, Efuse};
8use crate::{
9 peripherals::{APB_SARADC, SENS},
10 soc::regi2c,
11 system::{GenericPeripheralGuard, Peripheral},
12};
13
14mod calibration;
15
16pub(super) const NUM_ATTENS: usize = 10;
17
18cfg_if::cfg_if! {
19 if #[cfg(esp32s3)] {
20 const ADC_VAL_MASK: u16 = 0xfff;
21 const ADC_CAL_CNT_MAX: u16 = 32;
22 const ADC_CAL_CHANNEL: u16 = 15;
23 }
24}
25
26impl<ADCI> AdcConfig<ADCI>
27where
28 ADCI: RegisterAccess,
29{
30 pub fn adc_calibrate(atten: Attenuation, source: AdcCalSource) -> u16
32 where
33 ADCI: super::CalibrationAccess,
34 {
35 let mut adc_max: u16 = 0;
36 let mut adc_min: u16 = u16::MAX;
37 let mut adc_sum: u32 = 0;
38
39 ADCI::enable_vdef(true);
40
41 ADCI::set_en_pad(ADCI::ADC_CAL_CHANNEL as u8);
43 ADCI::set_attenuation(ADCI::ADC_CAL_CHANNEL as usize, atten as u8);
44
45 ADCI::connect_cal(source, true);
47
48 ADCI::calibration_init();
49 ADCI::set_init_code(0);
50
51 for _ in 0..ADCI::ADC_CAL_CNT_MAX {
52 ADCI::start_sample();
54
55 while !ADCI::is_done() {}
57
58 let adc = ADCI::read_data() & ADCI::ADC_VAL_MASK;
59
60 ADCI::reset();
61
62 adc_sum += adc as u32;
63 adc_max = adc.max(adc_max);
64 adc_min = adc.min(adc_min);
65 }
66
67 let cal_val =
68 (adc_sum - adc_max as u32 - adc_min as u32) as u16 / (ADCI::ADC_CAL_CNT_MAX - 2);
69
70 ADCI::connect_cal(source, false);
72
73 cal_val
74 }
75}
76
77#[doc(hidden)]
78pub trait RegisterAccess {
79 fn set_attenuation(channel: usize, attenuation: u8);
80
81 fn clear_dig_force();
82
83 fn set_start_force();
84
85 fn set_en_pad_force();
86
87 fn set_en_pad(channel: u8);
88
89 fn clear_start_sample();
90
91 fn start_sample();
92
93 fn is_done() -> bool;
95
96 fn read_data() -> u16;
98
99 fn calibration_init();
101
102 fn set_init_code(data: u16);
104
105 fn reset();
107}
108
109impl RegisterAccess for crate::peripherals::ADC1<'_> {
110 fn set_attenuation(channel: usize, attenuation: u8) {
111 SENS::regs().sar_atten1().modify(|r, w| {
112 let new_value = (r.bits() & !(0b11 << (channel * 2)))
113 | (((attenuation & 0b11) as u32) << (channel * 2));
114
115 unsafe { w.sar1_atten().bits(new_value) }
116 });
117 }
118
119 fn clear_dig_force() {
120 SENS::regs()
121 .sar_meas1_mux()
122 .modify(|_, w| w.sar1_dig_force().clear_bit());
123 }
124
125 fn set_start_force() {
126 SENS::regs()
127 .sar_meas1_ctrl2()
128 .modify(|_, w| w.meas1_start_force().set_bit());
129 }
130
131 fn set_en_pad_force() {
132 SENS::regs()
133 .sar_meas1_ctrl2()
134 .modify(|_, w| w.sar1_en_pad_force().set_bit());
135 }
136
137 fn set_en_pad(channel: u8) {
138 SENS::regs()
139 .sar_meas1_ctrl2()
140 .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
141 }
142
143 fn clear_start_sample() {
144 SENS::regs()
145 .sar_meas1_ctrl2()
146 .modify(|_, w| w.meas1_start_sar().clear_bit());
147 }
148
149 fn start_sample() {
150 SENS::regs()
151 .sar_meas1_ctrl2()
152 .modify(|_, w| w.meas1_start_sar().set_bit());
153 }
154
155 fn is_done() -> bool {
156 SENS::regs()
157 .sar_meas1_ctrl2()
158 .read()
159 .meas1_done_sar()
160 .bit_is_set()
161 }
162
163 fn read_data() -> u16 {
164 SENS::regs()
165 .sar_meas1_ctrl2()
166 .read()
167 .meas1_data_sar()
168 .bits()
169 }
170
171 #[cfg(any(esp32s2, esp32s3))]
172 fn calibration_init() {
173 regi2c::ADC_SAR1_DREF.write_field(4);
176 }
177
178 fn set_init_code(data: u16) {
179 let [msb, lsb] = data.to_be_bytes();
180
181 regi2c::ADC_SAR1_INITIAL_CODE_HIGH.write_field(msb);
182 regi2c::ADC_SAR1_INITIAL_CODE_LOW.write_field(lsb);
183 }
184
185 fn reset() {
186 let adc = APB_SARADC::regs();
187 let sensors = SENS::regs();
188
189 adc.int_clr().write(|w| w.adc1_done().clear_bit_by_one());
190
191 sensors
192 .sar_meas1_ctrl2()
193 .modify(|_, w| w.meas1_start_sar().clear_bit());
194 }
195}
196
197#[cfg(esp32s3)]
198impl super::CalibrationAccess for crate::peripherals::ADC1<'_> {
199 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
200 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
201 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
202
203 fn enable_vdef(enable: bool) {
204 regi2c::ADC_SAR1_DREF.write_field(enable as u8);
205 }
206
207 fn connect_cal(source: AdcCalSource, enable: bool) {
208 match source {
209 AdcCalSource::Gnd => regi2c::ADC_SAR1_ENCAL_GND.write_field(enable as u8),
210 AdcCalSource::Ref => regi2c::ADC_SAR1_ENCAL_REF.write_field(enable as u8),
211 }
212 }
213}
214
215impl RegisterAccess for crate::peripherals::ADC2<'_> {
216 fn set_attenuation(channel: usize, attenuation: u8) {
217 SENS::regs().sar_atten2().modify(|r, w| {
218 let new_value = (r.bits() & !(0b11 << (channel * 2)))
219 | (((attenuation & 0b11) as u32) << (channel * 2));
220
221 unsafe { w.sar2_atten().bits(new_value) }
222 });
223 }
224
225 fn clear_dig_force() {
226 SENS::regs()
227 .sar_meas2_mux()
228 .modify(|_, w| w.sar2_rtc_force().set_bit());
229
230 APB_SARADC::regs()
231 .arb_ctrl()
232 .modify(|_, w| w.rtc_force().set_bit());
233 }
234
235 fn set_start_force() {
236 SENS::regs()
237 .sar_meas2_ctrl2()
238 .modify(|_, w| w.meas2_start_force().set_bit());
239 }
240
241 fn set_en_pad_force() {
242 SENS::regs()
243 .sar_meas2_ctrl2()
244 .modify(|_, w| w.sar2_en_pad_force().set_bit());
245 }
246
247 fn set_en_pad(channel: u8) {
248 SENS::regs()
249 .sar_meas2_ctrl2()
250 .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
251 }
252
253 fn clear_start_sample() {
254 SENS::regs()
255 .sar_meas2_ctrl2()
256 .modify(|_, w| w.meas2_start_sar().clear_bit());
257 }
258
259 fn start_sample() {
260 SENS::regs()
261 .sar_meas2_ctrl2()
262 .modify(|_, w| w.meas2_start_sar().set_bit());
263 }
264
265 fn is_done() -> bool {
266 SENS::regs()
267 .sar_meas2_ctrl2()
268 .read()
269 .meas2_done_sar()
270 .bit_is_set()
271 }
272
273 fn read_data() -> u16 {
274 SENS::regs()
275 .sar_meas2_ctrl2()
276 .read()
277 .meas2_data_sar()
278 .bits()
279 }
280
281 #[cfg(any(esp32s2, esp32s3))]
282 fn calibration_init() {
283 regi2c::ADC_SAR2_DREF.write_field(4);
284 }
285
286 fn set_init_code(data: u16) {
287 let [msb, lsb] = data.to_be_bytes();
288
289 regi2c::ADC_SAR2_INITIAL_CODE_HIGH.write_field(msb);
290 regi2c::ADC_SAR2_INITIAL_CODE_LOW.write_field(lsb);
291 }
292
293 fn reset() {
294 let adc = APB_SARADC::regs();
295 let sensors = SENS::regs();
296
297 adc.int_clr().write(|w| w.adc2_done().clear_bit_by_one());
298
299 sensors
300 .sar_meas2_ctrl2()
301 .modify(|_, w| w.meas2_start_sar().clear_bit());
302 }
303}
304
305#[cfg(esp32s3)]
306impl super::CalibrationAccess for crate::peripherals::ADC2<'_> {
307 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
308 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
309 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
310
311 fn enable_vdef(enable: bool) {
312 regi2c::ADC_SAR2_DREF.write_field(enable as u8);
313 }
314
315 fn connect_cal(source: AdcCalSource, enable: bool) {
316 match source {
317 AdcCalSource::Gnd => regi2c::ADC_SAR2_ENCAL_GND.write_field(enable as u8),
318 AdcCalSource::Ref => regi2c::ADC_SAR2_ENCAL_REF.write_field(enable as u8),
319 }
320 }
321}
322
323pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
325 _adc: ADC,
326 active_channel: Option<u8>,
327 last_init_code: u16,
328 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
329 _phantom: PhantomData<(Dm, &'d mut ())>,
330}
331
332impl<'d, ADCI> Adc<'d, ADCI, crate::Blocking>
333where
334 ADCI: RegisterAccess + 'd,
335{
336 pub fn new(adc_instance: ADCI, config: AdcConfig<ADCI>) -> Self {
339 let guard = GenericPeripheralGuard::new();
340 let sensors = SENS::regs();
341
342 let attenuations = config.attenuations;
344
345 for (channel, attenuation) in attenuations.iter().enumerate() {
346 if let Some(attenuation) = attenuation {
347 ADCI::set_attenuation(channel, *attenuation as u8);
348 }
349 }
350
351 ADCI::clear_dig_force();
353 ADCI::set_start_force();
354 ADCI::set_en_pad_force();
355 sensors.sar_hall_ctrl().modify(|_, w| {
356 w.xpd_hall_force().set_bit();
357 w.hall_phase_force().set_bit()
358 });
359
360 #[cfg(esp32s2)]
362 sensors
363 .sar_meas1_ctrl1()
364 .modify(|_, w| w.rtc_saradc_clkgate_en().set_bit());
365
366 #[cfg(esp32s3)]
367 sensors
368 .sar_peri_clk_gate_conf()
369 .modify(|_, w| w.saradc_clk_en().set_bit());
370
371 sensors.sar_power_xpd_sar().modify(|_, w| unsafe {
372 w.sarclk_en().set_bit();
373 w.force_xpd_sar().bits(0b11)
374 });
375
376 sensors
378 .sar_meas1_ctrl1()
379 .modify(|_, w| unsafe { w.force_xpd_amp().bits(0b11) });
380 sensors.sar_amp_ctrl3().modify(|_, w| unsafe {
381 w.amp_rst_fb_fsm().bits(0);
382 w.amp_short_ref_fsm().bits(0);
383 w.amp_short_ref_gnd_fsm().bits(0)
384 });
385 sensors.sar_amp_ctrl1().modify(|_, w| unsafe {
386 w.sar_amp_wait1().bits(1);
387 w.sar_amp_wait2().bits(1)
388 });
389 sensors
390 .sar_amp_ctrl2()
391 .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
392
393 Adc {
394 _adc: adc_instance,
395 active_channel: None,
396 last_init_code: 0,
397 _guard: guard,
398 _phantom: PhantomData,
399 }
400 }
401
402 pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> u16
405 where
406 PIN: AdcChannel,
407 CS: AdcCalScheme<ADCI>,
408 {
409 self.start_sample(pin);
410
411 while !ADCI::is_done() {}
413
414 let converted_value = ADCI::read_data();
416 ADCI::reset();
417
418 pin.cal_scheme.adc_val(converted_value)
420 }
421
422 pub fn read_oneshot<PIN, CS>(
428 &mut self,
429 pin: &mut super::AdcPin<PIN, ADCI, CS>,
430 ) -> nb::Result<u16, ()>
431 where
432 PIN: super::AdcChannel,
433 CS: super::AdcCalScheme<ADCI>,
434 {
435 if let Some(active_channel) = self.active_channel {
436 if active_channel != pin.pin.adc_channel() {
440 return Err(nb::Error::WouldBlock);
441 }
442 } else {
443 self.active_channel = Some(pin.pin.adc_channel());
445
446 self.start_sample(pin);
447 }
448
449 let conversion_finished = ADCI::is_done();
451 if !conversion_finished {
452 return Err(nb::Error::WouldBlock);
453 }
454
455 let converted_value = ADCI::read_data();
457 ADCI::reset();
458
459 let converted_value = pin.cal_scheme.adc_val(converted_value);
461
462 self.active_channel = None;
464
465 Ok(converted_value)
466 }
467
468 fn start_sample<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>)
469 where
470 PIN: AdcChannel,
471 CS: AdcCalScheme<ADCI>,
472 {
473 let init_code = pin.cal_scheme.adc_cal();
475 if self.last_init_code != init_code {
476 ADCI::calibration_init();
477 ADCI::set_init_code(init_code);
478 self.last_init_code = init_code;
479 }
480
481 ADCI::set_en_pad(pin.pin.adc_channel());
482
483 ADCI::clear_start_sample();
484 ADCI::start_sample();
485 }
486}
487
488#[cfg(esp32s3)]
489impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
490 fn init_code(atten: Attenuation) -> Option<u16> {
491 Efuse::rtc_calib_init_code(AdcCalibUnit::ADC1, atten)
492 }
493
494 fn cal_mv(atten: Attenuation) -> u16 {
495 Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC1, atten)
496 }
497
498 fn cal_code(atten: Attenuation) -> Option<u16> {
499 Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC1, atten)
500 }
501}
502
503#[cfg(esp32s3)]
504impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
505 fn init_code(atten: Attenuation) -> Option<u16> {
506 Efuse::rtc_calib_init_code(AdcCalibUnit::ADC2, atten)
507 }
508
509 fn cal_mv(atten: Attenuation) -> u16 {
510 Efuse::rtc_calib_cal_mv(AdcCalibUnit::ADC2, atten)
511 }
512
513 fn cal_code(atten: Attenuation) -> Option<u16> {
514 Efuse::rtc_calib_cal_code(AdcCalibUnit::ADC2, atten)
515 }
516}