nrf/i2s: switch to new interrupt binding.
This commit is contained in:
parent
63b75eaf64
commit
34563b74aa
@ -14,7 +14,7 @@ use embassy_hal_common::drop::OnDrop;
|
|||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
|
|
||||||
use crate::gpio::{AnyPin, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Pin as GpioPin};
|
||||||
use crate::interrupt::Interrupt;
|
use crate::interrupt::{self, Interrupt};
|
||||||
use crate::pac::i2s::RegisterBlock;
|
use crate::pac::i2s::RegisterBlock;
|
||||||
use crate::util::{slice_in_ram_or, slice_ptr_parts};
|
use crate::util::{slice_in_ram_or, slice_ptr_parts};
|
||||||
use crate::{Peripheral, EASY_DMA_SIZE};
|
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.
|
/// I2S driver.
|
||||||
pub struct I2S<'d, T: Instance> {
|
pub struct I2S<'d, T: Instance> {
|
||||||
i2s: PeripheralRef<'d, T>,
|
i2s: PeripheralRef<'d, T>,
|
||||||
irq: PeripheralRef<'d, T::Interrupt>,
|
|
||||||
mck: Option<PeripheralRef<'d, AnyPin>>,
|
mck: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
sck: PeripheralRef<'d, AnyPin>,
|
sck: PeripheralRef<'d, AnyPin>,
|
||||||
lrck: PeripheralRef<'d, AnyPin>,
|
lrck: PeripheralRef<'d, AnyPin>,
|
||||||
@ -378,19 +407,18 @@ pub struct I2S<'d, T: Instance> {
|
|||||||
|
|
||||||
impl<'d, T: Instance> I2S<'d, T> {
|
impl<'d, T: Instance> I2S<'d, T> {
|
||||||
/// Create a new I2S in master mode
|
/// Create a new I2S in master mode
|
||||||
pub fn master(
|
pub fn new_master(
|
||||||
i2s: impl Peripheral<P = T> + 'd,
|
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,
|
mck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
master_clock: MasterClock,
|
master_clock: MasterClock,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(i2s, irq, mck, sck, lrck);
|
into_ref!(i2s, mck, sck, lrck);
|
||||||
Self {
|
Self {
|
||||||
i2s,
|
i2s,
|
||||||
irq,
|
|
||||||
mck: Some(mck.map_into()),
|
mck: Some(mck.map_into()),
|
||||||
sck: sck.map_into(),
|
sck: sck.map_into(),
|
||||||
lrck: lrck.map_into(),
|
lrck: lrck.map_into(),
|
||||||
@ -402,17 +430,16 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new I2S in slave mode
|
/// Create a new I2S in slave mode
|
||||||
pub fn slave(
|
pub fn new_slave(
|
||||||
i2s: impl Peripheral<P = T> + 'd,
|
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,
|
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
lrck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(i2s, irq, sck, lrck);
|
into_ref!(i2s, sck, lrck);
|
||||||
Self {
|
Self {
|
||||||
i2s,
|
i2s,
|
||||||
irq,
|
|
||||||
mck: None,
|
mck: None,
|
||||||
sck: sck.map_into(),
|
sck: sck.map_into(),
|
||||||
lrck: lrck.map_into(),
|
lrck: lrck.map_into(),
|
||||||
@ -537,9 +564,8 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_interrupt(&self) {
|
fn setup_interrupt(&self) {
|
||||||
self.irq.set_handler(Self::on_interrupt);
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
self.irq.unpend();
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
self.irq.enable();
|
|
||||||
|
|
||||||
let device = Device::<T>::new();
|
let device = Device::<T>::new();
|
||||||
device.disable_tx_ptr_interrupt();
|
device.disable_tx_ptr_interrupt();
|
||||||
@ -555,29 +581,6 @@ impl<'d, T: Instance> I2S<'d, T> {
|
|||||||
device.enable_stopped_interrupt();
|
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() {
|
async fn stop() {
|
||||||
compiler_fence(Ordering::SeqCst);
|
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 {
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
|
||||||
/// Interrupt for this peripheral.
|
/// Interrupt for this peripheral.
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
|
@ -7,7 +7,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::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S};
|
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 _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
type Sample = i16;
|
type Sample = i16;
|
||||||
@ -15,6 +15,10 @@ type Sample = i16;
|
|||||||
const NUM_BUFFERS: usize = 2;
|
const NUM_BUFFERS: usize = 2;
|
||||||
const NUM_SAMPLES: usize = 4;
|
const NUM_SAMPLES: usize = 4;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_nrf::init(Default::default());
|
let p = embassy_nrf::init(Default::default());
|
||||||
@ -28,15 +32,10 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.sample_width = SampleWidth::_16bit;
|
config.sample_width = SampleWidth::_16bit;
|
||||||
config.channels = Channels::MonoLeft;
|
config.channels = Channels::MonoLeft;
|
||||||
|
|
||||||
let irq = interrupt::take!(I2S);
|
|
||||||
let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
|
let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
|
||||||
let buffers_in = 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(
|
let mut full_duplex_stream = I2S::new_master(p.I2S, Irqs, p.P0_25, p.P0_26, p.P0_27, master_clock, config)
|
||||||
p.P0_29,
|
.full_duplex(p.P0_29, p.P0_28, buffers_out, buffers_in);
|
||||||
p.P0_28,
|
|
||||||
buffers_out,
|
|
||||||
buffers_in,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut modulator = SineOsc::new();
|
let mut modulator = SineOsc::new();
|
||||||
modulator.set_frequency(8.0, 1.0 / sample_rate as f32);
|
modulator.set_frequency(8.0, 1.0 / sample_rate as f32);
|
||||||
|
@ -5,14 +5,18 @@
|
|||||||
use defmt::{debug, error, info};
|
use defmt::{debug, error, info};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
|
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::pwm::{Prescaler, SimplePwm};
|
||||||
|
use embassy_nrf::{bind_interrupts, peripherals};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
type Sample = i16;
|
type Sample = i16;
|
||||||
|
|
||||||
const NUM_SAMPLES: usize = 500;
|
const NUM_SAMPLES: usize = 500;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_nrf::init(Default::default());
|
let p = embassy_nrf::init(Default::default());
|
||||||
@ -26,10 +30,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.sample_width = SampleWidth::_16bit;
|
config.sample_width = SampleWidth::_16bit;
|
||||||
config.channels = Channels::MonoLeft;
|
config.channels = Channels::MonoLeft;
|
||||||
|
|
||||||
let irq = interrupt::take!(I2S);
|
|
||||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||||
let mut input_stream =
|
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
|
// 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);
|
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 defmt::{error, info};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S};
|
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 _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
type Sample = i16;
|
type Sample = i16;
|
||||||
|
|
||||||
const NUM_SAMPLES: usize = 50;
|
const NUM_SAMPLES: usize = 50;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
I2S => i2s::InterruptHandler<peripherals::I2S>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_nrf::init(Default::default());
|
let p = embassy_nrf::init(Default::default());
|
||||||
@ -27,10 +31,9 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.sample_width = SampleWidth::_16bit;
|
config.sample_width = SampleWidth::_16bit;
|
||||||
config.channels = Channels::MonoLeft;
|
config.channels = Channels::MonoLeft;
|
||||||
|
|
||||||
let irq = interrupt::take!(I2S);
|
|
||||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||||
let mut output_stream =
|
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);
|
let mut waveform = Waveform::new(1.0 / sample_rate as f32);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user