diff options
| author | Christian Perez Llamas <[email protected]> | 2022-11-29 01:09:47 +0100 |
|---|---|---|
| committer | Christian Perez Llamas <[email protected]> | 2022-11-29 01:09:47 +0100 |
| commit | 199504be564b231154e07c58bcc52b11afdc9fe7 (patch) | |
| tree | 88d66d98acf9edbdb23d869d81f453fd3b2eb0f1 | |
| parent | 6b8ab32536bf2e831ec424b5aaf489bb1f53d017 (diff) | |
Optimization to be able to work with only 2 buffers
| -rw-r--r-- | embassy-nrf/src/i2s.rs | 48 | ||||
| -rw-r--r-- | 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 bc90dbc98..08d4093f2 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs | |||
| @@ -398,6 +398,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 398 | ) -> FullDuplexStream<'d, T> { | 398 | ) -> FullDuplexStream<'d, T> { |
| 399 | self.sdout = Some(sdout.into_ref().map_into()); | 399 | self.sdout = Some(sdout.into_ref().map_into()); |
| 400 | self.sdin = Some(sdin.into_ref().map_into()); | 400 | self.sdin = Some(sdin.into_ref().map_into()); |
| 401 | |||
| 401 | FullDuplexStream { _p: self.build() } | 402 | FullDuplexStream { _p: self.build() } |
| 402 | } | 403 | } |
| 403 | 404 | ||
| @@ -549,6 +550,16 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 549 | 550 | ||
| 550 | let device = Device::<T>::new(); | 551 | let device = Device::<T>::new(); |
| 551 | 552 | ||
| 553 | device.update_tx(buffer_ptr)?; | ||
| 554 | |||
| 555 | Self::wait_tx_ptr_update().await; | ||
| 556 | |||
| 557 | compiler_fence(Ordering::SeqCst); | ||
| 558 | |||
| 559 | Ok(()) | ||
| 560 | } | ||
| 561 | |||
| 562 | async fn wait_tx_ptr_update() { | ||
| 552 | let drop = OnDrop::new(move || { | 563 | let drop = OnDrop::new(move || { |
| 553 | trace!("TX DROP: Stopping"); | 564 | trace!("TX DROP: Stopping"); |
| 554 | 565 | ||
| @@ -566,6 +577,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 566 | poll_fn(|cx| { | 577 | poll_fn(|cx| { |
| 567 | T::state().tx_waker.register(cx.waker()); | 578 | T::state().tx_waker.register(cx.waker()); |
| 568 | 579 | ||
| 580 | let device = Device::<T>::new(); | ||
| 569 | if device.is_tx_ptr_updated() { | 581 | if device.is_tx_ptr_updated() { |
| 570 | trace!("TX POLL: Ready"); | 582 | trace!("TX POLL: Ready"); |
| 571 | device.reset_tx_ptr_event(); | 583 | device.reset_tx_ptr_event(); |
| @@ -578,12 +590,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 578 | }) | 590 | }) |
| 579 | .await; | 591 | .await; |
| 580 | 592 | ||
| 581 | device.update_tx(buffer_ptr)?; | ||
| 582 | |||
| 583 | compiler_fence(Ordering::SeqCst); | ||
| 584 | drop.defuse(); | 593 | drop.defuse(); |
| 585 | |||
| 586 | Ok(()) | ||
| 587 | } | 594 | } |
| 588 | 595 | ||
| 589 | async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error> | 596 | async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error> |
| @@ -599,6 +606,16 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 599 | 606 | ||
| 600 | let device = Device::<T>::new(); | 607 | let device = Device::<T>::new(); |
| 601 | 608 | ||
| 609 | device.update_rx(buffer_ptr)?; | ||
| 610 | |||
| 611 | Self::wait_rx_ptr_update().await; | ||
| 612 | |||
| 613 | compiler_fence(Ordering::SeqCst); | ||
| 614 | |||
| 615 | Ok(()) | ||
| 616 | } | ||
| 617 | |||
| 618 | async fn wait_rx_ptr_update() { | ||
| 602 | let drop = OnDrop::new(move || { | 619 | let drop = OnDrop::new(move || { |
| 603 | trace!("RX DROP: Stopping"); | 620 | trace!("RX DROP: Stopping"); |
| 604 | 621 | ||
| @@ -616,6 +633,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 616 | poll_fn(|cx| { | 633 | poll_fn(|cx| { |
| 617 | T::state().rx_waker.register(cx.waker()); | 634 | T::state().rx_waker.register(cx.waker()); |
| 618 | 635 | ||
| 636 | let device = Device::<T>::new(); | ||
| 619 | if device.is_rx_ptr_updated() { | 637 | if device.is_rx_ptr_updated() { |
| 620 | trace!("RX POLL: Ready"); | 638 | trace!("RX POLL: Ready"); |
| 621 | device.reset_rx_ptr_event(); | 639 | device.reset_rx_ptr_event(); |
| @@ -628,13 +646,7 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 628 | }) | 646 | }) |
| 629 | .await; | 647 | .await; |
| 630 | 648 | ||
| 631 | device.update_rx(buffer_ptr)?; | ||
| 632 | |||
| 633 | compiler_fence(Ordering::SeqCst); | ||
| 634 | |||
| 635 | drop.defuse(); | 649 | drop.defuse(); |
| 636 | |||
| 637 | Ok(()) | ||
| 638 | } | 650 | } |
| 639 | } | 651 | } |
| 640 | 652 | ||
| @@ -666,6 +678,8 @@ impl<'d, T: Instance> OutputStream<'d, T> { | |||
| 666 | 678 | ||
| 667 | device.start(); | 679 | device.start(); |
| 668 | 680 | ||
| 681 | I2S::<T>::wait_tx_ptr_update().await; | ||
| 682 | |||
| 669 | Ok(()) | 683 | Ok(()) |
| 670 | } | 684 | } |
| 671 | 685 | ||
| @@ -716,6 +730,8 @@ impl<'d, T: Instance> InputStream<'d, T> { | |||
| 716 | 730 | ||
| 717 | device.start(); | 731 | device.start(); |
| 718 | 732 | ||
| 733 | I2S::<T>::wait_rx_ptr_update().await; | ||
| 734 | |||
| 719 | Ok(()) | 735 | Ok(()) |
| 720 | } | 736 | } |
| 721 | 737 | ||
| @@ -746,7 +762,7 @@ pub struct FullDuplexStream<'d, T: Instance> { | |||
| 746 | impl<'d, T: Instance> FullDuplexStream<'d, T> { | 762 | impl<'d, T: Instance> FullDuplexStream<'d, T> { |
| 747 | /// Prepare the initial buffers and start the I2S transfer. | 763 | /// Prepare the initial buffers and start the I2S transfer. |
| 748 | #[allow(unused_mut)] | 764 | #[allow(unused_mut)] |
| 749 | pub async fn start<S>(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error> | 765 | pub async fn start<S>(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error> |
| 750 | where | 766 | where |
| 751 | S: Sample, | 767 | S: Sample, |
| 752 | { | 768 | { |
| @@ -768,6 +784,9 @@ impl<'d, T: Instance> FullDuplexStream<'d, T> { | |||
| 768 | 784 | ||
| 769 | device.start(); | 785 | device.start(); |
| 770 | 786 | ||
| 787 | I2S::<T>::wait_tx_ptr_update().await; | ||
| 788 | I2S::<T>::wait_rx_ptr_update().await; | ||
| 789 | |||
| 771 | Ok(()) | 790 | Ok(()) |
| 772 | } | 791 | } |
| 773 | 792 | ||
| @@ -782,7 +801,7 @@ impl<'d, T: Instance> FullDuplexStream<'d, T> { | |||
| 782 | /// The buffers must not be written/read while being used by the DMA, | 801 | /// The buffers must not be written/read while being used by the DMA, |
| 783 | /// which takes two other `send_and_receive` operations being awaited. | 802 | /// which takes two other `send_and_receive` operations being awaited. |
| 784 | #[allow(unused_mut)] | 803 | #[allow(unused_mut)] |
| 785 | pub async fn send_and_receive_from_ram<S>(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error> | 804 | pub async fn send_and_receive_from_ram<S>(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error> |
| 786 | where | 805 | where |
| 787 | S: Sample, | 806 | S: Sample, |
| 788 | { | 807 | { |
| @@ -903,7 +922,7 @@ impl<T: Instance> Device<T> { | |||
| 903 | #[inline(always)] | 922 | #[inline(always)] |
| 904 | fn enable_rx_ptr_interrupt(&self) { | 923 | fn enable_rx_ptr_interrupt(&self) { |
| 905 | trace!("RX PTR INTERRUPT: Enabled"); | 924 | trace!("RX PTR INTERRUPT: Enabled"); |
| 906 | self.0.intenclr.write(|w| w.rxptrupd().clear()); | 925 | self.0.intenset.write(|w| w.rxptrupd().set()); |
| 907 | } | 926 | } |
| 908 | 927 | ||
| 909 | #[inline(always)] | 928 | #[inline(always)] |
| @@ -974,6 +993,7 @@ impl Sample for i32 { | |||
| 974 | } | 993 | } |
| 975 | 994 | ||
| 976 | /// A 4-bytes aligned [Buffer]. | 995 | /// A 4-bytes aligned [Buffer]. |
| 996 | #[derive(Clone, Copy)] | ||
| 977 | #[repr(align(4))] | 997 | #[repr(align(4))] |
| 978 | pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]); | 998 | pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]); |
| 979 | 999 | ||
diff --git a/examples/nrf/src/bin/i2s_waveform.rs b/examples/nrf/src/bin/i2s_waveform.rs index 81858ff59..13b1300ea 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 _}; | |||
| 12 | 12 | ||
| 13 | type Sample = i16; | 13 | type Sample = i16; |
| 14 | 14 | ||
| 15 | const NUM_SAMPLES: usize = 6000; | 15 | const NUM_BUFFERS: usize = 2; |
| 16 | const NUM_SAMPLES: usize = 50; | ||
| 16 | 17 | ||
| 17 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 19 | async fn main(_spawner: Spawner) { |
| @@ -30,31 +31,27 @@ async fn main(_spawner: Spawner) { | |||
| 30 | let irq = interrupt::take!(I2S); | 31 | let irq = interrupt::take!(I2S); |
| 31 | 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); | 32 | 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); |
| 32 | 33 | ||
| 33 | let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; 3] = [ | 34 | let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; NUM_BUFFERS] = |
| 34 | i2s::AlignedBuffer::default(), | 35 | [i2s::AlignedBuffer::default(); NUM_BUFFERS]; |
| 35 | i2s::AlignedBuffer::default(), | ||
| 36 | i2s::AlignedBuffer::default(), | ||
| 37 | ]; | ||
| 38 | 36 | ||
| 39 | let mut waveform = Waveform::new(1.0 / sample_rate as f32); | 37 | let mut waveform = Waveform::new(1.0 / sample_rate as f32); |
| 40 | 38 | ||
| 41 | waveform.process(&mut buffers[0]); | 39 | waveform.process(&mut buffers[0]); |
| 42 | waveform.process(&mut buffers[1]); | ||
| 43 | 40 | ||
| 44 | output_stream.start(&buffers[0]).await.expect("I2S Start"); | 41 | output_stream.start(&buffers[0]).await.expect("I2S Start"); |
| 45 | 42 | ||
| 46 | let mut index = 1; | 43 | let mut index = 1; |
| 47 | loop { | 44 | loop { |
| 45 | waveform.process(&mut buffers[index]); | ||
| 46 | |||
| 48 | if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { | 47 | if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { |
| 49 | error!("{}", err); | 48 | error!("{}", err); |
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | index += 1; | 51 | index += 1; |
| 53 | if index >= 3 { | 52 | if index >= NUM_BUFFERS { |
| 54 | index = 0; | 53 | index = 0; |
| 55 | } | 54 | } |
| 56 | |||
| 57 | waveform.process(&mut buffers[index]); | ||
| 58 | } | 55 | } |
| 59 | } | 56 | } |
| 60 | 57 | ||
| @@ -67,7 +64,8 @@ struct Waveform { | |||
| 67 | 64 | ||
| 68 | impl Waveform { | 65 | impl Waveform { |
| 69 | fn new(inv_sample_rate: f32) -> Self { | 66 | fn new(inv_sample_rate: f32) -> Self { |
| 70 | let carrier = SineOsc::new(); | 67 | let mut carrier = SineOsc::new(); |
| 68 | carrier.set_frequency(110.0, inv_sample_rate); | ||
| 71 | 69 | ||
| 72 | let mut freq_mod = SineOsc::new(); | 70 | let mut freq_mod = SineOsc::new(); |
| 73 | freq_mod.set_frequency(8.0, inv_sample_rate); | 71 | freq_mod.set_frequency(8.0, inv_sample_rate); |
