Investigating discontinuities in the signal

This commit is contained in:
Christian Perez Llamas 2022-11-13 01:41:32 +01:00
parent 122a31d208
commit d2e8794f29
2 changed files with 66 additions and 29 deletions

View File

@ -371,21 +371,6 @@ impl<'d, T: Instance> I2S<'d, T> {
self.input.rx(buffer).await self.input.rx(buffer).await
} }
fn on_interrupt(_: *mut ()) {
let r = T::regs();
let s = T::state();
if r.events_txptrupd.read().bits() != 0 {
s.tx_waker.wake();
r.intenclr.write(|w| w.txptrupd().clear());
}
if r.events_rxptrupd.read().bits() != 0 {
s.rx_waker.wake();
r.intenclr.write(|w| w.rxptrupd().clear());
}
}
fn apply_config(c: &CONFIG, config: &Config) { fn apply_config(c: &CONFIG, config: &Config) {
match config.mode { match config.mode {
Mode::Master { freq, ratio } => { Mode::Master { freq, ratio } => {
@ -443,14 +428,36 @@ impl<'d, T: Instance> I2S<'d, T> {
fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>, r: &RegisterBlock) { fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>, r: &RegisterBlock) {
irq.set_handler(Self::on_interrupt); irq.set_handler(Self::on_interrupt);
irq.set_priority(Priority::P1); // TODO review priorities // irq.set_priority(Priority::P1); // TODO review priorities
irq.unpend(); irq.unpend();
irq.enable(); irq.enable();
r.intenclr.write(|w| w.rxptrupd().clear()); r.intenclr.write(|w| w.rxptrupd().clear());
r.intenclr.write(|w| w.txptrupd().clear()); r.intenclr.write(|w| w.txptrupd().clear());
r.events_rxptrupd.reset(); r.events_rxptrupd.reset();
r.events_txptrupd.reset(); r.events_txptrupd.reset();
r.intenset.write(|w| w.rxptrupd().set());
r.intenset.write(|w| w.txptrupd().set());
}
fn on_interrupt(_: *mut ()) {
let r = T::regs();
let s = T::state();
if r.events_txptrupd.read().bits() != 0 {
trace!("[{}] INT", s.seq.load(Ordering::Relaxed));
s.tx_waker.wake();
r.intenclr.write(|w| w.txptrupd().clear());
}
if r.events_rxptrupd.read().bits() != 0 {
s.rx_waker.wake();
r.intenclr.write(|w| w.rxptrupd().clear());
}
s.overruns.fetch_add(1, Ordering::Relaxed);
} }
} }
@ -479,6 +486,12 @@ impl<'d, T: Instance> I2sOutput<'d, T> {
let r = T::regs(); let r = T::regs();
let s = T::state(); let s = T::state();
let seq = s.seq.fetch_add(1, Ordering::Relaxed);
if r.events_txptrupd.read().bits() != 0 && seq > 0 {
info!("XRUN!");
loop {}
}
let drop = OnDrop::new(move || { let drop = OnDrop::new(move || {
trace!("write drop: stopping"); trace!("write drop: stopping");
@ -491,18 +504,26 @@ impl<'d, T: Instance> I2sOutput<'d, T> {
trace!("write drop: stopped"); trace!("write drop: stopped");
}); });
trace!("[{}] PTR", s.seq.load(Ordering::Relaxed));
r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
r.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) }); r.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
r.intenset.write(|w| w.txptrupd().set());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
poll_fn(|cx| { poll_fn(|cx| {
s.tx_waker.register(cx.waker()); s.tx_waker.register(cx.waker());
if r.events_txptrupd.read().bits() != 0 { if r.events_txptrupd.read().bits() != 0 || seq == 0 {
trace!("[{}] POLL Ready", s.seq.load(Ordering::Relaxed));
r.events_txptrupd.reset();
r.intenset.write(|w| w.txptrupd().set());
let overruns = s.overruns.fetch_sub(1, Ordering::Relaxed);
if overruns - 1 != 0 {
warn!("XRUN: {}", overruns);
s.overruns.store(0, Ordering::Relaxed)
}
Poll::Ready(()) Poll::Ready(())
} else { } else {
trace!("[{}] POLL Pending", s.seq.load(Ordering::Relaxed));
Poll::Pending Poll::Pending
} }
}) })
@ -593,19 +614,26 @@ impl Buffer for &[i32] {
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use core::sync::atomic::AtomicI32;
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
//use super::*; use super::*;
pub struct State { pub struct State {
pub rx_waker: AtomicWaker, pub rx_waker: AtomicWaker,
pub tx_waker: AtomicWaker, pub tx_waker: AtomicWaker,
pub overruns: AtomicI32,
pub seq: AtomicI32,
} }
impl State { impl State {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
rx_waker: AtomicWaker::new(), rx_waker: AtomicWaker::new(),
tx_waker: AtomicWaker::new(), tx_waker: AtomicWaker::new(),
overruns: AtomicI32::new(0),
seq: AtomicI32::new(0),
} }
} }
} }

View File

@ -9,6 +9,7 @@ use core::f32::consts::PI;
use defmt::{error, info}; use defmt::{error, info};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000};
use embassy_nrf::pac::ficr::info;
use embassy_nrf::{i2s, interrupt}; use embassy_nrf::{i2s, interrupt};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -49,16 +50,14 @@ async fn main(_spawner: Spawner) {
let mut buf = AlignedBuffer([0i16; BUF_SIZE]); let mut buf = AlignedBuffer([0i16; BUF_SIZE]);
let mut carrier = SineOsc::new(); let mut carrier = SineOsc::new();
carrier.set_frequency(300.0, inv_sample_rate); carrier.set_frequency(240.0, inv_sample_rate);
let mut modulator = SineOsc::new(); // let mut modulator = SineOsc::new();
modulator.set_frequency(0.01, inv_sample_rate); // modulator.set_frequency(0.01, inv_sample_rate);
modulator.set_amplitude(0.2); // modulator.set_amplitude(0.2);
i2s.set_tx_enabled(true); let mut lastf = 0.0;
i2s.start(); let mut generate = |buf: &mut [i16]| {
loop {
for sample in buf.as_mut().chunks_mut(2) { for sample in buf.as_mut().chunks_mut(2) {
let signal = carrier.generate(); let signal = carrier.generate();
// let modulation = bipolar_to_unipolar(modulator.generate()); // let modulation = bipolar_to_unipolar(modulator.generate());
@ -67,8 +66,18 @@ async fn main(_spawner: Spawner) {
let value = (i16::MAX as f32 * signal) as i16; let value = (i16::MAX as f32 * signal) as i16;
sample[0] = value; sample[0] = value;
sample[1] = value; sample[1] = value;
// info!("{}", signal);
} }
};
generate(buf.as_mut().as_mut_slice());
i2s.set_tx_enabled(true);
i2s.start();
loop {
// info!("--");
generate(buf.as_mut().as_mut_slice());
if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await {
error!("{}", err); error!("{}", err);