diff options
| author | huntc <[email protected]> | 2021-10-17 06:56:56 +1100 |
|---|---|---|
| committer | huntc <[email protected]> | 2021-10-18 10:26:11 +1100 |
| commit | cb56f52b9952bea266fdcad3a539b6097ddf5079 (patch) | |
| tree | 97404d82c36f658ce3d0389ed3a58ea8c950980c | |
| parent | a020b1a404c8e72d7b5404c595e57d8c04ac8701 (diff) | |
Removed the Mode enum and factored out into two functions so that we can assert channel limits
| -rw-r--r-- | embassy-nrf/src/saadc.rs | 73 | ||||
| -rw-r--r-- | examples/nrf/src/bin/saadc_continuous.rs | 4 |
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. | ||
| 117 | pub 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; | |||
| 7 | use defmt::panic; | 7 | use defmt::panic; |
| 8 | use embassy::executor::Spawner; | 8 | use embassy::executor::Spawner; |
| 9 | use embassy_nrf::ppi::Ppi; | 9 | use embassy_nrf::ppi::Ppi; |
| 10 | use embassy_nrf::saadc::{ChannelConfig, Config, Mode, Saadc, SamplerState}; | 10 | use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState}; |
| 11 | use embassy_nrf::timer::{Frequency, Timer}; | 11 | use embassy_nrf::timer::{Frequency, Timer}; |
| 12 | use embassy_nrf::{interrupt, Peripherals}; | 12 | use embassy_nrf::{interrupt, Peripherals}; |
| 13 | use example_common::*; | 13 | use 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; |
