esp_hal/analog/adc/
esp32.rs1use core::{
2 marker::PhantomData,
3 sync::atomic::{AtomicBool, Ordering},
4};
5
6use super::{AdcConfig, Attenuation};
7use crate::{
8 peripherals::{ADC1, ADC2, RTC_IO, SENS},
9 private::{self},
10};
11
12pub(super) const NUM_ATTENS: usize = 10;
13
14static ADC2_IN_USE: AtomicBool = AtomicBool::new(false);
17
18#[derive(Debug)]
20pub enum Error {
21 Adc2InUse,
23}
24
25#[doc(hidden)]
26pub fn try_claim_adc2(_: private::Internal) -> Result<(), Error> {
28 if ADC2_IN_USE.fetch_or(true, Ordering::Relaxed) {
29 Err(Error::Adc2InUse)
30 } else {
31 Ok(())
32 }
33}
34
35#[doc(hidden)]
36pub fn release_adc2(_: private::Internal) {
38 ADC2_IN_USE.store(false, Ordering::Relaxed);
39}
40
41#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44#[allow(clippy::enum_variant_names, reason = "unit of measurement")]
45pub enum Resolution {
46 _9Bit,
48 _10Bit,
50 _11Bit,
52 #[default]
54 _12Bit,
55}
56
57#[doc(hidden)]
58pub trait RegisterAccess {
59 fn set_resolution(resolution: u8);
60
61 fn set_attenuation(channel: usize, attenuation: u8);
62
63 fn clear_dig_force();
64
65 fn set_start_force();
66
67 fn set_en_pad_force();
68
69 fn set_en_pad(channel: u8);
70
71 fn clear_start_sar();
72
73 fn set_start_sar();
74
75 fn read_done_sar() -> bool;
76
77 fn read_data_sar() -> u16;
78
79 fn instance_number() -> u8;
80}
81
82impl RegisterAccess for ADC1<'_> {
83 fn set_resolution(resolution: u8) {
84 SENS::regs()
85 .sar_start_force()
86 .modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) });
87 SENS::regs()
88 .sar_read_ctrl()
89 .modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) });
90 }
91
92 fn set_attenuation(channel: usize, attenuation: u8) {
93 SENS::regs().sar_atten1().modify(|r, w| {
94 let new_value = (r.bits() & !(0b11 << (channel * 2)))
95 | (((attenuation & 0b11) as u32) << (channel * 2));
96
97 unsafe { w.sar1_atten().bits(new_value) }
98 });
99 }
100
101 fn clear_dig_force() {
102 SENS::regs()
103 .sar_read_ctrl()
104 .modify(|_, w| w.sar1_dig_force().clear_bit());
105 }
106
107 fn set_start_force() {
108 SENS::regs()
109 .sar_meas_start1()
110 .modify(|_, w| w.meas1_start_force().set_bit());
111 }
112
113 fn set_en_pad_force() {
114 SENS::regs()
115 .sar_meas_start1()
116 .modify(|_, w| w.sar1_en_pad_force().set_bit());
117 }
118
119 fn set_en_pad(channel: u8) {
120 SENS::regs()
121 .sar_meas_start1()
122 .modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
123 }
124
125 fn clear_start_sar() {
126 SENS::regs()
127 .sar_meas_start1()
128 .modify(|_, w| w.meas1_start_sar().clear_bit());
129 }
130
131 fn set_start_sar() {
132 SENS::regs()
133 .sar_meas_start1()
134 .modify(|_, w| w.meas1_start_sar().set_bit());
135 }
136
137 fn read_done_sar() -> bool {
138 SENS::regs()
139 .sar_meas_start1()
140 .read()
141 .meas1_done_sar()
142 .bit_is_set()
143 }
144
145 fn read_data_sar() -> u16 {
146 SENS::regs()
147 .sar_meas_start1()
148 .read()
149 .meas1_data_sar()
150 .bits()
151 }
152
153 fn instance_number() -> u8 {
154 1
155 }
156}
157
158impl RegisterAccess for ADC2<'_> {
159 fn set_resolution(resolution: u8) {
160 SENS::regs()
161 .sar_start_force()
162 .modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) });
163 SENS::regs()
164 .sar_read_ctrl2()
165 .modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) });
166 }
167
168 fn set_attenuation(channel: usize, attenuation: u8) {
169 SENS::regs().sar_atten2().modify(|r, w| {
170 let new_value = (r.bits() & !(0b11 << (channel * 2)))
171 | (((attenuation & 0b11) as u32) << (channel * 2));
172
173 unsafe { w.sar2_atten().bits(new_value) }
174 });
175 }
176
177 fn clear_dig_force() {
178 SENS::regs()
179 .sar_read_ctrl2()
180 .modify(|_, w| w.sar2_dig_force().clear_bit());
181 }
182
183 fn set_start_force() {
184 SENS::regs()
185 .sar_meas_start2()
186 .modify(|_, w| w.meas2_start_force().set_bit());
187 }
188
189 fn set_en_pad_force() {
190 SENS::regs()
191 .sar_meas_start2()
192 .modify(|_, w| w.sar2_en_pad_force().set_bit());
193 }
194
195 fn set_en_pad(channel: u8) {
196 SENS::regs()
197 .sar_meas_start2()
198 .modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
199 }
200
201 fn clear_start_sar() {
202 SENS::regs()
203 .sar_meas_start2()
204 .modify(|_, w| w.meas2_start_sar().clear_bit());
205 }
206
207 fn set_start_sar() {
208 SENS::regs()
209 .sar_meas_start2()
210 .modify(|_, w| w.meas2_start_sar().set_bit());
211 }
212
213 fn read_done_sar() -> bool {
214 SENS::regs()
215 .sar_meas_start2()
216 .read()
217 .meas2_done_sar()
218 .bit_is_set()
219 }
220
221 fn read_data_sar() -> u16 {
222 SENS::regs()
223 .sar_meas_start2()
224 .read()
225 .meas2_data_sar()
226 .bits()
227 }
228
229 fn instance_number() -> u8 {
230 2
231 }
232}
233
234pub struct Adc<'d, ADC, Dm: crate::DriverMode> {
236 _adc: ADC,
237 attenuations: [Option<Attenuation>; NUM_ATTENS],
238 active_channel: Option<u8>,
239 _phantom: PhantomData<(Dm, &'d mut ())>,
240}
241
242impl<'d, ADCI> Adc<'d, ADCI, crate::Blocking>
243where
244 ADCI: RegisterAccess + 'd,
245{
246 pub fn new(adc_instance: ADCI, config: AdcConfig<ADCI>) -> Self {
254 if ADCI::instance_number() == 2 && try_claim_adc2(private::Internal).is_err() {
255 panic!(
256 "ADC2 is already in use by Radio. On ESP32, ADC2 cannot be used simultaneously with Wi-Fi or Bluetooth."
257 );
258 }
259
260 let sensors = SENS::regs();
261
262 ADCI::set_resolution(config.resolution as u8);
264
265 let attenuations = config.attenuations;
267
268 for (channel, attentuation) in attenuations.iter().enumerate() {
269 if let Some(attenuation) = attentuation {
270 ADC1::set_attenuation(channel, *attenuation as u8);
271 }
272 }
273
274 ADCI::clear_dig_force();
276 ADCI::set_start_force();
277 ADCI::set_en_pad_force();
278 sensors.sar_touch_ctrl1().modify(|_, w| {
279 w.xpd_hall_force().set_bit();
280 w.hall_phase_force().set_bit()
281 });
282
283 sensors.sar_meas_wait2().modify(|_, w| unsafe {
284 w.force_xpd_sar().bits(0b11);
286 w.force_xpd_amp().bits(0b10)
288 });
289 sensors.sar_meas_ctrl().modify(|_, w| unsafe {
290 w.amp_rst_fb_fsm().bits(0);
291 w.amp_short_ref_fsm().bits(0);
292 w.amp_short_ref_gnd_fsm().bits(0)
293 });
294 sensors.sar_meas_wait1().modify(|_, w| unsafe {
295 w.sar_amp_wait1().bits(1);
296 w.sar_amp_wait2().bits(1)
297 });
298 sensors
299 .sar_meas_wait2()
300 .modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
301
302 sensors
305 .sar_read_ctrl2()
306 .modify(|_, w| w.sar2_data_inv().set_bit());
307
308 Adc {
309 _adc: adc_instance,
310 attenuations: config.attenuations,
311 active_channel: None,
312 _phantom: PhantomData,
313 }
314 }
315
316 pub fn read_oneshot<PIN>(&mut self, pin: &mut super::AdcPin<PIN, ADCI>) -> nb::Result<u16, ()>
322 where
323 PIN: super::AdcChannel,
324 {
325 if self.attenuations[pin.pin.adc_channel() as usize].is_none() {
326 panic!(
327 "Channel {} is not configured reading!",
328 pin.pin.adc_channel()
329 );
330 }
331
332 if let Some(active_channel) = self.active_channel {
333 if active_channel != pin.pin.adc_channel() {
337 return Err(nb::Error::WouldBlock);
338 }
339 } else {
340 self.active_channel = Some(pin.pin.adc_channel());
342
343 ADCI::set_en_pad(pin.pin.adc_channel());
344
345 ADCI::clear_start_sar();
346 ADCI::set_start_sar();
347 }
348
349 let conversion_finished = ADCI::read_done_sar();
351 if !conversion_finished {
352 return Err(nb::Error::WouldBlock);
353 }
354
355 let converted_value = ADCI::read_data_sar();
357
358 self.active_channel = None;
360
361 Ok(converted_value)
362 }
363}
364
365impl<ADC1> Adc<'_, ADC1, crate::Blocking> {
366 pub fn enable_hall_sensor() {
368 RTC_IO::regs()
369 .hall_sens()
370 .modify(|_, w| w.xpd_hall().set_bit());
371 }
372
373 pub fn disable_hall_sensor() {
375 RTC_IO::regs()
376 .hall_sens()
377 .modify(|_, w| w.xpd_hall().clear_bit());
378 }
379}
380
381impl Drop for ADC2<'_> {
382 fn drop(&mut self) {
383 release_adc2(private::Internal);
384 }
385}