aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/i2s.rs549
-rw-r--r--examples/nrf/src/bin/i2s-generate.rs (renamed from examples/nrf/src/bin/i2s.rs)73
2 files changed, 492 insertions, 130 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index e6dfb690c..53d9f9a1b 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -1,27 +1,27 @@
1#![macro_use] 1#![macro_use]
2 2
3//! I2S 3//! Support for I2S audio
4 4
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::sync::atomic::{compiler_fence, Ordering}; 7use core::sync::atomic::{compiler_fence, Ordering};
8use core::task::Poll; 8use core::task::Poll;
9 9
10use embassy_cortex_m::interrupt::{InterruptExt, Priority}; 10use embassy_cortex_m::interrupt::InterruptExt;
11use embassy_hal_common::drop::OnDrop; 11use embassy_hal_common::drop::OnDrop;
12use embassy_hal_common::{into_ref, PeripheralRef}; 12use embassy_hal_common::{into_ref, PeripheralRef};
13 13
14use crate::gpio::{AnyPin, Pin as GpioPin}; 14use crate::gpio::{AnyPin, Pin as GpioPin};
15use crate::interrupt::Interrupt; 15use crate::interrupt::Interrupt;
16use crate::pac::i2s::{RegisterBlock, CONFIG, PSEL}; 16use crate::pac::i2s::RegisterBlock;
17use crate::Peripheral; 17use crate::Peripheral;
18 18
19// TODO: Define those in lib.rs somewhere else 19// TODO: Define those in lib.rs somewhere else
20// 20
21// I2S EasyDMA MAXCNT bit length = 14 21/// I2S EasyDMA MAXCNT bit length = 14
22const MAX_DMA_MAXCNT: u32 = 1 << 14; 22const MAX_DMA_MAXCNT: u32 = 1 << 14;
23 23
24// Limits for Easy DMA - it can only read from data ram 24/// Limits for Easy DMA - it can only read from data ram
25pub const SRAM_LOWER: usize = 0x2000_0000; 25pub const SRAM_LOWER: usize = 0x2000_0000;
26pub const SRAM_UPPER: usize = 0x3000_0000; 26pub const SRAM_UPPER: usize = 0x3000_0000;
27 27
@@ -36,35 +36,144 @@ pub enum Error {
36 BufferLengthMisaligned, 36 BufferLengthMisaligned,
37} 37}
38 38
39pub const MODE_MASTER_8000: Mode = Mode::Master { 39/// Approximate sample rates.
40 freq: MckFreq::_32MDiv125, 40///
41 ratio: Ratio::_32x, 41/// Those are common sample rates that can not be configured without an small error.
42}; // error = 0 42///
43pub const MODE_MASTER_11025: Mode = Mode::Master { 43/// For custom master clock configuration, please refer to [Mode].
44 freq: MckFreq::_32MDiv15, 44#[derive(Clone, Copy)]
45 ratio: Ratio::_192x, 45pub enum ApproxSampleRate {
46}; // error = 86 46 _11025,
47pub const MODE_MASTER_16000: Mode = Mode::Master { 47 _16000,
48 freq: MckFreq::_32MDiv21, 48 _22050,
49 ratio: Ratio::_96x, 49 _32000,
50}; // error = 127 50 _44100,
51pub const MODE_MASTER_22050: Mode = Mode::Master { 51 _48000,
52 freq: MckFreq::_32MDiv15, 52}
53 ratio: Ratio::_96x, 53
54}; // error = 172 54impl From<ApproxSampleRate> for Mode {
55pub const MODE_MASTER_32000: Mode = Mode::Master { 55 fn from(value: ApproxSampleRate) -> Self {
56 freq: MckFreq::_32MDiv21, 56 match value {
57 ratio: Ratio::_48x, 57 // error = 86
58}; // error = 254 58 ApproxSampleRate::_11025 => Mode::Master {
59pub const MODE_MASTER_44100: Mode = Mode::Master { 59 freq: MckFreq::_32MDiv15,
60 freq: MckFreq::_32MDiv15, 60 ratio: Ratio::_192x,
61 ratio: Ratio::_48x, 61 },
62}; // error = 344 62 // error = 127
63pub const MODE_MASTER_48000: Mode = Mode::Master { 63 ApproxSampleRate::_16000 => Mode::Master {
64 freq: MckFreq::_32MDiv21, 64 freq: MckFreq::_32MDiv21,
65 ratio: Ratio::_32x, 65 ratio: Ratio::_96x,
66}; // error = 381 66 },
67 // error = 172
68 ApproxSampleRate::_22050 => Mode::Master {
69 freq: MckFreq::_32MDiv15,
70 ratio: Ratio::_96x,
71 },
72 // error = 254
73 ApproxSampleRate::_32000 => Mode::Master {
74 freq: MckFreq::_32MDiv21,
75 ratio: Ratio::_48x,
76 },
77 // error = 344
78 ApproxSampleRate::_44100 => Mode::Master {
79 freq: MckFreq::_32MDiv15,
80 ratio: Ratio::_48x,
81 },
82 // error = 381
83 ApproxSampleRate::_48000 => Mode::Master {
84 freq: MckFreq::_32MDiv21,
85 ratio: Ratio::_32x,
86 },
87 }
88 }
89}
90
91impl ApproxSampleRate {
92 pub fn sample_rate(&self) -> u32 {
93 // This will always provide a Master mode, so it is safe to unwrap.
94 Mode::from(*self).sample_rate().unwrap()
95 }
96}
97
98/// Exact sample rates.
99///
100/// Those are non standard sample rates that can be configured without error.
101///
102/// For custom master clock configuration, please refer to [Mode].
103#[derive(Clone, Copy)]
104pub enum ExactSampleRate {
105 _8000,
106 _10582,
107 _12500,
108 _15625,
109 _15873,
110 _25000,
111 _31250,
112 _50000,
113 _62500,
114 _100000,
115 _125000,
116}
67 117
118impl ExactSampleRate {
119 pub fn sample_rate(&self) -> u32 {
120 // This will always provide a Master mode, so it is safe to unwrap.
121 Mode::from(*self).sample_rate().unwrap()
122 }
123}
124
125impl From<ExactSampleRate> for Mode {
126 fn from(value: ExactSampleRate) -> Self {
127 match value {
128 ExactSampleRate::_8000 => Mode::Master {
129 freq: MckFreq::_32MDiv125,
130 ratio: Ratio::_32x,
131 },
132 ExactSampleRate::_10582 => Mode::Master {
133 freq: MckFreq::_32MDiv63,
134 ratio: Ratio::_48x,
135 },
136 ExactSampleRate::_12500 => Mode::Master {
137 freq: MckFreq::_32MDiv10,
138 ratio: Ratio::_256x,
139 },
140 ExactSampleRate::_15625 => Mode::Master {
141 freq: MckFreq::_32MDiv32,
142 ratio: Ratio::_64x,
143 },
144 ExactSampleRate::_15873 => Mode::Master {
145 freq: MckFreq::_32MDiv63,
146 ratio: Ratio::_32x,
147 },
148 ExactSampleRate::_25000 => Mode::Master {
149 freq: MckFreq::_32MDiv10,
150 ratio: Ratio::_128x,
151 },
152 ExactSampleRate::_31250 => Mode::Master {
153 freq: MckFreq::_32MDiv32,
154 ratio: Ratio::_32x,
155 },
156 ExactSampleRate::_50000 => Mode::Master {
157 freq: MckFreq::_32MDiv10,
158 ratio: Ratio::_64x,
159 },
160 ExactSampleRate::_62500 => Mode::Master {
161 freq: MckFreq::_32MDiv16,
162 ratio: Ratio::_32x,
163 },
164 ExactSampleRate::_100000 => Mode::Master {
165 freq: MckFreq::_32MDiv10,
166 ratio: Ratio::_32x,
167 },
168 ExactSampleRate::_125000 => Mode::Master {
169 freq: MckFreq::_32MDiv8,
170 ratio: Ratio::_32x,
171 },
172 }
173 }
174}
175
176/// I2S configuration.
68#[derive(Clone)] 177#[derive(Clone)]
69#[non_exhaustive] 178#[non_exhaustive]
70pub struct Config { 179pub struct Config {
@@ -78,7 +187,7 @@ pub struct Config {
78impl Default for Config { 187impl Default for Config {
79 fn default() -> Self { 188 fn default() -> Self {
80 Self { 189 Self {
81 mode: MODE_MASTER_32000, 190 mode: ExactSampleRate::_31250.into(),
82 swidth: SampleWidth::_16bit, 191 swidth: SampleWidth::_16bit,
83 align: Align::Left, 192 align: Align::Left,
84 format: Format::I2S, 193 format: Format::I2S,
@@ -132,10 +241,12 @@ impl MckFreq {
132 256000, 241 256000,
133 ]; 242 ];
134 243
244 /// Return the value that needs to be written to the register.
135 pub fn to_register_value(&self) -> u32 { 245 pub fn to_register_value(&self) -> u32 {
136 Self::REGISTER_VALUES[usize::from(*self)] 246 Self::REGISTER_VALUES[usize::from(*self)]
137 } 247 }
138 248
249 /// Return the master clock frequency.
139 pub fn to_frequency(&self) -> u32 { 250 pub fn to_frequency(&self) -> u32 {
140 Self::FREQUENCIES[usize::from(*self)] 251 Self::FREQUENCIES[usize::from(*self)]
141 } 252 }
@@ -147,7 +258,10 @@ impl From<MckFreq> for usize {
147 } 258 }
148} 259}
149 260
150/// MCK / LRCK ratio. 261/// Master clock frequency ratio
262///
263/// Sample Rate = LRCK = MCK / Ratio
264///
151#[derive(Debug, Eq, PartialEq, Clone, Copy)] 265#[derive(Debug, Eq, PartialEq, Clone, Copy)]
152pub enum Ratio { 266pub enum Ratio {
153 _32x, 267 _32x,
@@ -175,6 +289,7 @@ impl From<Ratio> for u8 {
175 } 289 }
176} 290}
177 291
292/// Sample width.
178#[derive(Debug, Eq, PartialEq, Clone, Copy)] 293#[derive(Debug, Eq, PartialEq, Clone, Copy)]
179pub enum SampleWidth { 294pub enum SampleWidth {
180 _8bit, 295 _8bit,
@@ -188,7 +303,7 @@ impl From<SampleWidth> for u8 {
188 } 303 }
189} 304}
190 305
191/// Alignment of sample within a frame. 306/// Channel used for the most significant sample value in a frame.
192#[derive(Debug, Eq, PartialEq, Clone, Copy)] 307#[derive(Debug, Eq, PartialEq, Clone, Copy)]
193pub enum Align { 308pub enum Align {
194 Left, 309 Left,
@@ -220,11 +335,13 @@ impl From<Format> for bool {
220 } 335 }
221} 336}
222 337
223/// Enable channels. 338/// Channels
224#[derive(Debug, Eq, PartialEq, Clone, Copy)] 339#[derive(Debug, Eq, PartialEq, Clone, Copy)]
225pub enum Channels { 340pub enum Channels {
226 Stereo, 341 Stereo,
342 /// Mono left
227 Left, 343 Left,
344 /// Mono right
228 Right, 345 Right,
229} 346}
230 347
@@ -235,8 +352,6 @@ impl From<Channels> for u8 {
235} 352}
236 353
237/// Interface to the I2S peripheral using EasyDMA to offload the transmission and reception workload. 354/// Interface to the I2S peripheral using EasyDMA to offload the transmission and reception workload.
238///
239/// For more details about EasyDMA, consult the module documentation.
240pub struct I2S<'d, T: Instance> { 355pub struct I2S<'d, T: Instance> {
241 _p: PeripheralRef<'d, T>, 356 _p: PeripheralRef<'d, T>,
242} 357}
@@ -278,29 +393,32 @@ impl<'d, T: Instance> I2S<'d, T> {
278 ) -> Self { 393 ) -> Self {
279 into_ref!(i2s, irq, mck, sck, lrck, sdin, sdout); 394 into_ref!(i2s, irq, mck, sck, lrck, sdin, sdout);
280 395
281 let r = T::regs(); 396 Self::apply_config(&config);
282 Self::apply_config(&r.config, &config); 397 Self::select_pins(mck, sck, lrck, sdin, sdout);
283 Self::select_pins(&r.psel, mck, sck, lrck, sdin, sdout); 398 Self::setup_interrupt(irq);
284 Self::setup_interrupt(irq, r);
285 399
286 r.enable.write(|w| w.enable().enabled()); 400 T::regs().enable.write(|w| w.enable().enabled());
287 401
288 Self { _p: i2s } 402 Self { _p: i2s }
289 } 403 }
290 404
405 /// I2S output only
291 pub fn output(self) -> Output<'d, T> { 406 pub fn output(self) -> Output<'d, T> {
292 Output { _p: self._p } 407 Output { _p: self._p }
293 } 408 }
294 409
410 /// I2S input only
295 pub fn input(self) -> Input<'d, T> { 411 pub fn input(self) -> Input<'d, T> {
296 Input { _p: self._p } 412 Input { _p: self._p }
297 } 413 }
298 414
415 /// I2S full duplex (input and output)
299 pub fn full_duplex(self) -> FullDuplex<'d, T> { 416 pub fn full_duplex(self) -> FullDuplex<'d, T> {
300 FullDuplex { _p: self._p } 417 FullDuplex { _p: self._p }
301 } 418 }
302 419
303 fn apply_config(c: &CONFIG, config: &Config) { 420 fn apply_config(config: &Config) {
421 let c = &T::regs().config;
304 match config.mode { 422 match config.mode {
305 Mode::Master { freq, ratio } => { 423 Mode::Master { freq, ratio } => {
306 c.mode.write(|w| w.mode().master()); 424 c.mode.write(|w| w.mode().master());
@@ -322,13 +440,14 @@ impl<'d, T: Instance> I2S<'d, T> {
322 } 440 }
323 441
324 fn select_pins( 442 fn select_pins(
325 psel: &PSEL,
326 mck: PeripheralRef<'d, AnyPin>, 443 mck: PeripheralRef<'d, AnyPin>,
327 sck: PeripheralRef<'d, AnyPin>, 444 sck: PeripheralRef<'d, AnyPin>,
328 lrck: PeripheralRef<'d, AnyPin>, 445 lrck: PeripheralRef<'d, AnyPin>,
329 sdin: PeripheralRef<'d, AnyPin>, 446 sdin: PeripheralRef<'d, AnyPin>,
330 sdout: PeripheralRef<'d, AnyPin>, 447 sdout: PeripheralRef<'d, AnyPin>,
331 ) { 448 ) {
449 let psel = &T::regs().psel;
450
332 psel.mck.write(|w| { 451 psel.mck.write(|w| {
333 unsafe { w.bits(mck.psel_bits()) }; 452 unsafe { w.bits(mck.psel_bits()) };
334 w.connect().connected() 453 w.connect().connected()
@@ -355,21 +474,23 @@ impl<'d, T: Instance> I2S<'d, T> {
355 }); 474 });
356 } 475 }
357 476
358 fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>, r: &RegisterBlock) { 477 fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>) {
359 irq.set_handler(Self::on_interrupt); 478 irq.set_handler(Self::on_interrupt);
360 // irq.set_priority(Priority::P1); // TODO review priorities
361 irq.unpend(); 479 irq.unpend();
362 irq.enable(); 480 irq.enable();
363 481
364 let device = Device::<T>::new(); 482 let device = Device::<T>::new();
365 device.disable_tx_ptr_interrupt(); 483 device.disable_tx_ptr_interrupt();
366 device.disable_rx_ptr_interrupt(); 484 device.disable_rx_ptr_interrupt();
485 device.disable_stopped_interrupt();
367 486
368 device.reset_tx_ptr_event(); 487 device.reset_tx_ptr_event();
369 device.reset_rx_ptr_event(); 488 device.reset_rx_ptr_event();
489 device.reset_stopped_event();
370 490
371 device.enable_tx_ptr_interrupt(); 491 device.enable_tx_ptr_interrupt();
372 device.enable_rx_ptr_interrupt(); 492 device.enable_rx_ptr_interrupt();
493 device.enable_stopped_interrupt();
373 } 494 }
374 495
375 fn on_interrupt(_: *mut ()) { 496 fn on_interrupt(_: *mut ()) {
@@ -387,41 +508,40 @@ impl<'d, T: Instance> I2S<'d, T> {
387 s.rx_waker.wake(); 508 s.rx_waker.wake();
388 device.disable_rx_ptr_interrupt(); 509 device.disable_rx_ptr_interrupt();
389 } 510 }
390 }
391}
392 511
393pub struct Output<'d, T: Instance> { 512 if device.is_stopped() {
394 _p: PeripheralRef<'d, T>, 513 trace!("STOPPED INT");
395} 514 s.stop_waker.wake();
515 device.disable_stopped_interrupt();
516 }
517 }
396 518
397impl<'d, T: Instance> Output<'d, T> { 519 async fn stop() {
398 /// Starts I2S transfer. 520 compiler_fence(Ordering::SeqCst);
399 #[inline(always)]
400 pub fn start<B>(&self, buffer: B) -> Result<(), Error>
401 where
402 B: Buffer,
403 {
404 // TODO what to do if it is started already?
405 521
406 let device = Device::<T>::new(); 522 let device = Device::<T>::new();
407 device.enable(); 523 device.stop();
408 device.set_tx_buffer(buffer)?;
409 device.enable_tx();
410 device.start();
411 524
412 Ok(()) 525 T::state().started.store(false, Ordering::Relaxed);
413 }
414 526
415 /// Stops the I2S transfer and waits until it has stopped. 527 poll_fn(|cx| {
416 #[inline(always)] 528 T::state().stop_waker.register(cx.waker());
417 pub async fn stop(&self) { 529
418 todo!() 530 if device.is_stopped() {
531 trace!("STOP: Ready");
532 device.reset_stopped_event();
533 Poll::Ready(())
534 } else {
535 trace!("STOP: Pending");
536 Poll::Pending
537 }
538 })
539 .await;
540
541 device.disable();
419 } 542 }
420 543
421 /// Transmits the given `buffer`. 544 async fn send<B>(buffer: B) -> Result<(), Error>
422 /// Buffer address must be 4 byte aligned and located in RAM.
423 #[allow(unused_mut)]
424 pub async fn send<B>(&mut self, buffer: B) -> Result<(), Error>
425 where 545 where
426 B: Buffer, 546 B: Buffer,
427 { 547 {
@@ -454,24 +574,191 @@ impl<'d, T: Instance> Output<'d, T> {
454 574
455 Ok(()) 575 Ok(())
456 } 576 }
577
578 async fn receive<B>(buffer: B) -> Result<(), Error>
579 where
580 B: Buffer,
581 {
582 trace!("RECEIVE: {}", buffer.bytes_ptr() as u32);
583
584 let device = Device::<T>::new();
585 let drop = device.on_rx_drop();
586
587 compiler_fence(Ordering::SeqCst);
588
589 poll_fn(|cx| {
590 T::state().rx_waker.register(cx.waker());
591
592 if device.is_rx_ptr_updated() {
593 trace!("RX POLL: Ready");
594 device.reset_rx_ptr_event();
595 device.enable_rx_ptr_interrupt();
596 Poll::Ready(())
597 } else {
598 trace!("RX POLL: Pending");
599 Poll::Pending
600 }
601 })
602 .await;
603
604 device.set_rx_buffer(buffer)?;
605
606 compiler_fence(Ordering::SeqCst);
607 drop.defuse();
608
609 Ok(())
610 }
611}
612
613/// I2S output
614pub struct Output<'d, T: Instance> {
615 _p: PeripheralRef<'d, T>,
616}
617
618impl<'d, T: Instance> Output<'d, T> {
619 /// Prepare the initial buffer and start the I2S transfer.
620 pub async fn start<B>(&self, buffer: B) -> Result<(), Error>
621 where
622 B: Buffer,
623 {
624 let device = Device::<T>::new();
625
626 let s = T::state();
627 if s.started.load(Ordering::Relaxed) {
628 self.stop().await;
629 }
630
631 device.enable();
632 device.enable_tx();
633 device.set_tx_buffer(buffer)?;
634
635 s.started.store(true, Ordering::Relaxed);
636
637 device.start();
638
639 Ok(())
640 }
641
642 /// Stops the I2S transfer and waits until it has stopped.
643 #[inline(always)]
644 pub async fn stop(&self) {
645 I2S::<T>::stop().await
646 }
647
648 /// Sets the given `buffer` for transmission in the DMA.
649 /// Buffer address must be 4 byte aligned and located in RAM.
650 /// The buffer must not be written while being used by the DMA,
651 /// which takes two other `send`s being awaited.
652 #[allow(unused_mut)]
653 pub async fn send<B>(&mut self, buffer: B) -> Result<(), Error>
654 where
655 B: Buffer,
656 {
657 I2S::<T>::send(buffer).await
658 }
457} 659}
458 660
661/// I2S input
459pub struct Input<'d, T: Instance> { 662pub struct Input<'d, T: Instance> {
460 _p: PeripheralRef<'d, T>, 663 _p: PeripheralRef<'d, T>,
461} 664}
462 665
463impl<'d, T: Instance> Input<'d, T> { 666impl<'d, T: Instance> Input<'d, T> {
464 // TODO 667 /// Prepare the initial buffer and start the I2S transfer.
668 pub async fn start<B>(&self, buffer: B) -> Result<(), Error>
669 where
670 B: Buffer,
671 {
672 let device = Device::<T>::new();
673
674 let s = T::state();
675 if s.started.load(Ordering::Relaxed) {
676 self.stop().await;
677 }
678
679 device.enable();
680 device.enable_rx();
681 device.set_rx_buffer(buffer)?;
682
683 s.started.store(true, Ordering::Relaxed);
684
685 device.start();
686
687 Ok(())
688 }
689
690 /// Stops the I2S transfer and waits until it has stopped.
691 #[inline(always)]
692 pub async fn stop(&self) {
693 I2S::<T>::stop().await
694 }
695
696 /// Sets the given `buffer` for reception from the DMA.
697 /// Buffer address must be 4 byte aligned and located in RAM.
698 /// The buffer must not be read while being used by the DMA,
699 /// which takes two other `receive`s being awaited.
700 #[allow(unused_mut)]
701 pub async fn receive<B>(&mut self, buffer: B) -> Result<(), Error>
702 where
703 B: Buffer,
704 {
705 I2S::<T>::receive(buffer).await
706 }
465} 707}
466 708
709/// I2S ful duplex (input & output)
467pub struct FullDuplex<'d, T: Instance> { 710pub struct FullDuplex<'d, T: Instance> {
468 _p: PeripheralRef<'d, T>, 711 _p: PeripheralRef<'d, T>,
469} 712}
470 713
471impl<'d, T: Instance> FullDuplex<'d, T> { 714impl<'d, T: Instance> FullDuplex<'d, T> {
472 // TODO 715 /// Prepare the initial buffers and start the I2S transfer.
716 pub async fn start<B>(&self, buffer_out: B, buffer_in: B) -> Result<(), Error>
717 where
718 B: Buffer,
719 {
720 let device = Device::<T>::new();
721
722 let s = T::state();
723 if s.started.load(Ordering::Relaxed) {
724 self.stop().await;
725 }
726
727 device.enable();
728 device.enable_tx();
729 device.enable_rx();
730 device.set_tx_buffer(buffer_out)?;
731 device.set_rx_buffer(buffer_in)?;
732
733 s.started.store(true, Ordering::Relaxed);
734
735 device.start();
736
737 Ok(())
738 }
739
740 /// Stops the I2S transfer and waits until it has stopped.
741 #[inline(always)]
742 pub async fn stop(&self) {
743 I2S::<T>::stop().await
744 }
745
746 /// Sets the given `buffer_out` and `buffer_in` for transmission/reception from the DMA.
747 /// Buffer address must be 4 byte aligned and located in RAM.
748 /// The buffers must not be written/read while being used by the DMA,
749 /// which takes two other `send_and_receive` operations being awaited.
750 #[allow(unused_mut)]
751 pub async fn send_and_receive<B>(&mut self, buffer_out: B, buffer_in: B) -> Result<(), Error>
752 where
753 B: Buffer,
754 {
755 I2S::<T>::send(buffer_out).await?;
756 I2S::<T>::receive(buffer_in).await?;
757 Ok(())
758 }
473} 759}
474 760
761/// Helper encapsulating common I2S device operations.
475struct Device<T>(&'static RegisterBlock, PhantomData<T>); 762struct Device<T>(&'static RegisterBlock, PhantomData<T>);
476 763
477impl<T: Instance> Device<T> { 764impl<T: Instance> Device<T> {
@@ -521,6 +808,34 @@ impl<T: Instance> Device<T> {
521 self.0.tasks_start.write(|w| unsafe { w.bits(1) }); 808 self.0.tasks_start.write(|w| unsafe { w.bits(1) });
522 } 809 }
523 810
811 #[inline(always)]
812 fn stop(&self) {
813 self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
814 }
815
816 #[inline(always)]
817 fn is_stopped(&self) -> bool {
818 self.0.events_stopped.read().bits() != 0
819 }
820
821 #[inline(always)]
822 fn reset_stopped_event(&self) {
823 trace!("STOPPED EVENT: Reset");
824 self.0.events_stopped.reset();
825 }
826
827 #[inline(always)]
828 fn disable_stopped_interrupt(&self) {
829 trace!("STOPPED INTERRUPT: Disabled");
830 self.0.intenclr.write(|w| w.stopped().clear());
831 }
832
833 #[inline(always)]
834 fn enable_stopped_interrupt(&self) {
835 trace!("STOPPED INTERRUPT: Enabled");
836 self.0.intenset.write(|w| w.stopped().set());
837 }
838
524 #[inline] 839 #[inline]
525 fn set_tx_buffer<B>(&self, buffer: B) -> Result<(), Error> 840 fn set_tx_buffer<B>(&self, buffer: B) -> Result<(), Error>
526 where 841 where
@@ -606,6 +921,23 @@ impl<T: Instance> Device<T> {
606 }) 921 })
607 } 922 }
608 923
924 #[inline]
925 fn on_rx_drop(&self) -> OnDrop<fn()> {
926 OnDrop::new(move || {
927 trace!("RX DROP: Stopping");
928
929 let device = Device::<T>::new();
930 device.disable_rx_ptr_interrupt();
931 device.reset_rx_ptr_event();
932 device.disable_rx();
933
934 // TX is stopped almost instantly, spinning is fine.
935 while !device.is_rx_ptr_updated() {}
936
937 trace!("RX DROP: Stopped");
938 })
939 }
940
609 fn validate_buffer<B>(buffer: B) -> Result<(u32, u32), Error> 941 fn validate_buffer<B>(buffer: B) -> Result<(u32, u32), Error>
610 where 942 where
611 B: Buffer, 943 B: Buffer,
@@ -632,6 +964,56 @@ impl<T: Instance> Device<T> {
632 } 964 }
633} 965}
634 966
967/// Sample details
968pub trait Sample: Sized + Copy + Default {
969 const WIDTH: usize;
970 const SCALE: Self;
971}
972
973impl Sample for i8 {
974 const WIDTH: usize = 8;
975 const SCALE: Self = 1 << (Self::WIDTH - 1);
976}
977
978impl Sample for i16 {
979 const WIDTH: usize = 16;
980 const SCALE: Self = 1 << (Self::WIDTH - 1);
981}
982
983impl Sample for i32 {
984 const WIDTH: usize = 24;
985 const SCALE: Self = 1 << (Self::WIDTH - 1);
986}
987
988/// A 4-bytes aligned [Buffer].
989#[repr(align(4))]
990pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
991
992impl<T: Sample, const N: usize> AlignedBuffer<T, N> {
993 pub fn new(array: [T; N]) -> Self {
994 Self(array)
995 }
996}
997
998impl<T: Sample, const N: usize> Default for AlignedBuffer<T, N> {
999 fn default() -> Self {
1000 Self([T::default(); N])
1001 }
1002}
1003
1004impl<T: Sample, const N: usize> AsRef<[T]> for AlignedBuffer<T, N> {
1005 fn as_ref(&self) -> &[T] {
1006 self.0.as_slice()
1007 }
1008}
1009
1010impl<T: Sample, const N: usize> AsMut<[T]> for AlignedBuffer<T, N> {
1011 fn as_mut(&mut self) -> &mut [T] {
1012 self.0.as_mut_slice()
1013 }
1014}
1015
1016/// Common operations required for a buffer to be used by the DMA
635pub trait Buffer: Sized { 1017pub trait Buffer: Sized {
636 fn bytes_ptr(&self) -> *const u8; 1018 fn bytes_ptr(&self) -> *const u8;
637 fn bytes_len(&self) -> usize; 1019 fn bytes_len(&self) -> usize;
@@ -674,22 +1056,25 @@ impl Buffer for &[i32] {
674} 1056}
675 1057
676pub(crate) mod sealed { 1058pub(crate) mod sealed {
677 use core::sync::atomic::AtomicI32; 1059 use core::sync::atomic::AtomicBool;
678 1060
679 use embassy_sync::waitqueue::AtomicWaker; 1061 use embassy_sync::waitqueue::AtomicWaker;
680 1062
681 use super::*; 1063 /// Peripheral static state
682
683 pub struct State { 1064 pub struct State {
1065 pub started: AtomicBool,
684 pub rx_waker: AtomicWaker, 1066 pub rx_waker: AtomicWaker,
685 pub tx_waker: AtomicWaker, 1067 pub tx_waker: AtomicWaker,
1068 pub stop_waker: AtomicWaker,
686 } 1069 }
687 1070
688 impl State { 1071 impl State {
689 pub const fn new() -> Self { 1072 pub const fn new() -> Self {
690 Self { 1073 Self {
1074 started: AtomicBool::new(false),
691 rx_waker: AtomicWaker::new(), 1075 rx_waker: AtomicWaker::new(),
692 tx_waker: AtomicWaker::new(), 1076 tx_waker: AtomicWaker::new(),
1077 stop_waker: AtomicWaker::new(),
693 } 1078 }
694 } 1079 }
695 } 1080 }
@@ -704,8 +1089,6 @@ pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
704 type Interrupt: Interrupt; 1089 type Interrupt: Interrupt;
705} 1090}
706 1091
707// TODO: Unsure why this macro is flagged as unused by CI when in fact it's used elsewhere?
708#[allow(unused_macros)]
709macro_rules! impl_i2s { 1092macro_rules! impl_i2s {
710 ($type:ident, $pac_type:ident, $irq:ident) => { 1093 ($type:ident, $pac_type:ident, $irq:ident) => {
711 impl crate::i2s::sealed::Instance for peripherals::$type { 1094 impl crate::i2s::sealed::Instance for peripherals::$type {
diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s-generate.rs
index 9b3144f24..f59b63ce6 100644
--- a/examples/nrf/src/bin/i2s.rs
+++ b/examples/nrf/src/bin/i2s-generate.rs
@@ -4,59 +4,41 @@
4 4
5use core::f32::consts::PI; 5use core::f32::consts::PI;
6 6
7use defmt::{error, info, trace}; 7use defmt::{error, info};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::gpio::{Input, Pin, Pull}; 9use embassy_nrf::i2s::{self, Sample as _};
10use embassy_nrf::i2s::{Channels, MckFreq, Mode, Ratio, SampleWidth, MODE_MASTER_32000}; 10use embassy_nrf::interrupt;
11use embassy_nrf::pac::ficr::info;
12use embassy_nrf::{i2s, interrupt};
13use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
14 12
15#[repr(align(4))]
16pub struct AlignedBuffer<T: ?Sized>(T);
17
18impl<T> AsRef<T> for AlignedBuffer<T> {
19 fn as_ref(&self) -> &T {
20 &self.0
21 }
22}
23
24impl<T> AsMut<T> for AlignedBuffer<T> {
25 fn as_mut(&mut self) -> &mut T {
26 &mut self.0
27 }
28}
29
30#[embassy_executor::main] 13#[embassy_executor::main]
31async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
32 let p = embassy_nrf::init(Default::default()); 15 let p = embassy_nrf::init(Default::default());
16
33 let mut config = i2s::Config::default(); 17 let mut config = i2s::Config::default();
34 config.mode = MODE_MASTER_32000; 18 config.mode = i2s::ExactSampleRate::_50000.into();
35 // config.mode = Mode::Master { 19 config.channels = i2s::Channels::Left;
36 // freq: MckFreq::_32MDiv10, 20 config.swidth = i2s::SampleWidth::_16bit;
37 // ratio: Ratio::_256x,
38 // }; // 12500 Hz
39 config.channels = Channels::Left;
40 config.swidth = SampleWidth::_16bit;
41 let sample_rate = config.mode.sample_rate().expect("I2S Master"); 21 let sample_rate = config.mode.sample_rate().expect("I2S Master");
42 let inv_sample_rate = 1.0 / sample_rate as f32; 22 let inv_sample_rate = 1.0 / sample_rate as f32;
43 23
44 info!("Sample rate: {}", sample_rate); 24 info!("Sample rate: {}", sample_rate);
45 25
46 // Wait for a button press 26 // Wait for a button press
27 // use embassy_nrf::gpio::{Input, Pin, Pull};
47 // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); 28 // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up);
48 // btn1.wait_for_low().await; 29 // btn1.wait_for_low().await;
49 30
50 let irq = interrupt::take!(I2S); 31 let irq = interrupt::take!(I2S);
51 let mut i2s = i2s::I2S::new(p.I2S, irq, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config).output(); 32 let mut i2s = i2s::I2S::new(p.I2S, irq, p.P0_28, p.P0_29, p.P0_31, p.P0_27, p.P0_30, config)
33 .output();
52 34
53 type Sample = i16; 35 type Sample = i16;
54 const MAX_UNIPOLAR_VALUE: Sample = (1 << 15) as Sample; 36 const NUM_SAMPLES: usize = 6000;
55 const NUM_SAMPLES: usize = 2000; 37
56 let mut buffers: [AlignedBuffer<[Sample; NUM_SAMPLES]>; 3] = [ 38 let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; 3] = [
57 AlignedBuffer([0; NUM_SAMPLES]), 39 i2s::AlignedBuffer::default(),
58 AlignedBuffer([0; NUM_SAMPLES]), 40 i2s::AlignedBuffer::default(),
59 AlignedBuffer([0; NUM_SAMPLES]), 41 i2s::AlignedBuffer::default(),
60 ]; 42 ];
61 43
62 let mut carrier = SineOsc::new(); 44 let mut carrier = SineOsc::new();
@@ -66,32 +48,29 @@ async fn main(_spawner: Spawner) {
66 freq_mod.set_amplitude(1.0); 48 freq_mod.set_amplitude(1.0);
67 49
68 let mut amp_mod = SineOsc::new(); 50 let mut amp_mod = SineOsc::new();
69 amp_mod.set_frequency(4.0, inv_sample_rate); 51 amp_mod.set_frequency(16.0, inv_sample_rate);
70 amp_mod.set_amplitude(0.5); 52 amp_mod.set_amplitude(0.5);
71 53
72 let mut generate = |buf: &mut [Sample]| { 54 let mut generate = |buf: &mut [Sample]| {
73 let ptr = buf as *const [Sample] as *const Sample as u32; 55 for sample in &mut buf.chunks_mut(1) {
74 trace!("GEN: {}", ptr);
75
76 for sample in &mut buf.as_mut().chunks_mut(1) {
77 let signal = carrier.generate();
78 let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); 56 let freq_modulation = bipolar_to_unipolar(freq_mod.generate());
79 carrier.set_frequency(220.0 + 220.0 * freq_modulation, inv_sample_rate); 57 carrier.set_frequency(220.0 + 440.0 * freq_modulation, inv_sample_rate);
80 let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); 58 let amp_modulation = bipolar_to_unipolar(amp_mod.generate());
81 carrier.set_amplitude(amp_modulation); 59 carrier.set_amplitude(amp_modulation);
82 let value = (MAX_UNIPOLAR_VALUE as f32 * signal) as Sample; 60 let signal = carrier.generate();
61 let value = (Sample::SCALE as f32 * signal) as Sample;
83 sample[0] = value; 62 sample[0] = value;
84 } 63 }
85 }; 64 };
86 65
87 generate(buffers[0].as_mut().as_mut_slice()); 66 generate(buffers[0].as_mut());
88 generate(buffers[1].as_mut().as_mut_slice()); 67 generate(buffers[1].as_mut());
89 68
90 i2s.start(buffers[0].as_ref().as_slice()).expect("I2S Start"); 69 i2s.start(buffers[0].as_ref()).await.expect("I2S Start");
91 70
92 let mut index = 1; 71 let mut index = 1;
93 loop { 72 loop {
94 if let Err(err) = i2s.send(buffers[index].as_ref().as_slice()).await { 73 if let Err(err) = i2s.send(buffers[index].as_ref()).await {
95 error!("{}", err); 74 error!("{}", err);
96 } 75 }
97 76
@@ -99,7 +78,7 @@ async fn main(_spawner: Spawner) {
99 if index >= 3 { 78 if index >= 3 {
100 index = 0; 79 index = 0;
101 } 80 }
102 generate(buffers[index].as_mut().as_mut_slice()); 81 generate(buffers[index].as_mut());
103 } 82 }
104} 83}
105 84