nrf/i2s: switch to new interrupt binding.
This commit is contained in:
parent
63b75eaf64
commit
34563b74aa
4 changed files with 59 additions and 51 deletions
|
@ -14,7 +14,7 @@ use embassy_hal_common::drop::OnDrop;
|
|||
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||
|
||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||
use crate::interrupt::Interrupt;
|
||||
use crate::interrupt::{self, Interrupt};
|
||||
use crate::pac::i2s::RegisterBlock;
|
||||
use crate::util::{slice_in_ram_or, slice_ptr_parts};
|
||||
use crate::{Peripheral, EASY_DMA_SIZE};
|
||||
|
@ -363,10 +363,39 @@ impl From<Channels> for u8 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Interrupt handler.
|
||||
pub struct InterruptHandler<T: Instance> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||
unsafe fn on_interrupt() {
|
||||
let device = Device::<T>::new();
|
||||
let s = T::state();
|
||||
|
||||
if device.is_tx_ptr_updated() {
|
||||
trace!("TX INT");
|
||||
s.tx_waker.wake();
|
||||
device.disable_tx_ptr_interrupt();
|
||||
}
|
||||
|
||||
if device.is_rx_ptr_updated() {
|
||||
trace!("RX INT");
|
||||
s.rx_waker.wake();
|
||||
device.disable_rx_ptr_interrupt();
|
||||
}
|
||||
|
||||
if device.is_stopped() {
|
||||
trace!("STOPPED INT");
|
||||
s.stop_waker.wake();
|
||||
device.disable_stopped_interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// I2S driver.
|
||||
pub struct I2S<'d, T: Instance> {
|
||||
i2s: PeripheralRef<'d, T>,
|
||||
irq: PeripheralRef<'d, T::Interrupt>,
|
||||
mck: Option<PeripheralRef<'d, AnyPin>>,
|
||||
sck: PeripheralRef<'d, AnyPin>,
|
||||
lrck: PeripheralRef<'d, AnyPin>,
|
||||
|
@ -378,19 +407,18 @@ pub struct I2S<'d, T: Instance> {
|
|||
|
||||
impl<'d, T: Instance> I2S<'d, T> {
|
||||
/// Create a new I2S in master mode
|
||||
pub fn master(
|
||||
pub fn new_master(
|
||||
i2s: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
mck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
master_clock: MasterClock,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(i2s, irq, mck, sck, lrck);
|
||||
into_ref!(i2s, mck, sck, lrck);
|
||||
Self {
|
||||
i2s,
|
||||
irq,
|
||||
mck: Some(mck.map_into()),
|
||||
sck: sck.map_into(),
|
||||
lrck: lrck.map_into(),
|
||||
|
@ -402,17 +430,16 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||
}
|
||||
|
||||
/// Create a new I2S in slave mode
|
||||
pub fn slave(
|
||||
pub fn new_slave(
|
||||
i2s: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(i2s, irq, sck, lrck);
|
||||
into_ref!(i2s, sck, lrck);
|
||||
Self {
|
||||
i2s,
|
||||
irq,
|
||||
mck: None,
|
||||
sck: sck.map_into(),
|
||||
lrck: lrck.map_into(),
|
||||
|
@ -537,9 +564,8 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||
}
|
||||
|
||||
fn setup_interrupt(&self) {
|
||||
self.irq.set_handler(Self::on_interrupt);
|
||||
self.irq.unpend();
|
||||
self.irq.enable();
|
||||
unsafe { T::Interrupt::steal() }.unpend();
|
||||
unsafe { T::Interrupt::steal() }.enable();
|
||||
|
||||
let device = Device::<T>::new();
|
||||
device.disable_tx_ptr_interrupt();
|
||||
|
@ -555,29 +581,6 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||
device.enable_stopped_interrupt();
|
||||
}
|
||||
|
||||
fn on_interrupt(_: *mut ()) {
|
||||
let device = Device::<T>::new();
|
||||
let s = T::state();
|
||||
|
||||
if device.is_tx_ptr_updated() {
|
||||
trace!("TX INT");
|
||||
s.tx_waker.wake();
|
||||
device.disable_tx_ptr_interrupt();
|
||||
}
|
||||
|
||||
if device.is_rx_ptr_updated() {
|
||||
trace!("RX INT");
|
||||
s.rx_waker.wake();
|
||||
device.disable_rx_ptr_interrupt();
|
||||
}
|
||||
|
||||
if device.is_stopped() {
|
||||
trace!("STOPPED INT");
|
||||
s.stop_waker.wake();
|
||||
device.disable_stopped_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
async fn stop() {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
|
@ -1168,7 +1171,7 @@ pub(crate) mod sealed {
|
|||
}
|
||||
}
|
||||
|
||||
/// I2S peripehral instance.
|
||||
/// I2S peripheral instance.
|
||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
|
||||
/// Interrupt for this peripheral.
|
||||
type Interrupt: Interrupt;
|
||||
|
|
|
@ -7,7 +7,7 @@ use core::f32::consts::PI;
|
|||
use defmt::{error, info};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S};
|
||||
use embassy_nrf::interrupt;
|
||||
use embassy_nrf::{bind_interrupts, peripherals};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type Sample = i16;
|
||||
|
@ -15,6 +15,10 @@ type Sample = i16;
|
|||
const NUM_BUFFERS: usize = 2;
|
||||
const NUM_SAMPLES: usize = 4;
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
|
@ -28,15 +32,10 @@ async fn main(_spawner: Spawner) {
|
|||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
|
||||
let buffers_in = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
|
||||
let mut full_duplex_stream = I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).full_duplex(
|
||||
p.P0_29,
|
||||
p.P0_28,
|
||||
buffers_out,
|
||||
buffers_in,
|
||||
);
|
||||
let mut full_duplex_stream = I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config)
|
||||
.full_duplex(p.P0_29, p.P0_28, buffers_out, buffers_in);
|
||||
|
||||
let mut modulator = SineOsc::new();
|
||||
modulator.set_frequency(8.0, 1.0 / sample_rate as f32);
|
||||
|
|
|
@ -5,14 +5,18 @@
|
|||
use defmt::{debug, error, info};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
|
||||
use embassy_nrf::interrupt;
|
||||
use embassy_nrf::pwm::{Prescaler, SimplePwm};
|
||||
use embassy_nrf::{bind_interrupts, peripherals};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type Sample = i16;
|
||||
|
||||
const NUM_SAMPLES: usize = 500;
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
|
@ -26,10 +30,9 @@ async fn main(_spawner: Spawner) {
|
|||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||
let mut input_stream =
|
||||
I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
|
||||
I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers);
|
||||
|
||||
// Configure the PWM to use the pins corresponding to the RGB leds
|
||||
let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24);
|
||||
|
|
|
@ -7,13 +7,17 @@ use core::f32::consts::PI;
|
|||
use defmt::{error, info};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
|
||||
use embassy_nrf::interrupt;
|
||||
use embassy_nrf::{bind_interrupts, peripherals};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type Sample = i16;
|
||||
|
||||
const NUM_SAMPLES: usize = 50;
|
||||
|
||||
bind_interrupts!(struct Irqs {
|
||||
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||
});
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
|
@ -27,10 +31,9 @@ async fn main(_spawner: Spawner) {
|
|||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||
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, buffers);
|
||||
I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config).output(p.P0_28, buffers);
|
||||
|
||||
let mut waveform = Waveform::new(1.0 / sample_rate as f32);
|
||||
|
||||
|
|
Loading…
Reference in a new issue