1use core::marker::PhantomData;
6use core::mem;
7use core::sync::atomic::{compiler_fence, Ordering};
8
9use embassy_hal_internal::{into_ref, Peripheral};
10use py32_metapac::adc::vals::SampleTime;
11
12use crate::adc::{Adc, AdcChannel, Instance, RxDma};
13use crate::dma::{Priority, ReadableRingBuffer, TransferOptions};
14use crate::rcc;
15
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct OverrunError;
18
19fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
20 r.sr().modify(|regs| {
21 regs.set_eoc(false);
22 regs.set_ovr(false);
23 });
24}
25
26#[derive(PartialOrd, PartialEq, Debug, Clone, Copy)]
27pub enum Sequence {
28 One,
29 Two,
30 Three,
31 Four,
32 Five,
33 Six,
34 Seven,
35 Eight,
36 Nine,
37 Ten,
38 Eleven,
39 Twelve,
40 Thirteen,
41 Fourteen,
42 Fifteen,
43 Sixteen,
44}
45
46impl From<Sequence> for u8 {
47 fn from(s: Sequence) -> u8 {
48 match s {
49 Sequence::One => 0,
50 Sequence::Two => 1,
51 Sequence::Three => 2,
52 Sequence::Four => 3,
53 Sequence::Five => 4,
54 Sequence::Six => 5,
55 Sequence::Seven => 6,
56 Sequence::Eight => 7,
57 Sequence::Nine => 8,
58 Sequence::Ten => 9,
59 Sequence::Eleven => 10,
60 Sequence::Twelve => 11,
61 Sequence::Thirteen => 12,
62 Sequence::Fourteen => 13,
63 Sequence::Fifteen => 14,
64 Sequence::Sixteen => 15,
65 }
66 }
67}
68
69impl From<u8> for Sequence {
70 fn from(val: u8) -> Self {
71 match val {
72 0 => Sequence::One,
73 1 => Sequence::Two,
74 2 => Sequence::Three,
75 3 => Sequence::Four,
76 4 => Sequence::Five,
77 5 => Sequence::Six,
78 6 => Sequence::Seven,
79 7 => Sequence::Eight,
80 8 => Sequence::Nine,
81 9 => Sequence::Ten,
82 10 => Sequence::Eleven,
83 11 => Sequence::Twelve,
84 12 => Sequence::Thirteen,
85 13 => Sequence::Fourteen,
86 14 => Sequence::Fifteen,
87 15 => Sequence::Sixteen,
88 _ => panic!("Invalid sequence number"),
89 }
90 }
91}
92
93pub struct RingBufferedAdc<'d, T: Instance> {
94 _phantom: PhantomData<T>,
95 ring_buf: ReadableRingBuffer<'d, u16>,
96}
97
98impl<'d, T: Instance> Adc<'d, T> {
99 pub fn into_ring_buffered(
110 self,
111 dma: impl Peripheral<P = impl RxDma<T>> + 'd,
112 dma_buf: &'d mut [u16],
113 ) -> RingBufferedAdc<'d, T> {
114 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
115 into_ref!(dma);
116
117 let opts: crate::dma::TransferOptions = TransferOptions {
118 half_transfer_ir: true,
119 priority: Priority::VeryHigh,
120 ..Default::default()
121 };
122
123 let rx_src = T::regs().dr().as_ptr() as *mut u16;
125 let request = dma.request();
126
127 let ring_buf = unsafe { ReadableRingBuffer::new(dma, request, rx_src, dma_buf, opts) };
128
129 mem::forget(self);
131
132 RingBufferedAdc {
133 _phantom: PhantomData,
134 ring_buf,
135 }
136 }
137}
138
139impl<'d, T: Instance> RingBufferedAdc<'d, T> {
140 fn is_on() -> bool {
141 T::regs().cr2().read().adon()
142 }
143
144 fn stop_adc() {
145 T::regs().cr2().modify(|reg| {
146 reg.set_adon(false);
147 });
148 }
149
150 fn start_adc() {
151 T::regs().cr2().modify(|reg| {
152 reg.set_adon(true);
153 });
154 }
155
156 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
161 if ch <= 9 {
162 T::regs()
163 .smpr2()
164 .modify(|reg| reg.set_smp(ch as _, sample_time));
165 } else {
166 T::regs()
167 .smpr1()
168 .modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
169 }
170 }
171
172 fn set_channels_sample_time(&mut self, ch: &[u8], sample_time: SampleTime) {
173 let ch_iter = ch.iter();
174 for idx in ch_iter {
175 unsafe {
176 Self::set_channel_sample_time(*idx, sample_time);
177 }
178 }
179 }
180
181 pub fn set_sample_sequence(
182 &mut self,
183 sequence: Sequence,
184 channel: &mut impl AdcChannel<T>,
185 sample_time: SampleTime,
186 ) {
187 let was_on = Self::is_on();
188 if !was_on {
189 Self::start_adc();
190 }
191
192 T::regs().sqr1().modify(|r| {
194 let prev: Sequence = r.l().into();
195 if prev < sequence {
196 let new_l: Sequence = sequence;
197 trace!(
198 "Setting sequence length from {:?} to {:?}",
199 prev as u8,
200 new_l as u8
201 );
202 r.set_l(sequence.into())
203 } else {
204 r.set_l(prev.into())
205 }
206 });
207
208 channel.setup();
210
211 match sequence {
213 Sequence::One => T::regs().sqr3().modify(|w| w.set_sq(0, channel.channel())),
214 Sequence::Two => T::regs().sqr3().modify(|w| w.set_sq(1, channel.channel())),
215 Sequence::Three => T::regs().sqr3().modify(|w| w.set_sq(2, channel.channel())),
216 Sequence::Four => T::regs().sqr3().modify(|w| w.set_sq(3, channel.channel())),
217 Sequence::Five => T::regs().sqr3().modify(|w| w.set_sq(4, channel.channel())),
218 Sequence::Six => T::regs().sqr3().modify(|w| w.set_sq(5, channel.channel())),
219 Sequence::Seven => T::regs().sqr2().modify(|w| w.set_sq(6, channel.channel())),
220 Sequence::Eight => T::regs().sqr2().modify(|w| w.set_sq(7, channel.channel())),
221 Sequence::Nine => T::regs().sqr2().modify(|w| w.set_sq(8, channel.channel())),
222 Sequence::Ten => T::regs().sqr2().modify(|w| w.set_sq(9, channel.channel())),
223 Sequence::Eleven => T::regs().sqr2().modify(|w| w.set_sq(10, channel.channel())),
224 Sequence::Twelve => T::regs().sqr2().modify(|w| w.set_sq(11, channel.channel())),
225 Sequence::Thirteen => T::regs().sqr1().modify(|w| w.set_sq(12, channel.channel())),
226 Sequence::Fourteen => T::regs().sqr1().modify(|w| w.set_sq(13, channel.channel())),
227 Sequence::Fifteen => T::regs().sqr1().modify(|w| w.set_sq(14, channel.channel())),
228 Sequence::Sixteen => T::regs().sqr1().modify(|w| w.set_sq(15, channel.channel())),
229 };
230
231 if !was_on {
232 Self::stop_adc();
233 }
234
235 self.set_channels_sample_time(&[channel.channel()], sample_time);
236
237 Self::start_adc();
238 }
239
240 pub fn start(&mut self) -> Result<(), OverrunError> {
242 self.setup_adc();
243 self.ring_buf.clear();
244
245 Ok(())
246 }
247
248 fn stop(&mut self, err: OverrunError) -> Result<usize, OverrunError> {
249 self.teardown_adc();
250 Err(err)
251 }
252
253 pub fn teardown_adc(&mut self) {
259 self.ring_buf.request_pause();
261
262 let r = T::regs();
263
264 r.cr2().modify(|reg| {
266 reg.set_swstart(false);
268 reg.set_dma(false);
270 });
271
272 r.cr1().modify(|w| {
273 w.set_eocie(false);
275 w.set_ovrie(false);
277 });
278
279 clear_interrupt_flags(r);
280
281 compiler_fence(Ordering::SeqCst);
282 }
283
284 fn setup_adc(&mut self) {
285 compiler_fence(Ordering::SeqCst);
286
287 self.ring_buf.start();
288
289 let r = T::regs();
290
291 let was_on = Self::is_on();
293 if !was_on {
294 r.cr2().modify(|reg| {
295 reg.set_adon(false);
296 reg.set_swstart(false);
297 });
298 }
299
300 r.sr().modify(|regs| {
302 regs.set_eoc(false);
303 regs.set_ovr(false);
304 regs.set_strt(false);
305 });
306
307 r.cr1().modify(|w| {
308 w.set_eocie(true);
310 w.set_ovrie(true);
312 w.set_scan(true);
314 w.set_discen(false);
316 });
317
318 r.cr2().modify(|w| {
319 w.set_dma(true);
321 w.set_cont(true);
323 });
324
325 T::regs().cr2().modify(|reg| {
327 reg.set_adon(true);
328 reg.set_swstart(true);
329 reg.set_exttrig(true);
330 });
331
332 super::blocking_delay_us(3);
333 }
334
335 pub fn blocking_read<const N: usize>(
344 &mut self,
345 buf: &mut [u16; N],
346 ) -> Result<usize, OverrunError> {
347 let r = T::regs();
348
349 if !r.cr2().read().dma() {
351 self.start()?;
352 }
353
354 if r.sr().read().ovr() {
356 return self.stop(OverrunError);
357 }
358
359 loop {
360 match self.ring_buf.read(buf) {
361 Ok((0, _)) => {}
362 Ok((len, _)) => {
363 return Ok(len);
364 }
365 Err(_) => {
366 return self.stop(OverrunError);
367 }
368 }
369 }
370 }
371
372 pub async fn read<const N: usize>(
420 &mut self,
421 measurements: &mut [u16; N],
422 ) -> Result<usize, OverrunError> {
423 assert_eq!(
424 self.ring_buf.capacity() / 2,
425 N,
426 "Buffer size must be half the size of the ring buffer"
427 );
428
429 let r = T::regs();
430
431 if !r.cr2().read().dma() {
433 self.start()?;
434 }
435
436 if r.sr().read().ovr() {
438 return self.stop(OverrunError);
439 }
440 match self.ring_buf.read_exact(measurements).await {
441 Ok(len) => Ok(len),
442 Err(_) => self.stop(OverrunError),
443 }
444 }
445}
446
447impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
448 fn drop(&mut self) {
449 self.teardown_adc();
450 rcc::disable::<T>();
451 }
452}