aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/saadc.rs73
-rw-r--r--examples/nrf/src/bin/saadc_continuous.rs4
2 files changed, 55 insertions, 22 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 273eff799..af45a8033 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -110,20 +110,6 @@ impl<'d> ChannelConfig<'d> {
110 } 110 }
111} 111}
112 112
113/// A sample rate can be provided for the internal clock of the SAADC when
114/// one channel is to be continuously sampled. When there are multiple channels
115/// to be continuously sampled then an external source is used to generate
116/// TASK_SAMPLE tasks.
117pub enum Mode {
118 /// The internal clock is to be used with a sample rate expressed as a divisor of
119 /// 16MHz, ranging from 80..2047. For example, 1600 represnts a sample rate of 10KHz
120 /// given 16_000_000 / 10_000_000 = 1600.
121 Timers(u16),
122 /// TASK_SAMPLE tasks are generated outside of the SAADC e.g. via PPI on a
123 /// timer.
124 Task,
125}
126
127/// The state of a continuously running sampler. While it reflects 113/// The state of a continuously running sampler. While it reflects
128/// the progress of a sampler, it also signals what should be done 114/// the progress of a sampler, it also signals what should be done
129/// next. For example, if the sampler has stopped then the Saadc implementation 115/// next. For example, if the sampler has stopped then the Saadc implementation
@@ -254,14 +240,61 @@ impl<'d, const N: usize> Saadc<'d, N> {
254 /// Continuous sampling with double buffers. The sample buffers generally 240 /// Continuous sampling with double buffers. The sample buffers generally
255 /// should be a multiple of the number of channels configured. 241 /// should be a multiple of the number of channels configured.
256 /// 242 ///
243 /// The internal clock is to be used with a sample rate expressed as a divisor of
244 /// 16MHz, ranging from 80..2047. For example, 1600 represnts a sample rate of 10KHz
245 /// given 16_000_000 / 10_000_000 = 1600.
246 ///
257 /// A sampler closure is provided that receives the buffer of samples, noting 247 /// A sampler closure is provided that receives the buffer of samples, noting
258 /// that the size of this buffer can be less than the original buffer's size. 248 /// that the size of this buffer can be less than the original buffer's size.
259 /// A command is return from the closure that indicates whether the sampling 249 /// A command is return from the closure that indicates whether the sampling
260 /// should continue or stop. 250 /// should continue or stop.
261 pub async fn run_sampler<S, const N0: usize>( 251 pub async fn run_timer_sampler<S, const N0: usize>(
252 &mut self,
253 bufs: &mut [[i16; N0]; 2],
254 sample_rate: u16,
255 sampler: S,
256 ) where
257 S: FnMut(&[i16]) -> SamplerState,
258 {
259 assert!(
260 N == 1,
261 "The internal timer can only be used with one channel"
262 );
263 assert!(
264 N0 % N == 0,
265 "The buffer size must be a multiple of the number of channels"
266 );
267 self.run_sampler(bufs, Some(sample_rate), sampler).await;
268 }
269
270 /// Continuous sampling with double buffers. The sample buffers generally
271 /// should be a multiple of the number of channels configured.
272 ///
273 /// A task-driven approach to driving TASK_SAMPLE is expected. With a task
274 /// driven approach, multiple channels can be used.
275 ///
276 /// A sampler closure is provided that receives the buffer of samples, noting
277 /// that the size of this buffer can be less than the original buffer's size.
278 /// A command is return from the closure that indicates whether the sampling
279 /// should continue or stop.
280 pub async fn run_task_sampler<S, const N0: usize>(
281 &mut self,
282 bufs: &mut [[i16; N0]; 2],
283 sampler: S,
284 ) where
285 S: FnMut(&[i16]) -> SamplerState,
286 {
287 assert!(
288 N0 % N == 0,
289 "The buffer size must be a multiple of the number of channels"
290 );
291 self.run_sampler(bufs, None, sampler).await;
292 }
293
294 async fn run_sampler<S, const N0: usize>(
262 &mut self, 295 &mut self,
263 bufs: &mut [[i16; N0]; 2], 296 bufs: &mut [[i16; N0]; 2],
264 mode: Mode, 297 sample_rate: Option<u16>,
265 mut sampler: S, 298 mut sampler: S,
266 ) where 299 ) where
267 S: FnMut(&[i16]) -> SamplerState, 300 S: FnMut(&[i16]) -> SamplerState,
@@ -269,16 +302,16 @@ impl<'d, const N: usize> Saadc<'d, N> {
269 let r = Self::regs(); 302 let r = Self::regs();
270 303
271 // Establish mode and sample rate 304 // Establish mode and sample rate
272 match mode { 305 match sample_rate {
273 Mode::Timers(sample_rate) => { 306 Some(sr) => {
274 r.samplerate.write(|w| unsafe { 307 r.samplerate.write(|w| unsafe {
275 w.cc().bits(sample_rate); 308 w.cc().bits(sr);
276 w.mode().timers(); 309 w.mode().timers();
277 w 310 w
278 }); 311 });
279 r.tasks_sample.write(|w| unsafe { w.bits(1) }); // Need to kick-start the internal timer 312 r.tasks_sample.write(|w| unsafe { w.bits(1) }); // Need to kick-start the internal timer
280 } 313 }
281 Mode::Task => r.samplerate.write(|w| unsafe { 314 None => r.samplerate.write(|w| unsafe {
282 w.cc().bits(0); 315 w.cc().bits(0);
283 w.mode().task(); 316 w.mode().task();
284 w 317 w
diff --git a/examples/nrf/src/bin/saadc_continuous.rs b/examples/nrf/src/bin/saadc_continuous.rs
index dfcb46171..d936a7d21 100644
--- a/examples/nrf/src/bin/saadc_continuous.rs
+++ b/examples/nrf/src/bin/saadc_continuous.rs
@@ -7,7 +7,7 @@ mod example_common;
7use defmt::panic; 7use defmt::panic;
8use embassy::executor::Spawner; 8use embassy::executor::Spawner;
9use embassy_nrf::ppi::Ppi; 9use embassy_nrf::ppi::Ppi;
10use embassy_nrf::saadc::{ChannelConfig, Config, Mode, Saadc, SamplerState}; 10use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState};
11use embassy_nrf::timer::{Frequency, Timer}; 11use embassy_nrf::timer::{Frequency, Timer};
12use embassy_nrf::{interrupt, Peripherals}; 12use embassy_nrf::{interrupt, Peripherals};
13use example_common::*; 13use example_common::*;
@@ -45,7 +45,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) {
45 let mut a: i32 = 0; 45 let mut a: i32 = 0;
46 46
47 saadc 47 saadc
48 .run_sampler(&mut bufs, Mode::Task, move |buf| { 48 .run_task_sampler(&mut bufs, move |buf| {
49 for (i, b) in buf.iter().enumerate() { 49 for (i, b) in buf.iter().enumerate() {
50 if i % 3 == 0 { 50 if i % 3 == 0 {
51 a += *b as i32; 51 a += *b as i32;