diff options
| author | Christian Perez Llamas <[email protected]> | 2022-11-13 01:41:32 +0100 |
|---|---|---|
| committer | Christian Perez Llamas <[email protected]> | 2022-11-13 01:41:32 +0100 |
| commit | d2e8794f29d3d0afef7a6bc610b2ee4a4d680643 (patch) | |
| tree | 120e9e77a49561ef4552b9b9a82e49e5535c3fc7 | |
| parent | 122a31d20877005c7201d4e7c98da5544666dd1d (diff) | |
Investigating discontinuities in the signal
| -rw-r--r-- | embassy-nrf/src/i2s.rs | 68 | ||||
| -rw-r--r-- | examples/nrf/src/bin/i2s.rs | 27 |
2 files changed, 66 insertions, 29 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index f5e36f0dd..9a8f29e78 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs | |||
| @@ -371,21 +371,6 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 371 | self.input.rx(buffer).await | 371 | self.input.rx(buffer).await |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | fn on_interrupt(_: *mut ()) { | ||
| 375 | let r = T::regs(); | ||
| 376 | let s = T::state(); | ||
| 377 | |||
| 378 | if r.events_txptrupd.read().bits() != 0 { | ||
| 379 | s.tx_waker.wake(); | ||
| 380 | r.intenclr.write(|w| w.txptrupd().clear()); | ||
| 381 | } | ||
| 382 | |||
| 383 | if r.events_rxptrupd.read().bits() != 0 { | ||
| 384 | s.rx_waker.wake(); | ||
| 385 | r.intenclr.write(|w| w.rxptrupd().clear()); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | fn apply_config(c: &CONFIG, config: &Config) { | 374 | fn apply_config(c: &CONFIG, config: &Config) { |
| 390 | match config.mode { | 375 | match config.mode { |
| 391 | Mode::Master { freq, ratio } => { | 376 | Mode::Master { freq, ratio } => { |
| @@ -443,14 +428,36 @@ impl<'d, T: Instance> I2S<'d, T> { | |||
| 443 | 428 | ||
| 444 | fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>, r: &RegisterBlock) { | 429 | fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>, r: &RegisterBlock) { |
| 445 | irq.set_handler(Self::on_interrupt); | 430 | irq.set_handler(Self::on_interrupt); |
| 446 | irq.set_priority(Priority::P1); // TODO review priorities | 431 | // irq.set_priority(Priority::P1); // TODO review priorities |
| 447 | irq.unpend(); | 432 | irq.unpend(); |
| 448 | irq.enable(); | 433 | irq.enable(); |
| 449 | 434 | ||
| 450 | r.intenclr.write(|w| w.rxptrupd().clear()); | 435 | r.intenclr.write(|w| w.rxptrupd().clear()); |
| 451 | r.intenclr.write(|w| w.txptrupd().clear()); | 436 | r.intenclr.write(|w| w.txptrupd().clear()); |
| 437 | |||
| 452 | r.events_rxptrupd.reset(); | 438 | r.events_rxptrupd.reset(); |
| 453 | r.events_txptrupd.reset(); | 439 | r.events_txptrupd.reset(); |
| 440 | |||
| 441 | r.intenset.write(|w| w.rxptrupd().set()); | ||
| 442 | r.intenset.write(|w| w.txptrupd().set()); | ||
| 443 | } | ||
| 444 | |||
| 445 | fn on_interrupt(_: *mut ()) { | ||
| 446 | let r = T::regs(); | ||
| 447 | let s = T::state(); | ||
| 448 | |||
| 449 | if r.events_txptrupd.read().bits() != 0 { | ||
| 450 | trace!("[{}] INT", s.seq.load(Ordering::Relaxed)); | ||
| 451 | s.tx_waker.wake(); | ||
| 452 | r.intenclr.write(|w| w.txptrupd().clear()); | ||
| 453 | } | ||
| 454 | |||
| 455 | if r.events_rxptrupd.read().bits() != 0 { | ||
| 456 | s.rx_waker.wake(); | ||
| 457 | r.intenclr.write(|w| w.rxptrupd().clear()); | ||
| 458 | } | ||
| 459 | |||
| 460 | s.overruns.fetch_add(1, Ordering::Relaxed); | ||
| 454 | } | 461 | } |
| 455 | } | 462 | } |
| 456 | 463 | ||
| @@ -479,6 +486,12 @@ impl<'d, T: Instance> I2sOutput<'d, T> { | |||
| 479 | let r = T::regs(); | 486 | let r = T::regs(); |
| 480 | let s = T::state(); | 487 | let s = T::state(); |
| 481 | 488 | ||
| 489 | let seq = s.seq.fetch_add(1, Ordering::Relaxed); | ||
| 490 | if r.events_txptrupd.read().bits() != 0 && seq > 0 { | ||
| 491 | info!("XRUN!"); | ||
| 492 | loop {} | ||
| 493 | } | ||
| 494 | |||
| 482 | let drop = OnDrop::new(move || { | 495 | let drop = OnDrop::new(move || { |
| 483 | trace!("write drop: stopping"); | 496 | trace!("write drop: stopping"); |
| 484 | 497 | ||
| @@ -491,18 +504,26 @@ impl<'d, T: Instance> I2sOutput<'d, T> { | |||
| 491 | trace!("write drop: stopped"); | 504 | trace!("write drop: stopped"); |
| 492 | }); | 505 | }); |
| 493 | 506 | ||
| 507 | trace!("[{}] PTR", s.seq.load(Ordering::Relaxed)); | ||
| 494 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | 508 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 495 | r.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) }); | 509 | r.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) }); |
| 496 | 510 | ||
| 497 | r.intenset.write(|w| w.txptrupd().set()); | ||
| 498 | |||
| 499 | compiler_fence(Ordering::SeqCst); | 511 | compiler_fence(Ordering::SeqCst); |
| 500 | 512 | ||
| 501 | poll_fn(|cx| { | 513 | poll_fn(|cx| { |
| 502 | s.tx_waker.register(cx.waker()); | 514 | s.tx_waker.register(cx.waker()); |
| 503 | if r.events_txptrupd.read().bits() != 0 { | 515 | if r.events_txptrupd.read().bits() != 0 || seq == 0 { |
| 516 | trace!("[{}] POLL Ready", s.seq.load(Ordering::Relaxed)); | ||
| 517 | r.events_txptrupd.reset(); | ||
| 518 | r.intenset.write(|w| w.txptrupd().set()); | ||
| 519 | let overruns = s.overruns.fetch_sub(1, Ordering::Relaxed); | ||
| 520 | if overruns - 1 != 0 { | ||
| 521 | warn!("XRUN: {}", overruns); | ||
| 522 | s.overruns.store(0, Ordering::Relaxed) | ||
| 523 | } | ||
| 504 | Poll::Ready(()) | 524 | Poll::Ready(()) |
| 505 | } else { | 525 | } else { |
| 526 | trace!("[{}] POLL Pending", s.seq.load(Ordering::Relaxed)); | ||
| 506 | Poll::Pending | 527 | Poll::Pending |
| 507 | } | 528 | } |
| 508 | }) | 529 | }) |
| @@ -593,19 +614,26 @@ impl Buffer for &[i32] { | |||
| 593 | } | 614 | } |
| 594 | 615 | ||
| 595 | pub(crate) mod sealed { | 616 | pub(crate) mod sealed { |
| 617 | use core::sync::atomic::AtomicI32; | ||
| 618 | |||
| 596 | use embassy_sync::waitqueue::AtomicWaker; | 619 | use embassy_sync::waitqueue::AtomicWaker; |
| 597 | 620 | ||
| 598 | //use super::*; | 621 | use super::*; |
| 599 | 622 | ||
| 600 | pub struct State { | 623 | pub struct State { |
| 601 | pub rx_waker: AtomicWaker, | 624 | pub rx_waker: AtomicWaker, |
| 602 | pub tx_waker: AtomicWaker, | 625 | pub tx_waker: AtomicWaker, |
| 626 | pub overruns: AtomicI32, | ||
| 627 | pub seq: AtomicI32, | ||
| 603 | } | 628 | } |
| 629 | |||
| 604 | impl State { | 630 | impl State { |
| 605 | pub const fn new() -> Self { | 631 | pub const fn new() -> Self { |
| 606 | Self { | 632 | Self { |
| 607 | rx_waker: AtomicWaker::new(), | 633 | rx_waker: AtomicWaker::new(), |
| 608 | tx_waker: AtomicWaker::new(), | 634 | tx_waker: AtomicWaker::new(), |
| 635 | overruns: AtomicI32::new(0), | ||
| 636 | seq: AtomicI32::new(0), | ||
| 609 | } | 637 | } |
| 610 | } | 638 | } |
| 611 | } | 639 | } |
diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 53ccb3b85..7fb1ecb84 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs | |||
| @@ -9,6 +9,7 @@ use core::f32::consts::PI; | |||
| 9 | use defmt::{error, info}; | 9 | use defmt::{error, info}; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; | 11 | use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; |
| 12 | use embassy_nrf::pac::ficr::info; | ||
| 12 | use embassy_nrf::{i2s, interrupt}; | 13 | use embassy_nrf::{i2s, interrupt}; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 15 | ||
| @@ -49,16 +50,14 @@ async fn main(_spawner: Spawner) { | |||
| 49 | let mut buf = AlignedBuffer([0i16; BUF_SIZE]); | 50 | let mut buf = AlignedBuffer([0i16; BUF_SIZE]); |
| 50 | 51 | ||
| 51 | let mut carrier = SineOsc::new(); | 52 | let mut carrier = SineOsc::new(); |
| 52 | carrier.set_frequency(300.0, inv_sample_rate); | 53 | carrier.set_frequency(240.0, inv_sample_rate); |
| 53 | 54 | ||
| 54 | let mut modulator = SineOsc::new(); | 55 | // let mut modulator = SineOsc::new(); |
| 55 | modulator.set_frequency(0.01, inv_sample_rate); | 56 | // modulator.set_frequency(0.01, inv_sample_rate); |
| 56 | modulator.set_amplitude(0.2); | 57 | // modulator.set_amplitude(0.2); |
| 57 | 58 | ||
| 58 | i2s.set_tx_enabled(true); | 59 | let mut lastf = 0.0; |
| 59 | i2s.start(); | 60 | let mut generate = |buf: &mut [i16]| { |
| 60 | |||
| 61 | loop { | ||
| 62 | for sample in buf.as_mut().chunks_mut(2) { | 61 | for sample in buf.as_mut().chunks_mut(2) { |
| 63 | let signal = carrier.generate(); | 62 | let signal = carrier.generate(); |
| 64 | // let modulation = bipolar_to_unipolar(modulator.generate()); | 63 | // let modulation = bipolar_to_unipolar(modulator.generate()); |
| @@ -67,8 +66,18 @@ async fn main(_spawner: Spawner) { | |||
| 67 | let value = (i16::MAX as f32 * signal) as i16; | 66 | let value = (i16::MAX as f32 * signal) as i16; |
| 68 | sample[0] = value; | 67 | sample[0] = value; |
| 69 | sample[1] = value; | 68 | sample[1] = value; |
| 70 | // info!("{}", signal); | ||
| 71 | } | 69 | } |
| 70 | }; | ||
| 71 | |||
| 72 | generate(buf.as_mut().as_mut_slice()); | ||
| 73 | |||
| 74 | i2s.set_tx_enabled(true); | ||
| 75 | i2s.start(); | ||
| 76 | |||
| 77 | loop { | ||
| 78 | // info!("--"); | ||
| 79 | |||
| 80 | generate(buf.as_mut().as_mut_slice()); | ||
| 72 | 81 | ||
| 73 | if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { | 82 | if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { |
| 74 | error!("{}", err); | 83 | error!("{}", err); |
