From 199504be564b231154e07c58bcc52b11afdc9fe7 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Tue, 29 Nov 2022 01:09:47 +0100 Subject: [PATCH] Optimization to be able to work with only 2 buffers --- embassy-nrf/src/i2s.rs | 48 ++++++++++++++++++++-------- examples/nrf/src/bin/i2s_waveform.rs | 20 ++++++------ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index bc90dbc9..08d4093f 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs @@ -398,6 +398,7 @@ impl<'d, T: Instance> I2S<'d, T> { ) -> FullDuplexStream<'d, T> { self.sdout = Some(sdout.into_ref().map_into()); self.sdin = Some(sdin.into_ref().map_into()); + FullDuplexStream { _p: self.build() } } @@ -549,6 +550,16 @@ impl<'d, T: Instance> I2S<'d, T> { let device = Device::::new(); + device.update_tx(buffer_ptr)?; + + Self::wait_tx_ptr_update().await; + + compiler_fence(Ordering::SeqCst); + + Ok(()) + } + + async fn wait_tx_ptr_update() { let drop = OnDrop::new(move || { trace!("TX DROP: Stopping"); @@ -566,6 +577,7 @@ impl<'d, T: Instance> I2S<'d, T> { poll_fn(|cx| { T::state().tx_waker.register(cx.waker()); + let device = Device::::new(); if device.is_tx_ptr_updated() { trace!("TX POLL: Ready"); device.reset_tx_ptr_event(); @@ -578,12 +590,7 @@ impl<'d, T: Instance> I2S<'d, T> { }) .await; - device.update_tx(buffer_ptr)?; - - compiler_fence(Ordering::SeqCst); drop.defuse(); - - Ok(()) } async fn receive_from_ram(buffer_ptr: *mut [S]) -> Result<(), Error> @@ -599,6 +606,16 @@ impl<'d, T: Instance> I2S<'d, T> { let device = Device::::new(); + device.update_rx(buffer_ptr)?; + + Self::wait_rx_ptr_update().await; + + compiler_fence(Ordering::SeqCst); + + Ok(()) + } + + async fn wait_rx_ptr_update() { let drop = OnDrop::new(move || { trace!("RX DROP: Stopping"); @@ -616,6 +633,7 @@ impl<'d, T: Instance> I2S<'d, T> { poll_fn(|cx| { T::state().rx_waker.register(cx.waker()); + let device = Device::::new(); if device.is_rx_ptr_updated() { trace!("RX POLL: Ready"); device.reset_rx_ptr_event(); @@ -628,13 +646,7 @@ impl<'d, T: Instance> I2S<'d, T> { }) .await; - device.update_rx(buffer_ptr)?; - - compiler_fence(Ordering::SeqCst); - drop.defuse(); - - Ok(()) } } @@ -666,6 +678,8 @@ impl<'d, T: Instance> OutputStream<'d, T> { device.start(); + I2S::::wait_tx_ptr_update().await; + Ok(()) } @@ -716,6 +730,8 @@ impl<'d, T: Instance> InputStream<'d, T> { device.start(); + I2S::::wait_rx_ptr_update().await; + Ok(()) } @@ -746,7 +762,7 @@ pub struct FullDuplexStream<'d, T: Instance> { impl<'d, T: Instance> FullDuplexStream<'d, T> { /// Prepare the initial buffers and start the I2S transfer. #[allow(unused_mut)] - pub async fn start(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error> + pub async fn start(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error> where S: Sample, { @@ -768,6 +784,9 @@ impl<'d, T: Instance> FullDuplexStream<'d, T> { device.start(); + I2S::::wait_tx_ptr_update().await; + I2S::::wait_rx_ptr_update().await; + Ok(()) } @@ -782,7 +801,7 @@ impl<'d, T: Instance> FullDuplexStream<'d, T> { /// The buffers must not be written/read while being used by the DMA, /// which takes two other `send_and_receive` operations being awaited. #[allow(unused_mut)] - pub async fn send_and_receive_from_ram(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error> + pub async fn send_and_receive_from_ram(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error> where S: Sample, { @@ -903,7 +922,7 @@ impl Device { #[inline(always)] fn enable_rx_ptr_interrupt(&self) { trace!("RX PTR INTERRUPT: Enabled"); - self.0.intenclr.write(|w| w.rxptrupd().clear()); + self.0.intenset.write(|w| w.rxptrupd().set()); } #[inline(always)] @@ -974,6 +993,7 @@ impl Sample for i32 { } /// A 4-bytes aligned [Buffer]. +#[derive(Clone, Copy)] #[repr(align(4))] pub struct AlignedBuffer([T; N]); diff --git a/examples/nrf/src/bin/i2s_waveform.rs b/examples/nrf/src/bin/i2s_waveform.rs index 81858ff5..13b1300e 100644 --- a/examples/nrf/src/bin/i2s_waveform.rs +++ b/examples/nrf/src/bin/i2s_waveform.rs @@ -12,7 +12,8 @@ use {defmt_rtt as _, panic_probe as _}; type Sample = i16; -const NUM_SAMPLES: usize = 6000; +const NUM_BUFFERS: usize = 2; +const NUM_SAMPLES: usize = 50; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -30,31 +31,27 @@ async fn main(_spawner: Spawner) { let irq = interrupt::take!(I2S); let mut output_stream = I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).output(p.P0_28); - let mut buffers: [i2s::AlignedBuffer; 3] = [ - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - ]; + let mut buffers: [i2s::AlignedBuffer; NUM_BUFFERS] = + [i2s::AlignedBuffer::default(); NUM_BUFFERS]; let mut waveform = Waveform::new(1.0 / sample_rate as f32); waveform.process(&mut buffers[0]); - waveform.process(&mut buffers[1]); output_stream.start(&buffers[0]).await.expect("I2S Start"); let mut index = 1; loop { + waveform.process(&mut buffers[index]); + if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { error!("{}", err); } index += 1; - if index >= 3 { + if index >= NUM_BUFFERS { index = 0; } - - waveform.process(&mut buffers[index]); } } @@ -67,7 +64,8 @@ struct Waveform { impl Waveform { fn new(inv_sample_rate: f32) -> Self { - let carrier = SineOsc::new(); + let mut carrier = SineOsc::new(); + carrier.set_frequency(110.0, inv_sample_rate); let mut freq_mod = SineOsc::new(); freq_mod.set_frequency(8.0, inv_sample_rate);