aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhuntc <[email protected]>2022-03-07 12:45:37 +1100
committerhuntc <[email protected]>2022-03-07 14:51:17 +1100
commit3990f09b2927ca8062482680f4caba04e0cb78a7 (patch)
tree37b8743495f27444477f790d2f2838b8ca31b169
parent98bdac51fe24c48ba097fcba3ec705f9da7df783 (diff)
Simplifies the API by taking in the TIMER and PPI channels
-rw-r--r--embassy-nrf/src/saadc.rs92
-rw-r--r--examples/nrf/src/bin/saadc_continuous.rs26
2 files changed, 59 insertions, 59 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index dcc7e86a2..c4de7315f 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -10,7 +10,8 @@ use embassy_hal_common::unborrow;
10use futures::future::poll_fn; 10use futures::future::poll_fn;
11 11
12use crate::interrupt; 12use crate::interrupt;
13use crate::ppi::{Event, Task}; 13use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
14use crate::timer::{Frequency, Instance as TimerInstance, Timer};
14use crate::{pac, peripherals}; 15use crate::{pac, peripherals};
15 16
16use pac::{saadc, SAADC}; 17use pac::{saadc, SAADC};
@@ -297,36 +298,67 @@ impl<'d, const N: usize> Saadc<'d, N> {
297 298
298 /// Continuous sampling with double buffers. 299 /// Continuous sampling with double buffers.
299 /// 300 ///
300 /// NOTE: It is important that the time spent within the callback supplied 301 /// A TIMER and two PPI peripherals are passed in so that precise sampling
301 /// does not exceed the time taken to acquire the samples into a single buffer. 302 /// can be attained. The sampling interval is expressed by selecting a
302 /// You should measure the time taken by the callback and set the sample buffer 303 /// timer clock frequency to use along with a counter threshold to be reached.
303 /// size accordingly. Exceeding this time can lead to the peripheral re-writing 304 /// For example, 1KHz can be achieved using a frequency of 1MHz and a counter
304 /// the other buffer. 305 /// threshold of 1000.
305 ///
306 /// A task-driven approach to driving TASK_SAMPLE is expected. With a task
307 /// driven approach, multiple channels can be used.
308 ///
309 /// In addition, the caller is responsible for triggering TASK_START in
310 /// relation to the previous one having ended (EVENTS_END). The the initial
311 /// TASKS_START is triggered by this method.
312 ///
313 /// A closure is provided so that any required initialization such as starting
314 /// the sampling task can occur once the peripheral has been started.
315 /// 306 ///
316 /// A sampler closure is provided that receives the buffer of samples, noting 307 /// A sampler closure is provided that receives the buffer of samples, noting
317 /// that the size of this buffer can be less than the original buffer's size. 308 /// that the size of this buffer can be less than the original buffer's size.
318 /// A command is return from the closure that indicates whether the sampling 309 /// A command is return from the closure that indicates whether the sampling
319 /// should continue or stop. 310 /// should continue or stop.
320 pub async fn run_task_sampler<I, S, const N0: usize>( 311 ///
312 /// NOTE: The time spent within the callback supplied should not exceed the time
313 /// taken to acquire the samples into a single buffer. You should measure the
314 /// time taken by the callback and set the sample buffer size accordingly.
315 /// Exceeding this time can lead to samples becoming dropped.
316 pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>(
321 &mut self, 317 &mut self,
318 timer: &mut T,
319 ppi_ch1: &mut impl ConfigurableChannel,
320 ppi_ch2: &mut impl ConfigurableChannel,
321 frequency: Frequency,
322 sample_counter: u32,
322 bufs: &mut [[[i16; N]; N0]; 2], 323 bufs: &mut [[[i16; N]; N0]; 2],
323 init: I,
324 sampler: S, 324 sampler: S,
325 ) where 325 ) where
326 I: FnMut(),
327 S: FnMut(&[[i16; N]]) -> SamplerState, 326 S: FnMut(&[[i16; N]]) -> SamplerState,
328 { 327 {
329 self.run_sampler(bufs, None, init, sampler).await; 328 let r = Self::regs();
329
330 // We want the task start to effectively short with the last one ending so
331 // we don't miss any samples. It'd be great for the SAADC to offer a SHORTS
332 // register instead, but it doesn't, so we must use PPI.
333 let mut start_ppi = Ppi::new_one_to_one(
334 ppi_ch1,
335 Event::from_reg(&r.events_end),
336 Task::from_reg(&r.tasks_start),
337 );
338 start_ppi.enable();
339
340 let mut timer = Timer::new(timer);
341 timer.set_frequency(frequency);
342 timer.cc(0).write(sample_counter);
343 timer.cc(0).short_compare_clear();
344
345 let mut sample_ppi = Ppi::new_one_to_one(
346 ppi_ch2,
347 timer.cc(0).event_compare(),
348 Task::from_reg(&r.tasks_sample),
349 );
350
351 timer.start();
352
353 self.run_sampler(
354 bufs,
355 None,
356 || {
357 sample_ppi.enable();
358 },
359 sampler,
360 )
361 .await;
330 } 362 }
331 363
332 async fn run_sampler<I, S, const N0: usize>( 364 async fn run_sampler<I, S, const N0: usize>(
@@ -424,31 +456,13 @@ impl<'d, const N: usize> Saadc<'d, N> {
424 }) 456 })
425 .await; 457 .await;
426 } 458 }
427
428 /// Return the end event for use with PPI
429 pub fn event_end(&self) -> Event {
430 let r = Self::regs();
431 Event::from_reg(&r.events_end)
432 }
433
434 /// Return the sample task for use with PPI
435 pub fn task_sample(&self) -> Task {
436 let r = Self::regs();
437 Task::from_reg(&r.tasks_sample)
438 }
439
440 /// Return the start task for use with PPI
441 pub fn task_start(&self) -> Task {
442 let r = Self::regs();
443 Task::from_reg(&r.tasks_start)
444 }
445} 459}
446 460
447impl<'d> Saadc<'d, 1> { 461impl<'d> Saadc<'d, 1> {
448 /// Continuous sampling on a single channel with double buffers. 462 /// Continuous sampling on a single channel with double buffers.
449 /// 463 ///
450 /// The internal clock is to be used with a sample rate expressed as a divisor of 464 /// The internal clock is to be used with a sample rate expressed as a divisor of
451 /// 16MHz, ranging from 80..2047. For example, 1600 represnts a sample rate of 10KHz 465 /// 16MHz, ranging from 80..2047. For example, 1600 represents a sample rate of 10KHz
452 /// given 16_000_000 / 10_000_000 = 1600. 466 /// given 16_000_000 / 10_000_000 = 1600.
453 /// 467 ///
454 /// A sampler closure is provided that receives the buffer of samples, noting 468 /// A sampler closure is provided that receives the buffer of samples, noting
diff --git a/examples/nrf/src/bin/saadc_continuous.rs b/examples/nrf/src/bin/saadc_continuous.rs
index 991adabad..bdf552fba 100644
--- a/examples/nrf/src/bin/saadc_continuous.rs
+++ b/examples/nrf/src/bin/saadc_continuous.rs
@@ -6,9 +6,8 @@
6mod example_common; 6mod example_common;
7use embassy::executor::Spawner; 7use embassy::executor::Spawner;
8use embassy::time::Duration; 8use embassy::time::Duration;
9use embassy_nrf::ppi::Ppi;
10use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState}; 9use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState};
11use embassy_nrf::timer::{Frequency, Timer}; 10use embassy_nrf::timer::Frequency;
12use embassy_nrf::{interrupt, Peripherals}; 11use embassy_nrf::{interrupt, Peripherals};
13use example_common::*; 12use example_common::*;
14 13
@@ -27,21 +26,6 @@ async fn main(_spawner: Spawner, mut p: Peripherals) {
27 [channel_1_config, channel_2_config, channel_3_config], 26 [channel_1_config, channel_2_config, channel_3_config],
28 ); 27 );
29 28
30 // We want the task start to effectively short with the last one ending so
31 // we don't miss any samples. The Saadc will trigger the initial TASKS_START.
32 let mut start_ppi = Ppi::new_one_to_one(p.PPI_CH0, saadc.event_end(), saadc.task_start());
33 start_ppi.enable();
34
35 let mut timer = Timer::new(p.TIMER0);
36 timer.set_frequency(Frequency::F1MHz);
37 timer.cc(0).write(1000); // We want to sample at 1KHz
38 timer.cc(0).short_compare_clear();
39
40 let mut sample_ppi =
41 Ppi::new_one_to_one(p.PPI_CH1, timer.cc(0).event_compare(), saadc.task_sample());
42
43 timer.start();
44
45 // This delay demonstrates that starting the timer prior to running 29 // This delay demonstrates that starting the timer prior to running
46 // the task sampler is benign given the calibration that follows. 30 // the task sampler is benign given the calibration that follows.
47 embassy::time::Timer::after(Duration::from_millis(500)).await; 31 embassy::time::Timer::after(Duration::from_millis(500)).await;
@@ -54,10 +38,12 @@ async fn main(_spawner: Spawner, mut p: Peripherals) {
54 38
55 saadc 39 saadc
56 .run_task_sampler( 40 .run_task_sampler(
41 &mut p.TIMER0,
42 &mut p.PPI_CH0,
43 &mut p.PPI_CH1,
44 Frequency::F1MHz,
45 1000, // We want to sample at 1KHz
57 &mut bufs, 46 &mut bufs,
58 || {
59 sample_ppi.enable();
60 },
61 move |buf| { 47 move |buf| {
62 // NOTE: It is important that the time spent within this callback 48 // NOTE: It is important that the time spent within this callback
63 // does not exceed the time taken to acquire the 1500 samples we 49 // does not exceed the time taken to acquire the 1500 samples we