Investigating discontinuities in the signal
This commit is contained in:
parent
122a31d208
commit
d2e8794f29
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user