diff options
| -rw-r--r-- | embassy-nrf/src/pdm.rs | 13 | ||||
| -rw-r--r-- | examples/nrf/src/bin/pdm_continuous.rs | 13 |
2 files changed, 18 insertions, 8 deletions
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 6a070e7bc..b58a0e976 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs | |||
| @@ -9,6 +9,8 @@ use embassy_util::waitqueue::AtomicWaker; | |||
| 9 | use futures::future::poll_fn; | 9 | use futures::future::poll_fn; |
| 10 | use pac::{pdm, PDM}; | 10 | use pac::{pdm, PDM}; |
| 11 | use pdm::mode::{EDGE_A, OPERATION_A}; | 11 | use pdm::mode::{EDGE_A, OPERATION_A}; |
| 12 | pub use pdm::pdmclkctrl::FREQ_A as Frequency; | ||
| 13 | pub use pdm::ratio::RATIO_A as Ratio; | ||
| 12 | use fixed::types::I7F1; | 14 | use fixed::types::I7F1; |
| 13 | 15 | ||
| 14 | use crate::interrupt::InterruptExt; | 16 | use crate::interrupt::InterruptExt; |
| @@ -32,8 +34,10 @@ static WAKER: AtomicWaker = AtomicWaker::new(); | |||
| 32 | /// See the `Default` impl for suitable default values. | 34 | /// See the `Default` impl for suitable default values. |
| 33 | #[non_exhaustive] | 35 | #[non_exhaustive] |
| 34 | pub struct Config { | 36 | pub struct Config { |
| 35 | /// Clock | 37 | /// Clock frequency |
| 38 | pub frequency: Frequency, | ||
| 36 | /// Clock ratio | 39 | /// Clock ratio |
| 40 | pub ratio: Ratio, | ||
| 37 | /// Channels | 41 | /// Channels |
| 38 | pub channels: Channels, | 42 | pub channels: Channels, |
| 39 | /// Edge to sample on | 43 | /// Edge to sample on |
| @@ -48,6 +52,8 @@ impl Default for Config { | |||
| 48 | /// Default configuration for single channel sampling. | 52 | /// Default configuration for single channel sampling. |
| 49 | fn default() -> Self { | 53 | fn default() -> Self { |
| 50 | Self { | 54 | Self { |
| 55 | frequency: Frequency::DEFAULT, | ||
| 56 | ratio: Ratio::RATIO80, | ||
| 51 | channels: Channels::Stereo, | 57 | channels: Channels::Stereo, |
| 52 | left_edge: Edge::FallingEdge, | 58 | left_edge: Edge::FallingEdge, |
| 53 | gain_left: I7F1::ZERO, | 59 | gain_left: I7F1::ZERO, |
| @@ -78,11 +84,12 @@ impl<'d> Pdm<'d> { | |||
| 78 | 84 | ||
| 79 | let r = unsafe { &*PDM::ptr() }; | 85 | let r = unsafe { &*PDM::ptr() }; |
| 80 | 86 | ||
| 81 | let Config { channels, left_edge, gain_left, gain_right } = config; | 87 | let Config { frequency, ratio, channels, left_edge, gain_left, gain_right } = config; |
| 82 | 88 | ||
| 83 | // Configure channels | 89 | // Configure channels |
| 84 | r.enable.write(|w| w.enable().enabled()); | 90 | r.enable.write(|w| w.enable().enabled()); |
| 85 | // TODO: Clock control | 91 | r.pdmclkctrl.write(|w| w.freq().variant(frequency)); |
| 92 | r.ratio.write(|w| w.ratio().variant(ratio)); | ||
| 86 | r.mode.write(|w| { | 93 | r.mode.write(|w| { |
| 87 | w.operation().variant(channels.into()); | 94 | w.operation().variant(channels.into()); |
| 88 | w.edge().variant(left_edge.into()); | 95 | w.edge().variant(left_edge.into()); |
diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index e7d1806bb..33ba1e274 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs | |||
| @@ -5,8 +5,7 @@ | |||
| 5 | use defmt::info; | 5 | use defmt::info; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::interrupt; | 7 | use embassy_nrf::interrupt; |
| 8 | use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; | 8 | use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio}; |
| 9 | use embassy_nrf::timer::Frequency; | ||
| 10 | use fixed::types::I7F1; | 9 | use fixed::types::I7F1; |
| 11 | use num_integer::Roots; | 10 | use num_integer::Roots; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -18,11 +17,13 @@ async fn main(_p: Spawner) { | |||
| 18 | let mut p = embassy_nrf::init(Default::default()); | 17 | let mut p = embassy_nrf::init(Default::default()); |
| 19 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 20 | // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. | 19 | // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. |
| 20 | config.frequency = Frequency::_1280K; // 16 kHz sample rate | ||
| 21 | config.ratio = Ratio::RATIO80; | ||
| 21 | config.channels = Channels::Mono; | 22 | config.channels = Channels::Mono; |
| 22 | config.gain_left = I7F1::from_bits(5); // 2.5 dB | 23 | config.gain_left = I7F1::from_bits(5); // 2.5 dB |
| 23 | let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); | 24 | let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); |
| 24 | 25 | ||
| 25 | let mut bufs = [[0; 500]; 2]; | 26 | let mut bufs = [[0; 1024]; 2]; |
| 26 | 27 | ||
| 27 | pdm | 28 | pdm |
| 28 | .run_task_sampler( | 29 | .run_task_sampler( |
| @@ -34,13 +35,15 @@ async fn main(_p: Spawner) { | |||
| 34 | // sample * 1500 = 18ms. You need to measure the time taken here | 35 | // sample * 1500 = 18ms. You need to measure the time taken here |
| 35 | // and set the sample buffer size accordingly. Exceeding this | 36 | // and set the sample buffer size accordingly. Exceeding this |
| 36 | // time can lead to the peripheral re-writing the other buffer. | 37 | // time can lead to the peripheral re-writing the other buffer. |
| 38 | let mean = (buf.iter().map(|v| i32::from(*v)).sum::<i32>() / buf.len() as i32) as i16; | ||
| 37 | info!( | 39 | info!( |
| 38 | "{} samples, min {=i16}, max {=i16}, RMS {=i16}", | 40 | "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", |
| 39 | buf.len(), | 41 | buf.len(), |
| 40 | buf.iter().min().unwrap(), | 42 | buf.iter().min().unwrap(), |
| 41 | buf.iter().max().unwrap(), | 43 | buf.iter().max().unwrap(), |
| 44 | mean, | ||
| 42 | ( | 45 | ( |
| 43 | buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) | 46 | buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) |
| 44 | / buf.len() as i32).sqrt() as i16, | 47 | / buf.len() as i32).sqrt() as i16, |
| 45 | ); | 48 | ); |
| 46 | SamplerState::Sampled | 49 | SamplerState::Sampled |
