aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
authorkalkyl <[email protected]>2024-06-05 09:42:08 +0200
committerkalkyl <[email protected]>2024-06-05 09:42:08 +0200
commitbf36bec9bb85caea613687ab9e0c1652f414b95c (patch)
tree80a8f818648742dabff97fd2c27053e7211e1077 /embassy-rp
parent5f9bc6def7ea8698a6ce45d8e12e1d1bd8cce876 (diff)
rp: Add multichannel ADC
Diffstat (limited to 'embassy-rp')
-rw-r--r--embassy-rp/src/adc.rs71
1 files changed, 66 insertions, 5 deletions
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index 101c5b71f..be453d08e 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -221,16 +221,26 @@ impl<'d> Adc<'d, Async> {
221 221
222 async fn read_many_inner<W: dma::Word>( 222 async fn read_many_inner<W: dma::Word>(
223 &mut self, 223 &mut self,
224 ch: &mut Channel<'_>, 224 channels: impl Iterator<Item = u8>,
225 buf: &mut [W], 225 buf: &mut [W],
226 fcs_err: bool, 226 fcs_err: bool,
227 div: u16, 227 div: u16,
228 dma: impl Peripheral<P = impl dma::Channel>, 228 dma: impl Peripheral<P = impl dma::Channel>,
229 ) -> Result<(), Error> { 229 ) -> Result<(), Error> {
230 let mut rrobin = 0_u8;
231 for c in channels {
232 rrobin |= 1 << c;
233 }
234 let first_ch = rrobin.trailing_zeros() as u8;
235 if rrobin.count_ones() == 1 {
236 rrobin = 0;
237 }
238
230 let r = Self::regs(); 239 let r = Self::regs();
231 // clear previous errors and set channel 240 // clear previous errors and set channel
232 r.cs().modify(|w| { 241 r.cs().modify(|w| {
233 w.set_ainsel(ch.channel()); 242 w.set_ainsel(first_ch);
243 w.set_rrobin(rrobin);
234 w.set_err_sticky(true); // clear previous errors 244 w.set_err_sticky(true); // clear previous errors
235 w.set_start_many(false); 245 w.set_start_many(false);
236 }); 246 });
@@ -283,7 +293,49 @@ impl<'d> Adc<'d, Async> {
283 } 293 }
284 } 294 }
285 295
296 /// Sample multiple values from multiple channels using DMA.
297 /// Samples are stored in an interleaved fashion inside the buffer.
298 /// `div` is the integer part of the clock divider and can be calculated with `floor(48MHz / sample_rate * num_channels - 1)`
299 /// Any `div` value of less than 96 will have the same effect as setting it to 0
300 #[inline]
301 pub async fn read_many_multichannel<S: AdcSample>(
302 &mut self,
303 ch: &mut [Channel<'_>],
304 buf: &mut [S],
305 div: u16,
306 dma: impl Peripheral<P = impl dma::Channel>,
307 ) -> Result<(), Error> {
308 self.read_many_inner(ch.iter().map(|c| c.channel()), buf, false, div, dma)
309 .await
310 }
311
312 /// Sample multiple values from multiple channels using DMA, with errors inlined in samples.
313 /// Samples are stored in an interleaved fashion inside the buffer.
314 /// `div` is the integer part of the clock divider and can be calculated with `floor(48MHz / sample_rate * num_channels - 1)`
315 /// Any `div` value of less than 96 will have the same effect as setting it to 0
316 #[inline]
317 pub async fn read_many_multichannel_raw(
318 &mut self,
319 ch: &mut [Channel<'_>],
320 buf: &mut [Sample],
321 div: u16,
322 dma: impl Peripheral<P = impl dma::Channel>,
323 ) {
324 // errors are reported in individual samples
325 let _ = self
326 .read_many_inner(
327 ch.iter().map(|c| c.channel()),
328 unsafe { mem::transmute::<_, &mut [u16]>(buf) },
329 true,
330 div,
331 dma,
332 )
333 .await;
334 }
335
286 /// Sample multiple values from a channel using DMA. 336 /// Sample multiple values from a channel using DMA.
337 /// `div` is the integer part of the clock divider and can be calculated with `floor(48MHz / sample_rate - 1)`
338 /// Any `div` value of less than 96 will have the same effect as setting it to 0
287 #[inline] 339 #[inline]
288 pub async fn read_many<S: AdcSample>( 340 pub async fn read_many<S: AdcSample>(
289 &mut self, 341 &mut self,
@@ -292,10 +344,13 @@ impl<'d> Adc<'d, Async> {
292 div: u16, 344 div: u16,
293 dma: impl Peripheral<P = impl dma::Channel>, 345 dma: impl Peripheral<P = impl dma::Channel>,
294 ) -> Result<(), Error> { 346 ) -> Result<(), Error> {
295 self.read_many_inner(ch, buf, false, div, dma).await 347 self.read_many_inner([ch.channel()].into_iter(), buf, false, div, dma)
348 .await
296 } 349 }
297 350
298 /// Sample multiple values from a channel using DMA with errors inlined in samples. 351 /// Sample multiple values from a channel using DMA, with errors inlined in samples.
352 /// `div` is the integer part of the clock divider and can be calculated with `floor(48MHz / sample_rate - 1)`
353 /// Any `div` value of less than 96 will have the same effect as setting it to 0
299 #[inline] 354 #[inline]
300 pub async fn read_many_raw( 355 pub async fn read_many_raw(
301 &mut self, 356 &mut self,
@@ -306,7 +361,13 @@ impl<'d> Adc<'d, Async> {
306 ) { 361 ) {
307 // errors are reported in individual samples 362 // errors are reported in individual samples
308 let _ = self 363 let _ = self
309 .read_many_inner(ch, unsafe { mem::transmute::<_, &mut [u16]>(buf) }, true, div, dma) 364 .read_many_inner(
365 [ch.channel()].into_iter(),
366 unsafe { mem::transmute::<_, &mut [u16]>(buf) },
367 true,
368 div,
369 dma,
370 )
310 .await; 371 .await;
311 } 372 }
312} 373}