embassy_nrf/
i2s.rs

1//! Inter-IC Sound (I2S) driver.
2
3#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::mem::size_of;
8use core::ops::{Deref, DerefMut};
9use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
10use core::task::Poll;
11
12use embassy_hal_internal::drop::OnDrop;
13use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::AtomicWaker;
15
16use crate::gpio::{AnyPin, Pin as GpioPin, PselBits};
17use crate::interrupt::typelevel::Interrupt;
18use crate::pac::i2s::vals;
19use crate::util::slice_in_ram_or;
20use crate::{interrupt, pac, EASY_DMA_SIZE};
21
22/// Type alias for `MultiBuffering` with 2 buffers.
23pub type DoubleBuffering<S, const NS: usize> = MultiBuffering<S, 2, NS>;
24
25/// I2S transfer error.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28#[non_exhaustive]
29pub enum Error {
30    /// The buffer is too long.
31    BufferTooLong,
32    /// The buffer is empty.
33    BufferZeroLength,
34    /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash.
35    BufferNotInRAM,
36    /// The buffer address is not aligned.
37    BufferMisaligned,
38    /// The buffer length is not a multiple of the alignment.
39    BufferLengthMisaligned,
40}
41
42/// I2S configuration.
43#[derive(Clone)]
44#[non_exhaustive]
45pub struct Config {
46    /// Sample width
47    pub sample_width: SampleWidth,
48    /// Alignment
49    pub align: Align,
50    /// Sample format
51    pub format: Format,
52    /// Channel configuration.
53    pub channels: Channels,
54}
55
56impl Default for Config {
57    fn default() -> Self {
58        Self {
59            sample_width: SampleWidth::_16bit,
60            align: Align::Left,
61            format: Format::I2S,
62            channels: Channels::Stereo,
63        }
64    }
65}
66
67/// I2S clock configuration.
68#[derive(Debug, Eq, PartialEq, Clone, Copy)]
69pub struct MasterClock {
70    freq: MckFreq,
71    ratio: Ratio,
72}
73
74impl MasterClock {
75    /// Create a new `MasterClock`.
76    pub fn new(freq: MckFreq, ratio: Ratio) -> Self {
77        Self { freq, ratio }
78    }
79}
80
81impl MasterClock {
82    /// Get the sample rate for this clock configuration.
83    pub fn sample_rate(&self) -> u32 {
84        self.freq.to_frequency() / self.ratio.to_divisor()
85    }
86}
87
88/// Master clock generator frequency.
89#[derive(Debug, Eq, PartialEq, Clone, Copy)]
90pub enum MckFreq {
91    /// 32 Mhz / 8 = 4000.00 kHz
92    _32MDiv8,
93    /// 32 Mhz / 10 = 3200.00 kHz
94    _32MDiv10,
95    /// 32 Mhz / 11 = 2909.09 kHz
96    _32MDiv11,
97    /// 32 Mhz / 15 = 2133.33 kHz
98    _32MDiv15,
99    /// 32 Mhz / 16 = 2000.00 kHz
100    _32MDiv16,
101    /// 32 Mhz / 21 = 1523.81 kHz
102    _32MDiv21,
103    /// 32 Mhz / 23 = 1391.30 kHz
104    _32MDiv23,
105    /// 32 Mhz / 30 = 1066.67 kHz
106    _32MDiv30,
107    /// 32 Mhz / 31 = 1032.26 kHz
108    _32MDiv31,
109    /// 32 Mhz / 32 = 1000.00 kHz
110    _32MDiv32,
111    /// 32 Mhz / 42 = 761.90 kHz
112    _32MDiv42,
113    /// 32 Mhz / 63 = 507.94 kHz
114    _32MDiv63,
115    /// 32 Mhz / 125 = 256.00 kHz
116    _32MDiv125,
117}
118
119impl MckFreq {
120    const REGISTER_VALUES: &'static [vals::Mckfreq] = &[
121        vals::Mckfreq::_32MDIV8,
122        vals::Mckfreq::_32MDIV10,
123        vals::Mckfreq::_32MDIV11,
124        vals::Mckfreq::_32MDIV15,
125        vals::Mckfreq::_32MDIV16,
126        vals::Mckfreq::_32MDIV21,
127        vals::Mckfreq::_32MDIV23,
128        vals::Mckfreq::_32MDIV30,
129        vals::Mckfreq::_32MDIV31,
130        vals::Mckfreq::_32MDIV32,
131        vals::Mckfreq::_32MDIV42,
132        vals::Mckfreq::_32MDIV63,
133        vals::Mckfreq::_32MDIV125,
134    ];
135
136    const FREQUENCIES: &'static [u32] = &[
137        4000000, 3200000, 2909090, 2133333, 2000000, 1523809, 1391304, 1066666, 1032258, 1000000, 761904, 507936,
138        256000,
139    ];
140
141    /// Return the value that needs to be written to the register.
142    pub fn to_register_value(&self) -> vals::Mckfreq {
143        Self::REGISTER_VALUES[usize::from(*self)]
144    }
145
146    /// Return the master clock frequency.
147    pub fn to_frequency(&self) -> u32 {
148        Self::FREQUENCIES[usize::from(*self)]
149    }
150}
151
152impl From<MckFreq> for usize {
153    fn from(variant: MckFreq) -> Self {
154        variant as _
155    }
156}
157
158/// Master clock frequency ratio
159///
160/// Sample Rate = LRCK = MCK / Ratio
161///
162#[derive(Debug, Eq, PartialEq, Clone, Copy)]
163pub enum Ratio {
164    /// Divide by 32
165    _32x,
166    /// Divide by 48
167    _48x,
168    /// Divide by 64
169    _64x,
170    /// Divide by 96
171    _96x,
172    /// Divide by 128
173    _128x,
174    /// Divide by 192
175    _192x,
176    /// Divide by 256
177    _256x,
178    /// Divide by 384
179    _384x,
180    /// Divide by 512
181    _512x,
182}
183
184impl Ratio {
185    const RATIOS: &'static [u32] = &[32, 48, 64, 96, 128, 192, 256, 384, 512];
186
187    /// Return the value that needs to be written to the register.
188    pub fn to_register_value(&self) -> vals::Ratio {
189        vals::Ratio::from_bits(*self as u8)
190    }
191
192    /// Return the divisor for this ratio
193    pub fn to_divisor(&self) -> u32 {
194        Self::RATIOS[usize::from(*self)]
195    }
196}
197
198impl From<Ratio> for usize {
199    fn from(variant: Ratio) -> Self {
200        variant as _
201    }
202}
203
204/// Approximate sample rates.
205///
206/// Those are common sample rates that can not be configured without an small error.
207///
208/// For custom master clock configuration, please refer to [MasterClock].
209#[derive(Clone, Copy)]
210pub enum ApproxSampleRate {
211    /// 11025 Hz
212    _11025,
213    /// 16000 Hz
214    _16000,
215    /// 22050 Hz
216    _22050,
217    /// 32000 Hz
218    _32000,
219    /// 44100 Hz
220    _44100,
221    /// 48000 Hz
222    _48000,
223}
224
225impl From<ApproxSampleRate> for MasterClock {
226    fn from(value: ApproxSampleRate) -> Self {
227        match value {
228            // error = 86
229            ApproxSampleRate::_11025 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_192x),
230            // error = 127
231            ApproxSampleRate::_16000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_96x),
232            // error = 172
233            ApproxSampleRate::_22050 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_96x),
234            // error = 254
235            ApproxSampleRate::_32000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_48x),
236            // error = 344
237            ApproxSampleRate::_44100 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_48x),
238            // error = 381
239            ApproxSampleRate::_48000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_32x),
240        }
241    }
242}
243
244impl ApproxSampleRate {
245    /// Get the sample rate as an integer.
246    pub fn sample_rate(&self) -> u32 {
247        MasterClock::from(*self).sample_rate()
248    }
249}
250
251/// Exact sample rates.
252///
253/// Those are non standard sample rates that can be configured without error.
254///
255/// For custom master clock configuration, please refer to [Mode].
256#[derive(Clone, Copy)]
257pub enum ExactSampleRate {
258    /// 8000 Hz
259    _8000,
260    /// 10582 Hz
261    _10582,
262    /// 12500 Hz
263    _12500,
264    /// 15625 Hz
265    _15625,
266    /// 15873 Hz
267    _15873,
268    /// 25000 Hz
269    _25000,
270    /// 31250 Hz
271    _31250,
272    /// 50000 Hz
273    _50000,
274    /// 62500 Hz
275    _62500,
276    /// 100000 Hz
277    _100000,
278    /// 125000 Hz
279    _125000,
280}
281
282impl ExactSampleRate {
283    /// Get the sample rate as an integer.
284    pub fn sample_rate(&self) -> u32 {
285        MasterClock::from(*self).sample_rate()
286    }
287}
288
289impl From<ExactSampleRate> for MasterClock {
290    fn from(value: ExactSampleRate) -> Self {
291        match value {
292            ExactSampleRate::_8000 => MasterClock::new(MckFreq::_32MDiv125, Ratio::_32x),
293            ExactSampleRate::_10582 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_48x),
294            ExactSampleRate::_12500 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_256x),
295            ExactSampleRate::_15625 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_64x),
296            ExactSampleRate::_15873 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_32x),
297            ExactSampleRate::_25000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_128x),
298            ExactSampleRate::_31250 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_32x),
299            ExactSampleRate::_50000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_64x),
300            ExactSampleRate::_62500 => MasterClock::new(MckFreq::_32MDiv16, Ratio::_32x),
301            ExactSampleRate::_100000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_32x),
302            ExactSampleRate::_125000 => MasterClock::new(MckFreq::_32MDiv8, Ratio::_32x),
303        }
304    }
305}
306
307/// Sample width.
308#[derive(Debug, Eq, PartialEq, Clone, Copy)]
309pub enum SampleWidth {
310    /// 8 bit samples.
311    _8bit,
312    /// 16 bit samples.
313    _16bit,
314    /// 24 bit samples.
315    _24bit,
316}
317
318impl From<SampleWidth> for vals::Swidth {
319    fn from(variant: SampleWidth) -> Self {
320        vals::Swidth::from_bits(variant as u8)
321    }
322}
323
324/// Channel used for the most significant sample value in a frame.
325#[derive(Debug, Eq, PartialEq, Clone, Copy)]
326pub enum Align {
327    /// Left-align samples.
328    Left,
329    /// Right-align samples.
330    Right,
331}
332
333impl From<Align> for vals::Align {
334    fn from(variant: Align) -> Self {
335        match variant {
336            Align::Left => vals::Align::LEFT,
337            Align::Right => vals::Align::RIGHT,
338        }
339    }
340}
341
342/// Frame format.
343#[derive(Debug, Eq, PartialEq, Clone, Copy)]
344pub enum Format {
345    /// I2S frame format
346    I2S,
347    /// Aligned frame format
348    Aligned,
349}
350
351impl From<Format> for vals::Format {
352    fn from(variant: Format) -> Self {
353        match variant {
354            Format::I2S => vals::Format::I2S,
355            Format::Aligned => vals::Format::ALIGNED,
356        }
357    }
358}
359
360/// Channels
361#[derive(Debug, Eq, PartialEq, Clone, Copy)]
362pub enum Channels {
363    /// Stereo (2 channels).
364    Stereo,
365    /// Mono, left channel only.
366    MonoLeft,
367    /// Mono, right channel only.
368    MonoRight,
369}
370
371impl From<Channels> for vals::Channels {
372    fn from(variant: Channels) -> Self {
373        vals::Channels::from_bits(variant as u8)
374    }
375}
376
377/// Interrupt handler.
378pub struct InterruptHandler<T: Instance> {
379    _phantom: PhantomData<T>,
380}
381
382impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
383    unsafe fn on_interrupt() {
384        let device = Device::<T>::new();
385        let s = T::state();
386
387        if device.is_tx_ptr_updated() {
388            trace!("TX INT");
389            s.tx_waker.wake();
390            device.disable_tx_ptr_interrupt();
391        }
392
393        if device.is_rx_ptr_updated() {
394            trace!("RX INT");
395            s.rx_waker.wake();
396            device.disable_rx_ptr_interrupt();
397        }
398
399        if device.is_stopped() {
400            trace!("STOPPED INT");
401            s.stop_waker.wake();
402            device.disable_stopped_interrupt();
403        }
404    }
405}
406
407/// I2S driver.
408pub struct I2S<'d, T: Instance> {
409    i2s: Peri<'d, T>,
410    mck: Option<Peri<'d, AnyPin>>,
411    sck: Peri<'d, AnyPin>,
412    lrck: Peri<'d, AnyPin>,
413    sdin: Option<Peri<'d, AnyPin>>,
414    sdout: Option<Peri<'d, AnyPin>>,
415    master_clock: Option<MasterClock>,
416    config: Config,
417}
418
419impl<'d, T: Instance> I2S<'d, T> {
420    /// Create a new I2S in master mode
421    pub fn new_master(
422        i2s: Peri<'d, T>,
423        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
424        mck: Peri<'d, impl GpioPin>,
425        sck: Peri<'d, impl GpioPin>,
426        lrck: Peri<'d, impl GpioPin>,
427        master_clock: MasterClock,
428        config: Config,
429    ) -> Self {
430        Self {
431            i2s,
432            mck: Some(mck.into()),
433            sck: sck.into(),
434            lrck: lrck.into(),
435            sdin: None,
436            sdout: None,
437            master_clock: Some(master_clock),
438            config,
439        }
440    }
441
442    /// Create a new I2S in slave mode
443    pub fn new_slave(
444        i2s: Peri<'d, T>,
445        _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
446        sck: Peri<'d, impl GpioPin>,
447        lrck: Peri<'d, impl GpioPin>,
448        config: Config,
449    ) -> Self {
450        Self {
451            i2s,
452            mck: None,
453            sck: sck.into(),
454            lrck: lrck.into(),
455            sdin: None,
456            sdout: None,
457            master_clock: None,
458            config,
459        }
460    }
461
462    /// I2S output only
463    pub fn output<S: Sample, const NB: usize, const NS: usize>(
464        mut self,
465        sdout: Peri<'d, impl GpioPin>,
466        buffers: MultiBuffering<S, NB, NS>,
467    ) -> OutputStream<'d, T, S, NB, NS> {
468        self.sdout = Some(sdout.into());
469        OutputStream {
470            _p: self.build(),
471            buffers,
472        }
473    }
474
475    /// I2S input only
476    pub fn input<S: Sample, const NB: usize, const NS: usize>(
477        mut self,
478        sdin: Peri<'d, impl GpioPin>,
479        buffers: MultiBuffering<S, NB, NS>,
480    ) -> InputStream<'d, T, S, NB, NS> {
481        self.sdin = Some(sdin.into());
482        InputStream {
483            _p: self.build(),
484            buffers,
485        }
486    }
487
488    /// I2S full duplex (input and output)
489    pub fn full_duplex<S: Sample, const NB: usize, const NS: usize>(
490        mut self,
491        sdin: Peri<'d, impl GpioPin>,
492        sdout: Peri<'d, impl GpioPin>,
493        buffers_out: MultiBuffering<S, NB, NS>,
494        buffers_in: MultiBuffering<S, NB, NS>,
495    ) -> FullDuplexStream<'d, T, S, NB, NS> {
496        self.sdout = Some(sdout.into());
497        self.sdin = Some(sdin.into());
498
499        FullDuplexStream {
500            _p: self.build(),
501            buffers_out,
502            buffers_in,
503        }
504    }
505
506    fn build(self) -> Peri<'d, T> {
507        self.apply_config();
508        self.select_pins();
509        self.setup_interrupt();
510
511        let device = Device::<T>::new();
512        device.enable();
513
514        self.i2s
515    }
516
517    fn apply_config(&self) {
518        let c = T::regs().config();
519        match &self.master_clock {
520            Some(MasterClock { freq, ratio }) => {
521                c.mode().write(|w| w.set_mode(vals::Mode::MASTER));
522                c.mcken().write(|w| w.set_mcken(true));
523                c.mckfreq().write(|w| w.set_mckfreq(freq.to_register_value()));
524                c.ratio().write(|w| w.set_ratio(ratio.to_register_value()));
525            }
526            None => {
527                c.mode().write(|w| w.set_mode(vals::Mode::SLAVE));
528            }
529        };
530
531        c.swidth().write(|w| w.set_swidth(self.config.sample_width.into()));
532        c.align().write(|w| w.set_align(self.config.align.into()));
533        c.format().write(|w| w.set_format(self.config.format.into()));
534        c.channels().write(|w| w.set_channels(self.config.channels.into()));
535    }
536
537    fn select_pins(&self) {
538        let psel = T::regs().psel();
539        psel.mck().write_value(self.mck.psel_bits());
540        psel.sck().write_value(self.sck.psel_bits());
541        psel.lrck().write_value(self.lrck.psel_bits());
542        psel.sdin().write_value(self.sdin.psel_bits());
543        psel.sdout().write_value(self.sdout.psel_bits());
544    }
545
546    fn setup_interrupt(&self) {
547        T::Interrupt::unpend();
548        unsafe { T::Interrupt::enable() };
549
550        let device = Device::<T>::new();
551        device.disable_tx_ptr_interrupt();
552        device.disable_rx_ptr_interrupt();
553        device.disable_stopped_interrupt();
554
555        device.reset_tx_ptr_event();
556        device.reset_rx_ptr_event();
557        device.reset_stopped_event();
558
559        device.enable_tx_ptr_interrupt();
560        device.enable_rx_ptr_interrupt();
561        device.enable_stopped_interrupt();
562    }
563
564    async fn stop() {
565        compiler_fence(Ordering::SeqCst);
566
567        let device = Device::<T>::new();
568        device.stop();
569
570        T::state().started.store(false, Ordering::Relaxed);
571
572        poll_fn(|cx| {
573            T::state().stop_waker.register(cx.waker());
574
575            if device.is_stopped() {
576                trace!("STOP: Ready");
577                device.reset_stopped_event();
578                Poll::Ready(())
579            } else {
580                trace!("STOP: Pending");
581                Poll::Pending
582            }
583        })
584        .await;
585
586        device.disable();
587    }
588
589    async fn send_from_ram<S>(buffer_ptr: *const [S]) -> Result<(), Error>
590    where
591        S: Sample,
592    {
593        trace!("SEND: {}", buffer_ptr as *const S as u32);
594
595        slice_in_ram_or(buffer_ptr, Error::BufferNotInRAM)?;
596
597        compiler_fence(Ordering::SeqCst);
598
599        let device = Device::<T>::new();
600
601        device.update_tx(buffer_ptr)?;
602
603        Self::wait_tx_ptr_update().await;
604
605        compiler_fence(Ordering::SeqCst);
606
607        Ok(())
608    }
609
610    async fn wait_tx_ptr_update() {
611        let drop = OnDrop::new(move || {
612            trace!("TX DROP: Stopping");
613
614            let device = Device::<T>::new();
615            device.disable_tx_ptr_interrupt();
616            device.reset_tx_ptr_event();
617            device.disable_tx();
618
619            // TX is stopped almost instantly, spinning is fine.
620            while !device.is_tx_ptr_updated() {}
621
622            trace!("TX DROP: Stopped");
623        });
624
625        poll_fn(|cx| {
626            T::state().tx_waker.register(cx.waker());
627
628            let device = Device::<T>::new();
629            if device.is_tx_ptr_updated() {
630                trace!("TX POLL: Ready");
631                device.reset_tx_ptr_event();
632                device.enable_tx_ptr_interrupt();
633                Poll::Ready(())
634            } else {
635                trace!("TX POLL: Pending");
636                Poll::Pending
637            }
638        })
639        .await;
640
641        drop.defuse();
642    }
643
644    async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error>
645    where
646        S: Sample,
647    {
648        trace!("RECEIVE: {}", buffer_ptr as *const S as u32);
649
650        // NOTE: RAM slice check for rx is not necessary, as a mutable
651        // slice can only be built from data located in RAM.
652
653        compiler_fence(Ordering::SeqCst);
654
655        let device = Device::<T>::new();
656
657        device.update_rx(buffer_ptr)?;
658
659        Self::wait_rx_ptr_update().await;
660
661        compiler_fence(Ordering::SeqCst);
662
663        Ok(())
664    }
665
666    async fn wait_rx_ptr_update() {
667        let drop = OnDrop::new(move || {
668            trace!("RX DROP: Stopping");
669
670            let device = Device::<T>::new();
671            device.disable_rx_ptr_interrupt();
672            device.reset_rx_ptr_event();
673            device.disable_rx();
674
675            // TX is stopped almost instantly, spinning is fine.
676            while !device.is_rx_ptr_updated() {}
677
678            trace!("RX DROP: Stopped");
679        });
680
681        poll_fn(|cx| {
682            T::state().rx_waker.register(cx.waker());
683
684            let device = Device::<T>::new();
685            if device.is_rx_ptr_updated() {
686                trace!("RX POLL: Ready");
687                device.reset_rx_ptr_event();
688                device.enable_rx_ptr_interrupt();
689                Poll::Ready(())
690            } else {
691                trace!("RX POLL: Pending");
692                Poll::Pending
693            }
694        })
695        .await;
696
697        drop.defuse();
698    }
699}
700
701/// I2S output
702pub struct OutputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
703    _p: Peri<'d, T>,
704    buffers: MultiBuffering<S, NB, NS>,
705}
706
707impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream<'d, T, S, NB, NS> {
708    /// Get a mutable reference to the current buffer.
709    pub fn buffer(&mut self) -> &mut [S] {
710        self.buffers.get_mut()
711    }
712
713    /// Prepare the initial buffer and start the I2S transfer.
714    pub async fn start(&mut self) -> Result<(), Error>
715    where
716        S: Sample,
717    {
718        let device = Device::<T>::new();
719
720        let s = T::state();
721        if s.started.load(Ordering::Relaxed) {
722            self.stop().await;
723        }
724
725        device.enable();
726        device.enable_tx();
727
728        device.update_tx(self.buffers.switch())?;
729
730        s.started.store(true, Ordering::Relaxed);
731
732        device.start();
733
734        I2S::<T>::wait_tx_ptr_update().await;
735
736        Ok(())
737    }
738
739    /// Stops the I2S transfer and waits until it has stopped.
740    #[inline(always)]
741    pub async fn stop(&self) {
742        I2S::<T>::stop().await
743    }
744
745    /// Sends the current buffer for transmission in the DMA.
746    /// Switches to use the next available buffer.
747    pub async fn send(&mut self) -> Result<(), Error>
748    where
749        S: Sample,
750    {
751        I2S::<T>::send_from_ram(self.buffers.switch()).await
752    }
753}
754
755/// I2S input
756pub struct InputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
757    _p: Peri<'d, T>,
758    buffers: MultiBuffering<S, NB, NS>,
759}
760
761impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<'d, T, S, NB, NS> {
762    /// Get a mutable reference to the current buffer.
763    pub fn buffer(&mut self) -> &mut [S] {
764        self.buffers.get_mut()
765    }
766
767    /// Prepare the initial buffer and start the I2S transfer.
768    pub async fn start(&mut self) -> Result<(), Error>
769    where
770        S: Sample,
771    {
772        let device = Device::<T>::new();
773
774        let s = T::state();
775        if s.started.load(Ordering::Relaxed) {
776            self.stop().await;
777        }
778
779        device.enable();
780        device.enable_rx();
781
782        device.update_rx(self.buffers.switch())?;
783
784        s.started.store(true, Ordering::Relaxed);
785
786        device.start();
787
788        I2S::<T>::wait_rx_ptr_update().await;
789
790        Ok(())
791    }
792
793    /// Stops the I2S transfer and waits until it has stopped.
794    #[inline(always)]
795    pub async fn stop(&self) {
796        I2S::<T>::stop().await
797    }
798
799    /// Sets the current buffer for reception from the DMA.
800    /// Switches to use the next available buffer.
801    #[allow(unused_mut)]
802    pub async fn receive(&mut self) -> Result<(), Error>
803    where
804        S: Sample,
805    {
806        I2S::<T>::receive_from_ram(self.buffers.switch_mut()).await
807    }
808}
809
810/// I2S full duplex stream (input & output)
811pub struct FullDuplexStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
812    _p: Peri<'d, T>,
813    buffers_out: MultiBuffering<S, NB, NS>,
814    buffers_in: MultiBuffering<S, NB, NS>,
815}
816
817impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> FullDuplexStream<'d, T, S, NB, NS> {
818    /// Get the current output and input buffers.
819    pub fn buffers(&mut self) -> (&mut [S], &[S]) {
820        (self.buffers_out.get_mut(), self.buffers_in.get())
821    }
822
823    /// Prepare the initial buffers and start the I2S transfer.
824    pub async fn start(&mut self) -> Result<(), Error>
825    where
826        S: Sample,
827    {
828        let device = Device::<T>::new();
829
830        let s = T::state();
831        if s.started.load(Ordering::Relaxed) {
832            self.stop().await;
833        }
834
835        device.enable();
836        device.enable_tx();
837        device.enable_rx();
838
839        device.update_tx(self.buffers_out.switch())?;
840        device.update_rx(self.buffers_in.switch_mut())?;
841
842        s.started.store(true, Ordering::Relaxed);
843
844        device.start();
845
846        I2S::<T>::wait_tx_ptr_update().await;
847        I2S::<T>::wait_rx_ptr_update().await;
848
849        Ok(())
850    }
851
852    /// Stops the I2S transfer and waits until it has stopped.
853    #[inline(always)]
854    pub async fn stop(&self) {
855        I2S::<T>::stop().await
856    }
857
858    /// Sets the current buffers for output and input for transmission/reception from the DMA.
859    /// Switch to use the next available buffers for output/input.
860    pub async fn send_and_receive(&mut self) -> Result<(), Error>
861    where
862        S: Sample,
863    {
864        I2S::<T>::send_from_ram(self.buffers_out.switch()).await?;
865        I2S::<T>::receive_from_ram(self.buffers_in.switch_mut()).await?;
866        Ok(())
867    }
868}
869
870/// Helper encapsulating common I2S device operations.
871struct Device<T>(pac::i2s::I2s, PhantomData<T>);
872
873impl<T: Instance> Device<T> {
874    fn new() -> Self {
875        Self(T::regs(), PhantomData)
876    }
877
878    #[inline(always)]
879    pub fn enable(&self) {
880        trace!("ENABLED");
881        self.0.enable().write(|w| w.set_enable(true));
882    }
883
884    #[inline(always)]
885    pub fn disable(&self) {
886        trace!("DISABLED");
887        self.0.enable().write(|w| w.set_enable(false));
888    }
889
890    #[inline(always)]
891    fn enable_tx(&self) {
892        trace!("TX ENABLED");
893        self.0.config().txen().write(|w| w.set_txen(true));
894    }
895
896    #[inline(always)]
897    fn disable_tx(&self) {
898        trace!("TX DISABLED");
899        self.0.config().txen().write(|w| w.set_txen(false));
900    }
901
902    #[inline(always)]
903    fn enable_rx(&self) {
904        trace!("RX ENABLED");
905        self.0.config().rxen().write(|w| w.set_rxen(true));
906    }
907
908    #[inline(always)]
909    fn disable_rx(&self) {
910        trace!("RX DISABLED");
911        self.0.config().rxen().write(|w| w.set_rxen(false));
912    }
913
914    #[inline(always)]
915    fn start(&self) {
916        trace!("START");
917        self.0.tasks_start().write_value(1);
918    }
919
920    #[inline(always)]
921    fn stop(&self) {
922        self.0.tasks_stop().write_value(1);
923    }
924
925    #[inline(always)]
926    fn is_stopped(&self) -> bool {
927        self.0.events_stopped().read() != 0
928    }
929
930    #[inline(always)]
931    fn reset_stopped_event(&self) {
932        trace!("STOPPED EVENT: Reset");
933        self.0.events_stopped().write_value(0);
934    }
935
936    #[inline(always)]
937    fn disable_stopped_interrupt(&self) {
938        trace!("STOPPED INTERRUPT: Disabled");
939        self.0.intenclr().write(|w| w.set_stopped(true));
940    }
941
942    #[inline(always)]
943    fn enable_stopped_interrupt(&self) {
944        trace!("STOPPED INTERRUPT: Enabled");
945        self.0.intenset().write(|w| w.set_stopped(true));
946    }
947
948    #[inline(always)]
949    fn reset_tx_ptr_event(&self) {
950        trace!("TX PTR EVENT: Reset");
951        self.0.events_txptrupd().write_value(0);
952    }
953
954    #[inline(always)]
955    fn reset_rx_ptr_event(&self) {
956        trace!("RX PTR EVENT: Reset");
957        self.0.events_rxptrupd().write_value(0);
958    }
959
960    #[inline(always)]
961    fn disable_tx_ptr_interrupt(&self) {
962        trace!("TX PTR INTERRUPT: Disabled");
963        self.0.intenclr().write(|w| w.set_txptrupd(true));
964    }
965
966    #[inline(always)]
967    fn disable_rx_ptr_interrupt(&self) {
968        trace!("RX PTR INTERRUPT: Disabled");
969        self.0.intenclr().write(|w| w.set_rxptrupd(true));
970    }
971
972    #[inline(always)]
973    fn enable_tx_ptr_interrupt(&self) {
974        trace!("TX PTR INTERRUPT: Enabled");
975        self.0.intenset().write(|w| w.set_txptrupd(true));
976    }
977
978    #[inline(always)]
979    fn enable_rx_ptr_interrupt(&self) {
980        trace!("RX PTR INTERRUPT: Enabled");
981        self.0.intenset().write(|w| w.set_rxptrupd(true));
982    }
983
984    #[inline(always)]
985    fn is_tx_ptr_updated(&self) -> bool {
986        self.0.events_txptrupd().read() != 0
987    }
988
989    #[inline(always)]
990    fn is_rx_ptr_updated(&self) -> bool {
991        self.0.events_rxptrupd().read() != 0
992    }
993
994    #[inline]
995    fn update_tx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
996        let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
997        self.0.rxtxd().maxcnt().write(|w| w.0 = maxcnt);
998        self.0.txd().ptr().write_value(ptr);
999        Ok(())
1000    }
1001
1002    #[inline]
1003    fn update_rx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
1004        let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
1005        self.0.rxtxd().maxcnt().write(|w| w.0 = maxcnt);
1006        self.0.rxd().ptr().write_value(ptr);
1007        Ok(())
1008    }
1009
1010    fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
1011        let ptr = buffer_ptr as *const S as u32;
1012        let bytes_len = buffer_ptr.len() * size_of::<S>();
1013        let maxcnt = (bytes_len / size_of::<u32>()) as u32;
1014
1015        trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
1016
1017        if ptr % 4 != 0 {
1018            Err(Error::BufferMisaligned)
1019        } else if bytes_len % 4 != 0 {
1020            Err(Error::BufferLengthMisaligned)
1021        } else if maxcnt as usize > EASY_DMA_SIZE {
1022            Err(Error::BufferTooLong)
1023        } else {
1024            Ok((ptr, maxcnt))
1025        }
1026    }
1027}
1028
1029/// Sample details
1030pub trait Sample: Sized + Copy + Default {
1031    /// Width of this sample type.
1032    const WIDTH: usize;
1033
1034    /// Scale of this sample.
1035    const SCALE: Self;
1036}
1037
1038impl Sample for i8 {
1039    const WIDTH: usize = 8;
1040    const SCALE: Self = 1 << (Self::WIDTH - 1);
1041}
1042
1043impl Sample for i16 {
1044    const WIDTH: usize = 16;
1045    const SCALE: Self = 1 << (Self::WIDTH - 1);
1046}
1047
1048impl Sample for i32 {
1049    const WIDTH: usize = 24;
1050    const SCALE: Self = 1 << (Self::WIDTH - 1);
1051}
1052
1053/// A 4-bytes aligned buffer. Needed for DMA access.
1054#[derive(Clone, Copy)]
1055#[repr(align(4))]
1056pub struct AlignedBuffer<T: Sample, const N: usize>([T; N]);
1057
1058impl<T: Sample, const N: usize> AlignedBuffer<T, N> {
1059    /// Create a new `AlignedBuffer`.
1060    pub fn new(array: [T; N]) -> Self {
1061        Self(array)
1062    }
1063}
1064
1065impl<T: Sample, const N: usize> Default for AlignedBuffer<T, N> {
1066    fn default() -> Self {
1067        Self([T::default(); N])
1068    }
1069}
1070
1071impl<T: Sample, const N: usize> Deref for AlignedBuffer<T, N> {
1072    type Target = [T];
1073    fn deref(&self) -> &Self::Target {
1074        self.0.as_slice()
1075    }
1076}
1077
1078impl<T: Sample, const N: usize> DerefMut for AlignedBuffer<T, N> {
1079    fn deref_mut(&mut self) -> &mut Self::Target {
1080        self.0.as_mut_slice()
1081    }
1082}
1083
1084/// Set of multiple buffers, for multi-buffering transfers.
1085pub struct MultiBuffering<S: Sample, const NB: usize, const NS: usize> {
1086    buffers: [AlignedBuffer<S, NS>; NB],
1087    index: usize,
1088}
1089
1090impl<S: Sample, const NB: usize, const NS: usize> MultiBuffering<S, NB, NS> {
1091    /// Create a new `MultiBuffering`.
1092    pub fn new() -> Self {
1093        assert!(NB > 1);
1094        Self {
1095            buffers: [AlignedBuffer::<S, NS>::default(); NB],
1096            index: 0,
1097        }
1098    }
1099
1100    fn get(&self) -> &[S] {
1101        &self.buffers[self.index]
1102    }
1103
1104    fn get_mut(&mut self) -> &mut [S] {
1105        &mut self.buffers[self.index]
1106    }
1107
1108    /// Advance to use the next buffer and return a non mutable pointer to the previous one.
1109    fn switch(&mut self) -> *const [S] {
1110        let prev_index = self.index;
1111        self.index = (self.index + 1) % NB;
1112        self.buffers[prev_index].deref() as *const [S]
1113    }
1114
1115    /// Advance to use the next buffer and return a mutable pointer to the previous one.
1116    fn switch_mut(&mut self) -> *mut [S] {
1117        let prev_index = self.index;
1118        self.index = (self.index + 1) % NB;
1119        self.buffers[prev_index].deref_mut() as *mut [S]
1120    }
1121}
1122
1123/// Peripheral static state
1124pub(crate) struct State {
1125    started: AtomicBool,
1126    rx_waker: AtomicWaker,
1127    tx_waker: AtomicWaker,
1128    stop_waker: AtomicWaker,
1129}
1130
1131impl State {
1132    pub(crate) const fn new() -> Self {
1133        Self {
1134            started: AtomicBool::new(false),
1135            rx_waker: AtomicWaker::new(),
1136            tx_waker: AtomicWaker::new(),
1137            stop_waker: AtomicWaker::new(),
1138        }
1139    }
1140}
1141
1142pub(crate) trait SealedInstance {
1143    fn regs() -> pac::i2s::I2s;
1144    fn state() -> &'static State;
1145}
1146
1147/// I2S peripheral instance.
1148#[allow(private_bounds)]
1149pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
1150    /// Interrupt for this peripheral.
1151    type Interrupt: interrupt::typelevel::Interrupt;
1152}
1153
1154macro_rules! impl_i2s {
1155    ($type:ident, $pac_type:ident, $irq:ident) => {
1156        impl crate::i2s::SealedInstance for peripherals::$type {
1157            fn regs() -> pac::i2s::I2s {
1158                pac::$pac_type
1159            }
1160            fn state() -> &'static crate::i2s::State {
1161                static STATE: crate::i2s::State = crate::i2s::State::new();
1162                &STATE
1163            }
1164        }
1165        impl crate::i2s::Instance for peripherals::$type {
1166            type Interrupt = crate::interrupt::typelevel::$irq;
1167        }
1168    };
1169}