Optimization to be able to work with only 2 buffers
This commit is contained in:
parent
6b8ab32536
commit
199504be56
@ -398,6 +398,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
) -> FullDuplexStream<'d, T> {
|
) -> FullDuplexStream<'d, T> {
|
||||||
self.sdout = Some(sdout.into_ref().map_into());
|
self.sdout = Some(sdout.into_ref().map_into());
|
||||||
self.sdin = Some(sdin.into_ref().map_into());
|
self.sdin = Some(sdin.into_ref().map_into());
|
||||||
|
|
||||||
FullDuplexStream { _p: self.build() }
|
FullDuplexStream { _p: self.build() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,6 +550,16 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
|
|
||||||
let device = Device::<T>::new();
|
let device = Device::<T>::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 || {
|
let drop = OnDrop::new(move || {
|
||||||
trace!("TX DROP: Stopping");
|
trace!("TX DROP: Stopping");
|
||||||
|
|
||||||
@ -566,6 +577,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().tx_waker.register(cx.waker());
|
T::state().tx_waker.register(cx.waker());
|
||||||
|
|
||||||
|
let device = Device::<T>::new();
|
||||||
if device.is_tx_ptr_updated() {
|
if device.is_tx_ptr_updated() {
|
||||||
trace!("TX POLL: Ready");
|
trace!("TX POLL: Ready");
|
||||||
device.reset_tx_ptr_event();
|
device.reset_tx_ptr_event();
|
||||||
@ -578,12 +590,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
device.update_tx(buffer_ptr)?;
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
drop.defuse();
|
drop.defuse();
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error>
|
async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error>
|
||||||
@ -599,6 +606,16 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
|
|
||||||
let device = Device::<T>::new();
|
let device = Device::<T>::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 || {
|
let drop = OnDrop::new(move || {
|
||||||
trace!("RX DROP: Stopping");
|
trace!("RX DROP: Stopping");
|
||||||
|
|
||||||
@ -616,6 +633,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().rx_waker.register(cx.waker());
|
T::state().rx_waker.register(cx.waker());
|
||||||
|
|
||||||
|
let device = Device::<T>::new();
|
||||||
if device.is_rx_ptr_updated() {
|
if device.is_rx_ptr_updated() {
|
||||||
trace!("RX POLL: Ready");
|
trace!("RX POLL: Ready");
|
||||||
device.reset_rx_ptr_event();
|
device.reset_rx_ptr_event();
|
||||||
@ -628,13 +646,7 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
device.update_rx(buffer_ptr)?;
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
drop.defuse();
|
drop.defuse();
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,6 +678,8 @@ impl<'d, T: Instance> OutputStream<'d, T> {
|
|||||||
|
|
||||||
device.start();
|
device.start();
|
||||||
|
|
||||||
|
I2S::<T>::wait_tx_ptr_update().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,6 +730,8 @@ impl<'d, T: Instance> InputStream<'d, T> {
|
|||||||
|
|
||||||
device.start();
|
device.start();
|
||||||
|
|
||||||
|
I2S::<T>::wait_rx_ptr_update().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,7 +762,7 @@ pub struct FullDuplexStream<'d, T: Instance> {
|
|||||||
impl<'d, T: Instance> FullDuplexStream<'d, T> {
|
impl<'d, T: Instance> FullDuplexStream<'d, T> {
|
||||||
/// Prepare the initial buffers and start the I2S transfer.
|
/// Prepare the initial buffers and start the I2S transfer.
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub async fn start<S>(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error>
|
pub async fn start<S>(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
S: Sample,
|
S: Sample,
|
||||||
{
|
{
|
||||||
@ -768,6 +784,9 @@ impl<'d, T: Instance> FullDuplexStream<'d, T> {
|
|||||||
|
|
||||||
device.start();
|
device.start();
|
||||||
|
|
||||||
|
I2S::<T>::wait_tx_ptr_update().await;
|
||||||
|
I2S::<T>::wait_rx_ptr_update().await;
|
||||||
|
|
||||||
Ok(())
|
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,
|
/// The buffers must not be written/read while being used by the DMA,
|
||||||
/// which takes two other `send_and_receive` operations being awaited.
|
/// which takes two other `send_and_receive` operations being awaited.
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub async fn send_and_receive_from_ram<S>(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error>
|
pub async fn send_and_receive_from_ram<S>(&mut self, buffer_in: &mut [S], buffer_out: &[S]) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
S: Sample,
|
S: Sample,
|
||||||
{
|
{
|
||||||
@ -903,7 +922,7 @@ impl<T: Instance> Device<T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn enable_rx_ptr_interrupt(&self) {
|
fn enable_rx_ptr_interrupt(&self) {
|
||||||
trace!("RX PTR INTERRUPT: Enabled");
|
trace!("RX PTR INTERRUPT: Enabled");
|
||||||
self.0.intenclr.write(|w| w.rxptrupd().clear());
|
self.0.intenset.write(|w| w.rxptrupd().set());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -974,6 +993,7 @@ impl Sample for i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A 4-bytes aligned [Buffer].
|
/// A 4-bytes aligned [Buffer].
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
#[repr(align(4))]
|
#[repr(align(4))]
|
||||||
pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
|
pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
|
|
||||||
type Sample = i16;
|
type Sample = i16;
|
||||||
|
|
||||||
const NUM_SAMPLES: usize = 6000;
|
const NUM_BUFFERS: usize = 2;
|
||||||
|
const NUM_SAMPLES: usize = 50;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
@ -30,31 +31,27 @@ async fn main(_spawner: Spawner) {
|
|||||||
let irq = interrupt::take!(I2S);
|
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 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<Sample, NUM_SAMPLES>; 3] = [
|
let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; NUM_BUFFERS] =
|
||||||
i2s::AlignedBuffer::default(),
|
[i2s::AlignedBuffer::default(); NUM_BUFFERS];
|
||||||
i2s::AlignedBuffer::default(),
|
|
||||||
i2s::AlignedBuffer::default(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut waveform = Waveform::new(1.0 / sample_rate as f32);
|
let mut waveform = Waveform::new(1.0 / sample_rate as f32);
|
||||||
|
|
||||||
waveform.process(&mut buffers[0]);
|
waveform.process(&mut buffers[0]);
|
||||||
waveform.process(&mut buffers[1]);
|
|
||||||
|
|
||||||
output_stream.start(&buffers[0]).await.expect("I2S Start");
|
output_stream.start(&buffers[0]).await.expect("I2S Start");
|
||||||
|
|
||||||
let mut index = 1;
|
let mut index = 1;
|
||||||
loop {
|
loop {
|
||||||
|
waveform.process(&mut buffers[index]);
|
||||||
|
|
||||||
if let Err(err) = output_stream.send_from_ram(&buffers[index]).await {
|
if let Err(err) = output_stream.send_from_ram(&buffers[index]).await {
|
||||||
error!("{}", err);
|
error!("{}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
if index >= 3 {
|
if index >= NUM_BUFFERS {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
waveform.process(&mut buffers[index]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +64,8 @@ struct Waveform {
|
|||||||
|
|
||||||
impl Waveform {
|
impl Waveform {
|
||||||
fn new(inv_sample_rate: f32) -> Self {
|
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();
|
let mut freq_mod = SineOsc::new();
|
||||||
freq_mod.set_frequency(8.0, inv_sample_rate);
|
freq_mod.set_frequency(8.0, inv_sample_rate);
|
||||||
|
Loading…
Reference in New Issue
Block a user