1#[allow(unused)]
2use pac::adc::vals::{Adc4Dmacfg, Adc4Exten, Adc4OversamplingRatio};
3
4use super::{blocking_delay_us, AdcChannel, AnyAdcChannel, RxDma4, SealedAdcChannel};
5use crate::dma::Transfer;
6pub use crate::pac::adc::regs::Adc4Chselrmod0;
7pub use crate::pac::adc::vals::{Adc4Presc as Presc, Adc4Res as Resolution, Adc4SampleTime as SampleTime};
8use crate::time::Hertz;
9use crate::{pac, rcc, Peripheral};
10
11const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(megahertz:55);
12
13/// Default VREF voltage used for sample conversion to millivolts.
14pub const VREF_DEFAULT_MV: u32 = 3300;
15/// VREF voltage used for factory calibration of VREFINTCAL register.
16pub const VREF_CALIB_MV: u32 = 3300;
17
18const VREF_CHANNEL: u8 = 0;
19const VCORE_CHANNEL: u8 = 12;
20const TEMP_CHANNEL: u8 = 13;
21const VBAT_CHANNEL: u8 = 14;
22const DAC_CHANNEL: u8 = 21;
23
24// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
25/// Internal voltage reference channel.
26pub struct VrefInt;
27impl<T: Instance> AdcChannel<T> for VrefInt {}
28impl<T: Instance> SealedAdcChannel<T> for VrefInt {
29 fn channel(&self) -> u8 {
30 VREF_CHANNEL
31 }
32}
33
34/// Internal temperature channel.
35pub struct Temperature;
36impl<T: Instance> AdcChannel<T> for Temperature {}
37impl<T: Instance> SealedAdcChannel<T> for Temperature {
38 fn channel(&self) -> u8 {
39 TEMP_CHANNEL
40 }
41}
42
43/// Internal battery voltage channel.
44pub struct Vbat;
45impl<T: Instance> AdcChannel<T> for Vbat {}
46impl<T: Instance> SealedAdcChannel<T> for Vbat {
47 fn channel(&self) -> u8 {
48 VBAT_CHANNEL
49 }
50}
51
52/// Internal DAC channel.
53pub struct Dac;
54impl<T: Instance> AdcChannel<T> for Dac {}
55impl<T: Instance> SealedAdcChannel<T> for Dac {
56 fn channel(&self) -> u8 {
57 DAC_CHANNEL
58 }
59}
60
61/// Internal Vcore channel.
62pub struct Vcore;
63impl<T: Instance> AdcChannel<T> for Vcore {}
64impl<T: Instance> SealedAdcChannel<T> for Vcore {
65 fn channel(&self) -> u8 {
66 VCORE_CHANNEL
67 }
68}
69
70pub enum DacChannel {
71 OUT1,
72 OUT2,
73}
74
75/// Number of samples used for averaging.
76pub enum Averaging {
77 Disabled,
78 Samples2,
79 Samples4,
80 Samples8,
81 Samples16,
82 Samples32,
83 Samples64,
84 Samples128,
85 Samples256,
86}
87
88pub const fn resolution_to_max_count(res: Resolution) -> u32 {
89 match res {
90 Resolution::BITS12 => (1 << 12) - 1,
91 Resolution::BITS10 => (1 << 10) - 1,
92 Resolution::BITS8 => (1 << 8) - 1,
93 Resolution::BITS6 => (1 << 6) - 1,
94 #[allow(unreachable_patterns)]
95 _ => core::unreachable!(),
96 }
97}
98
99// NOTE (unused): The prescaler enum closely copies the hardware capabilities,
100// but high prescaling doesn't make a lot of sense in the current implementation and is ommited.
101#[allow(unused)]
102enum Prescaler {
103 NotDivided,
104 DividedBy2,
105 DividedBy4,
106 DividedBy6,
107 DividedBy8,
108 DividedBy10,
109 DividedBy12,
110 DividedBy16,
111 DividedBy32,
112 DividedBy64,
113 DividedBy128,
114 DividedBy256,
115}
116
117impl Prescaler {
118 fn from_ker_ck(frequency: Hertz) -> Self {
119 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
120 match raw_prescaler {
121 0 => Self::NotDivided,
122 1 => Self::DividedBy2,
123 2..=3 => Self::DividedBy4,
124 4..=5 => Self::DividedBy6,
125 6..=7 => Self::DividedBy8,
126 8..=9 => Self::DividedBy10,
127 10..=11 => Self::DividedBy12,
128 _ => unimplemented!(),
129 }
130 }
131
132 fn divisor(&self) -> u32 {
133 match self {
134 Prescaler::NotDivided => 1,
135 Prescaler::DividedBy2 => 2,
136 Prescaler::DividedBy4 => 4,
137 Prescaler::DividedBy6 => 6,
138 Prescaler::DividedBy8 => 8,
139 Prescaler::DividedBy10 => 10,
140 Prescaler::DividedBy12 => 12,
141 Prescaler::DividedBy16 => 16,
142 Prescaler::DividedBy32 => 32,
143 Prescaler::DividedBy64 => 64,
144 Prescaler::DividedBy128 => 128,
145 Prescaler::DividedBy256 => 256,
146 }
147 }
148
149 fn presc(&self) -> Presc {
150 match self {
151 Prescaler::NotDivided => Presc::DIV1,
152 Prescaler::DividedBy2 => Presc::DIV2,
153 Prescaler::DividedBy4 => Presc::DIV4,
154 Prescaler::DividedBy6 => Presc::DIV6,
155 Prescaler::DividedBy8 => Presc::DIV8,
156 Prescaler::DividedBy10 => Presc::DIV10,
157 Prescaler::DividedBy12 => Presc::DIV12,
158 Prescaler::DividedBy16 => Presc::DIV16,
159 Prescaler::DividedBy32 => Presc::DIV32,
160 Prescaler::DividedBy64 => Presc::DIV64,
161 Prescaler::DividedBy128 => Presc::DIV128,
162 Prescaler::DividedBy256 => Presc::DIV256,
163 }
164 }
165}
166
167pub trait SealedInstance {
168 #[allow(unused)]
169 fn regs() -> crate::pac::adc::Adc4;
170}
171
172pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {
173 type Interrupt: crate::interrupt::typelevel::Interrupt;
174}
175
176pub struct Adc4<'d, T: Instance> {
177 #[allow(unused)]
178 adc: crate::PeripheralRef<'d, T>,
179}
180
181#[derive(Debug)]
182pub enum Adc4Error {
183 InvalidSequence,
184 DMAError,
185}
186
187impl<'d, T: Instance> Adc4<'d, T> {
188 /// Create a new ADC driver.
189 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
190 embassy_hal_internal::into_ref!(adc);
191 rcc::enable_and_reset::<T>();
192 let prescaler = Prescaler::from_ker_ck(T::frequency());
193
194 T::regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
195
196 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
197 info!("ADC4 frequency set to {} Hz", frequency.0);
198
199 if frequency > MAX_ADC_CLK_FREQ {
200 panic!("Maximal allowed frequency for ADC4 is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 );
201 }
202
203 let mut s = Self { adc };
204
205 s.power_up();
206
207 s.calibrate();
208 blocking_delay_us(1);
209
210 s.enable();
211 s.configure();
212
213 s
214 }
215
216 fn power_up(&mut self) {
217 T::regs().isr().modify(|w| {
218 w.set_ldordy(true);
219 });
220 T::regs().cr().modify(|w| {
221 w.set_advregen(true);
222 });
223 while !T::regs().isr().read().ldordy() {}
224
225 T::regs().isr().modify(|w| {
226 w.set_ldordy(true);
227 });
228 }
229
230 fn calibrate(&mut self) {
231 T::regs().cr().modify(|w| w.set_adcal(true));
232 while T::regs().cr().read().adcal() {}
233 T::regs().isr().modify(|w| w.set_eocal(true));
234 }
235
236 fn enable(&mut self) {
237 T::regs().isr().write(|w| w.set_adrdy(true));
238 T::regs().cr().modify(|w| w.set_aden(true));
239 while !T::regs().isr().read().adrdy() {}
240 T::regs().isr().write(|w| w.set_adrdy(true));
241 }
242
243 fn configure(&mut self) {
244 // single conversion mode, software trigger
245 T::regs().cfgr1().modify(|w| {
246 w.set_cont(false);
247 w.set_discen(false);
248 w.set_exten(Adc4Exten::DISABLED);
249 w.set_chselrmod(false);
250 });
251
252 // only use one channel at the moment
253 T::regs().smpr().modify(|w| {
254 for i in 0..24 {
255 w.set_smpsel(i, false);
256 }
257 });
258 }
259
260 /// Enable reading the voltage reference internal channel.
261 pub fn enable_vrefint(&self) -> VrefInt {
262 T::regs().ccr().modify(|w| {
263 w.set_vrefen(true);
264 });
265
266 VrefInt {}
267 }
268
269 /// Enable reading the temperature internal channel.
270 pub fn enable_temperature(&self) -> Temperature {
271 T::regs().ccr().modify(|w| {
272 w.set_vsensesel(true);
273 });
274
275 Temperature {}
276 }
277
278 /// Enable reading the vbat internal channel.
279 pub fn enable_vbat(&self) -> Vbat {
280 T::regs().ccr().modify(|w| {
281 w.set_vbaten(true);
282 });
283
284 Vbat {}
285 }
286
287 /// Enable reading the vbat internal channel.
288 pub fn enable_vcore(&self) -> Vcore {
289 Vcore {}
290 }
291
292 /// Enable reading the vbat internal channel.
293 pub fn enable_dac_channel(&self, dac: DacChannel) -> Dac {
294 let mux;
295 match dac {
296 DacChannel::OUT1 => mux = false,
297 DacChannel::OUT2 => mux = true,
298 }
299 T::regs().or().modify(|w| w.set_chn21sel(mux));
300 Dac {}
301 }
302
303 /// Set the ADC sample time.
304 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
305 T::regs().smpr().modify(|w| {
306 w.set_smp(0, sample_time);
307 });
308 }
309
310 /// Get the ADC sample time.
311 pub fn sample_time(&self) -> SampleTime {
312 T::regs().smpr().read().smp(0)
313 }
314
315 /// Set the ADC resolution.
316 pub fn set_resolution(&mut self, resolution: Resolution) {
317 T::regs().cfgr1().modify(|w| w.set_res(resolution.into()));
318 }
319
320 /// Set hardware averaging.
321 pub fn set_averaging(&mut self, averaging: Averaging) {
322 let (enable, samples, right_shift) = match averaging {
323 Averaging::Disabled => (false, Adc4OversamplingRatio::OVERSAMPLE2X, 0),
324 Averaging::Samples2 => (true, Adc4OversamplingRatio::OVERSAMPLE2X, 1),
325 Averaging::Samples4 => (true, Adc4OversamplingRatio::OVERSAMPLE4X, 2),
326 Averaging::Samples8 => (true, Adc4OversamplingRatio::OVERSAMPLE8X, 3),
327 Averaging::Samples16 => (true, Adc4OversamplingRatio::OVERSAMPLE16X, 4),
328 Averaging::Samples32 => (true, Adc4OversamplingRatio::OVERSAMPLE32X, 5),
329 Averaging::Samples64 => (true, Adc4OversamplingRatio::OVERSAMPLE64X, 6),
330 Averaging::Samples128 => (true, Adc4OversamplingRatio::OVERSAMPLE128X, 7),
331 Averaging::Samples256 => (true, Adc4OversamplingRatio::OVERSAMPLE256X, 8),
332 };
333
334 T::regs().cfgr2().modify(|w| {
335 w.set_ovsr(samples);
336 w.set_ovss(right_shift);
337 w.set_ovse(enable)
338 })
339 }
340
341 /// Read an ADC channel.
342 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
343 channel.setup();
344
345 // Select channel
346 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
347 T::regs().chselrmod0().modify(|w| {
348 w.set_chsel(channel.channel() as usize, true);
349 });
350
351 // Reset interrupts
352 T::regs().isr().modify(|reg| {
353 reg.set_eos(true);
354 reg.set_eoc(true);
355 });
356
357 // Start conversion
358 T::regs().cr().modify(|reg| {
359 reg.set_adstart(true);
360 });
361
362 while !T::regs().isr().read().eos() {
363 // spin
364 }
365
366 T::regs().dr().read().0 as u16
367 }
368
369 /// Read one or multiple ADC channels using DMA.
370 ///
371 /// `sequence` iterator and `readings` must have the same length.
372 /// The channels in `sequence` must be in ascending order.
373 ///
374 /// Example
375 /// ```rust,ignore
376 /// use embassy_stm32::adc::adc4;
377 /// use embassy_stm32::adc::AdcChannel;
378 ///
379 /// let mut adc4 = adc4::Adc4::new(p.ADC4);
380 /// let mut adc4_pin1 = p.PC1;
381 /// let mut adc4_pin2 = p.PC0;
382 /// let mut degraded41 = adc4_pin1.degrade_adc();
383 /// let mut degraded42 = adc4_pin2.degrade_adc();
384 /// let mut measurements = [0u16; 2];
385 /// // not that the channels must be in ascending order
386 /// adc4.read(
387 /// &mut p.GPDMA1_CH1,
388 /// [
389 /// &mut degraded42,
390 /// &mut degraded41,
391 /// ]
392 /// .into_iter(),
393 /// &mut measurements,
394 /// ).await.unwrap();
395 /// ```
396 pub async fn read(
397 &mut self,
398 rx_dma: &mut impl RxDma4<T>,
399 sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
400 readings: &mut [u16],
401 ) -> Result<(), Adc4Error> {
402 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
403 assert!(
404 sequence.len() == readings.len(),
405 "Sequence length must be equal to readings length"
406 );
407
408 // Ensure no conversions are ongoing
409 Self::cancel_conversions();
410
411 T::regs().isr().modify(|reg| {
412 reg.set_ovr(true);
413 reg.set_eos(true);
414 reg.set_eoc(true);
415 });
416
417 T::regs().cfgr1().modify(|reg| {
418 reg.set_dmaen(true);
419 reg.set_dmacfg(Adc4Dmacfg::ONE_SHOT);
420 reg.set_chselrmod(false);
421 });
422
423 // Verify and activate sequence
424 let mut prev_channel: i16 = -1;
425 T::regs().chselrmod0().write_value(Adc4Chselrmod0(0_u32));
426 for channel in sequence {
427 let channel_num = channel.channel;
428 if channel_num as i16 <= prev_channel {
429 return Err(Adc4Error::InvalidSequence);
430 };
431 prev_channel = channel_num as i16;
432
433 T::regs().chselrmod0().modify(|w| {
434 w.set_chsel(channel.channel as usize, true);
435 });
436 }
437
438 let request = rx_dma.request();
439 let transfer = unsafe {
440 Transfer::new_read(
441 rx_dma,
442 request,
443 T::regs().dr().as_ptr() as *mut u16,
444 readings,
445 Default::default(),
446 )
447 };
448
449 // Start conversion
450 T::regs().cr().modify(|reg| {
451 reg.set_adstart(true);
452 });
453
454 transfer.await;
455
456 // Ensure conversions are finished.
457 Self::cancel_conversions();
458
459 // Reset configuration.
460 T::regs().cfgr1().modify(|reg| {
461 reg.set_dmaen(false);
462 });
463
464 if T::regs().isr().read().ovr() {
465 Err(Adc4Error::DMAError)
466 } else {
467 Ok(())
468 }
469 }
470
471 fn cancel_conversions() {
472 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
473 T::regs().cr().modify(|reg| {
474 reg.set_adstp(true);
475 });
476 while T::regs().cr().read().adstart() {}
477 }
478 }
479}
480