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::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
26#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29#[allow(clippy::enum_variant_names, reason = "peripheral is unstable")]
30pub enum Resolution {
31 #[default]
33 Resolution13Bit,
34}
35
36impl<ADCI> AdcConfig<ADCI>
37where
38 ADCI: RegisterAccess,
39{
40 pub fn adc_calibrate(atten: Attenuation, source: AdcCalSource) -> u16
42 where
43 ADCI: super::CalibrationAccess,
44 {
45 let mut adc_max: u16 = 0;
46 let mut adc_min: u16 = u16::MAX;
47 let mut adc_sum: u32 = 0;
48
49 ADCI::enable_vdef(true);
50
51 ADCI::set_en_pad(ADCI::ADC_CAL_CHANNEL as u8);
53 ADCI::set_attenuation(ADCI::ADC_CAL_CHANNEL as usize, atten as u8);
54
55 ADCI::connect_cal(source, true);
57
58 ADCI::set_init_code(0);
59
60 for _ in 0..ADCI::ADC_CAL_CNT_MAX {
61 ADCI::start_sample();
63
64 while !ADCI::is_done() {}
66
67 let adc = ADCI::read_data() & ADCI::ADC_VAL_MASK;
68
69 ADCI::reset();
70
71 adc_sum += adc as u32;
72 adc_max = adc.max(adc_max);
73 adc_min = adc.min(adc_min);
74 }
75
76 let cal_val =
77 (adc_sum - adc_max as u32 - adc_min as u32) as u16 / (ADCI::ADC_CAL_CNT_MAX - 2);
78
79 ADCI::connect_cal(source, false);
81
82 cal_val
83 }
84}
85
86#[doc(hidden)]
87pub trait RegisterAccess {
88 fn set_attenuation(channel: usize, attenuation: u8);
89
90 fn clear_dig_force();
91
92 fn set_start_force();
93
94 fn set_en_pad_force();
95
96 fn set_en_pad(channel: u8);
97
98 fn clear_start_sample();
99
100 fn start_sample();
101
102 fn is_done() -> bool;
104
105 fn read_data() -> u16;
107
108 fn set_init_code(data: u16);
110
111 fn reset();
113}
114
115impl RegisterAccess for crate::peripherals::ADC1<'_> {
116 fn set_attenuation(channel: usize, attenuation: u8) {
117 SENS::regs().sar_atten1().modify(|r, w| {
118 let new_value = (r.bits() & !(0b11 << (channel * 2)))
119 | (((attenuation & 0b11) as u32) << (channel * 2));
120
121 unsafe { w.sar1_atten().bits(new_value) }
122 });
123 }
124
125 fn clear_dig_force() {
126 SENS::regs()
127 .sar_meas1_mux()
128 .modify(|_, w| w.sar1_dig_force().clear_bit());
129 }
130
131 fn set_start_force() {
132 SENS::regs()
133 .sar_meas1_ctrl2()
134 .modify(|_, w| w.meas1_start_force().set_bit());
135 }
136
137 fn set_en_pad_force() {
138 SENS::regs()
139 .sar_meas1_ctrl2()
140 .modify(|_, w| w.sar1_en_pad_force().set_bit());
141 }
142
143 fn set_en_pad(channel: u8) {
144 SENS::regs()
145 .sar_meas1_ctrl2()
146 .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
147 }
148
149 fn clear_start_sample() {
150 SENS::regs()
151 .sar_meas1_ctrl2()
152 .modify(|_, w| w.meas1_start_sar().clear_bit());
153 }
154
155 fn start_sample() {
156 SENS::regs()
157 .sar_meas1_ctrl2()
158 .modify(|_, w| w.meas1_start_sar().set_bit());
159 }
160
161 fn is_done() -> bool {
162 SENS::regs()
163 .sar_meas1_ctrl2()
164 .read()
165 .meas1_done_sar()
166 .bit_is_set()
167 }
168
169 fn read_data() -> u16 {
170 SENS::regs()
171 .sar_meas1_ctrl2()
172 .read()
173 .meas1_data_sar()
174 .bits()
175 }
176
177 fn set_init_code(data: u16) {
178 let [msb, lsb] = data.to_be_bytes();
179
180 regi2c::ADC_SAR1_INITIAL_CODE_HIGH.write_field(msb);
181 regi2c::ADC_SAR1_INITIAL_CODE_LOW.write_field(lsb);
182 }
183
184 fn reset() {
185 let adc = APB_SARADC::regs();
186 let sensors = SENS::regs();
187
188 adc.int_clr().write(|w| w.adc1_done().clear_bit_by_one());
189
190 sensors
191 .sar_meas1_ctrl2()
192 .modify(|_, w| w.meas1_start_sar().clear_bit());
193 }
194}
195
196#[cfg(esp32s3)]
197impl super::CalibrationAccess for crate::peripherals::ADC1<'_> {
198 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
199 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
200 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
201
202 fn enable_vdef(enable: bool) {
203 regi2c::ADC_SAR1_DREF.write_field(enable as u8);
204 }
205
206 fn connect_cal(source: AdcCalSource, enable: bool) {
207 match source {
208 AdcCalSource::Gnd => regi2c::ADC_SAR1_ENCAL_GND.write_field(enable as u8),
209 AdcCalSource::Ref => regi2c::ADC_SAR1_ENCAL_REF.write_field(enable as u8),
210 }
211 }
212}
213
214impl RegisterAccess for crate::peripherals::ADC2<'_> {
215 fn set_attenuation(channel: usize, attenuation: u8) {
216 SENS::regs().sar_atten2().modify(|r, w| {
217 let new_value = (r.bits() & !(0b11 << (channel * 2)))
218 | (((attenuation & 0b11) as u32) << (channel * 2));
219
220 unsafe { w.sar2_atten().bits(new_value) }
221 });
222 }
223
224 fn clear_dig_force() {
225 SENS::regs()
226 .sar_meas2_mux()
227 .modify(|_, w| w.sar2_rtc_force().set_bit());
228
229 APB_SARADC::regs()
230 .arb_ctrl()
231 .modify(|_, w| w.rtc_force().set_bit());
232 }
233
234 fn set_start_force() {
235 SENS::regs()
236 .sar_meas2_ctrl2()
237 .modify(|_, w| w.meas2_start_force().set_bit());
238 }
239
240 fn set_en_pad_force() {
241 SENS::regs()
242 .sar_meas2_ctrl2()
243 .modify(|_, w| w.sar2_en_pad_force().set_bit());
244 }
245
246 fn set_en_pad(channel: u8) {
247 SENS::regs()
248 .sar_meas2_ctrl2()
249 .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
250 }
251
252 fn clear_start_sample() {
253 SENS::regs()
254 .sar_meas2_ctrl2()
255 .modify(|_, w| w.meas2_start_sar().clear_bit());
256 }
257
258 fn start_sample() {
259 SENS::regs()
260 .sar_meas2_ctrl2()
261 .modify(|_, w| w.meas2_start_sar().set_bit());
262 }
263
264 fn is_done() -> bool {
265 SENS::regs()
266 .sar_meas2_ctrl2()
267 .read()
268 .meas2_done_sar()
269 .bit_is_set()
270 }
271
272 fn read_data() -> u16 {
273 SENS::regs()
274 .sar_meas2_ctrl2()
275 .read()
276 .meas2_data_sar()
277 .bits()
278 }
279
280 fn set_init_code(data: u16) {
281 let [msb, lsb] = data.to_be_bytes();
282
283 regi2c::ADC_SAR2_INITIAL_CODE_HIGH.write_field(msb);
284 regi2c::ADC_SAR2_INITIAL_CODE_LOW.write_field(lsb);
285 }
286
287 fn reset() {
288 let adc = APB_SARADC::regs();
289 let sensors = SENS::regs();
290
291 adc.int_clr().write(|w| w.adc2_done().clear_bit_by_one());
292
293 sensors
294 .sar_meas2_ctrl2()
295 .modify(|_, w| w.meas2_start_sar().clear_bit());
296 }
297}
298
299#[cfg(esp32s3)]
300impl super::CalibrationAccess for crate::peripherals::ADC2<'_> {
301 const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
302 const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
303 const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
304
305 fn enable_vdef(enable: bool) {
306 regi2c::ADC_SAR2_DREF.write_field(enable as u8);
307 }
308
309 fn connect_cal(source: AdcCalSource, enable: bool) {
310 match source {
311 AdcCalSource::Gnd => regi2c::ADC_SAR2_ENCAL_GND.write_field(enable as u8),
312 AdcCalSource::Ref => regi2c::ADC_SAR2_ENCAL_REF.write_field(enable as u8),
313 }
314 }
315}
316
317pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
319 _adc: ADC,
320 active_channel: Option<u8>,
321 last_init_code: u16,
322 _guard: GenericPeripheralGuard<{ Peripheral::ApbSarAdc as u8 }>,
323 _phantom: PhantomData<(Dm, &'d mut ())>,
324}
325
326impl<'d, ADCI> Adc<'d, ADCI, crate::Blocking>
327where
328 ADCI: RegisterAccess + 'd,
329{
330 pub fn new(adc_instance: ADCI, config: AdcConfig<ADCI>) -> Self {
333 let guard = GenericPeripheralGuard::new();
334 let sensors = SENS::regs();
335
336 let attenuations = config.attenuations;
338
339 for (channel, attenuation) in attenuations.iter().enumerate() {
340 if let Some(attenuation) = attenuation {
341 ADCI::set_attenuation(channel, *attenuation as u8);
342 }
343 }
344
345 ADCI::clear_dig_force();
347 ADCI::set_start_force();
348 ADCI::set_en_pad_force();
349 sensors
350 .sar_hall_ctrl()
351 .modify(|_, w| w.xpd_hall_force().set_bit());
352 sensors
353 .sar_hall_ctrl()
354 .modify(|_, w| w.hall_phase_force().set_bit());
355
356 #[cfg(esp32s2)]
358 sensors
359 .sar_meas1_ctrl1()
360 .modify(|_, w| w.rtc_saradc_clkgate_en().set_bit());
361
362 #[cfg(esp32s3)]
363 sensors
364 .sar_peri_clk_gate_conf()
365 .modify(|_, w| w.saradc_clk_en().set_bit());
366
367 sensors
368 .sar_power_xpd_sar()
369 .modify(|_, w| w.sarclk_en().set_bit());
370
371 sensors
372 .sar_power_xpd_sar()
373 .modify(|_, w| unsafe { w.force_xpd_sar().bits(0b11) });
374
375 sensors
377 .sar_meas1_ctrl1()
378 .modify(|_, w| unsafe { w.force_xpd_amp().bits(0b11) });
379 sensors
380 .sar_amp_ctrl3()
381 .modify(|_, w| unsafe { w.amp_rst_fb_fsm().bits(0) });
382 sensors
383 .sar_amp_ctrl3()
384 .modify(|_, w| unsafe { w.amp_short_ref_fsm().bits(0) });
385 sensors
386 .sar_amp_ctrl3()
387 .modify(|_, w| unsafe { w.amp_short_ref_gnd_fsm().bits(0) });
388 sensors
389 .sar_amp_ctrl1()
390 .modify(|_, w| unsafe { w.sar_amp_wait1().bits(1) });
391 sensors
392 .sar_amp_ctrl1()
393 .modify(|_, w| unsafe { w.sar_amp_wait2().bits(1) });
394 sensors
395 .sar_amp_ctrl2()
396 .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
397
398 Adc {
399 _adc: adc_instance,
400 active_channel: None,
401 last_init_code: 0,
402 _guard: guard,
403 _phantom: PhantomData,
404 }
405 }
406
407 pub fn read_blocking<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> u16
410 where
411 PIN: AdcChannel,
412 CS: AdcCalScheme<ADCI>,
413 {
414 self.start_sample(pin);
415
416 while !ADCI::is_done() {}
418
419 let converted_value = ADCI::read_data();
421 ADCI::reset();
422
423 pin.cal_scheme.adc_val(converted_value)
425 }
426
427 pub fn read_oneshot<PIN, CS>(
433 &mut self,
434 pin: &mut super::AdcPin<PIN, ADCI, CS>,
435 ) -> nb::Result<u16, ()>
436 where
437 PIN: super::AdcChannel,
438 CS: super::AdcCalScheme<ADCI>,
439 {
440 if let Some(active_channel) = self.active_channel {
441 if active_channel != PIN::CHANNEL {
445 return Err(nb::Error::WouldBlock);
446 }
447 } else {
448 self.active_channel = Some(PIN::CHANNEL);
450
451 self.start_sample(pin);
452 }
453
454 let conversion_finished = ADCI::is_done();
456 if !conversion_finished {
457 return Err(nb::Error::WouldBlock);
458 }
459
460 let converted_value = ADCI::read_data();
462 ADCI::reset();
463
464 let converted_value = pin.cal_scheme.adc_val(converted_value);
466
467 self.active_channel = None;
469
470 Ok(converted_value)
471 }
472
473 fn start_sample<PIN, CS>(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>)
474 where
475 PIN: AdcChannel,
476 CS: AdcCalScheme<ADCI>,
477 {
478 let init_code = pin.cal_scheme.adc_cal();
480 if self.last_init_code != init_code {
481 ADCI::set_init_code(init_code);
482 self.last_init_code = init_code;
483 }
484
485 ADCI::set_en_pad(PIN::CHANNEL);
486
487 ADCI::clear_start_sample();
488 ADCI::start_sample();
489 }
490}
491
492#[cfg(esp32s3)]
493impl super::AdcCalEfuse for crate::peripherals::ADC1<'_> {
494 fn init_code(atten: Attenuation) -> Option<u16> {
495 Efuse::rtc_calib_init_code(1, atten)
496 }
497
498 fn cal_mv(atten: Attenuation) -> u16 {
499 Efuse::rtc_calib_cal_mv(1, atten)
500 }
501
502 fn cal_code(atten: Attenuation) -> Option<u16> {
503 Efuse::rtc_calib_cal_code(1, atten)
504 }
505}
506
507#[cfg(esp32s3)]
508impl super::AdcCalEfuse for crate::peripherals::ADC2<'_> {
509 fn init_code(atten: Attenuation) -> Option<u16> {
510 Efuse::rtc_calib_init_code(2, atten)
511 }
512
513 fn cal_mv(atten: Attenuation) -> u16 {
514 Efuse::rtc_calib_cal_mv(2, atten)
515 }
516
517 fn cal_code(atten: Attenuation) -> Option<u16> {
518 Efuse::rtc_calib_cal_code(2, atten)
519 }
520}
521
522mod adc_implementation {
523 crate::analog::adc::impl_adc_interface! {
524 ADC1 [
525 (GPIO1<'_>, 0),
526 (GPIO2<'_>, 1),
527 (GPIO3<'_>, 2),
528 (GPIO4<'_>, 3),
529 (GPIO5<'_>, 4),
530 (GPIO6<'_>, 5),
531 (GPIO7<'_>, 6),
532 (GPIO8<'_>, 7),
533 (GPIO9<'_>, 8),
534 (GPIO10<'_>, 9),
535 ]
536 }
537
538 crate::analog::adc::impl_adc_interface! {
539 ADC2 [
540 (GPIO11<'_>, 0),
541 (GPIO12<'_>, 1),
542 (GPIO13<'_>, 2),
543 (GPIO14<'_>, 3),
544 (GPIO15<'_>, 4),
545 (GPIO16<'_>, 5),
546 (GPIO17<'_>, 6),
547 (GPIO18<'_>, 7),
548 (GPIO19<'_>, 8),
549 (GPIO20<'_>, 9),
550 ]
551 }
552}