1use crate::iomuxc::{consts, sai};
32use crate::ral;
33
34#[derive(Clone, Copy, Default, Eq, PartialEq)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub enum ByteOrder {
38 #[default]
40 LSB = 0,
41 MSB = 1,
43}
44
45#[derive(Clone, Copy, Default, Eq, PartialEq)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub enum Mode {
49 #[default]
51 Master = 0,
52 Slave = 1,
54 BclkMasterFrameSyncSlave = 2,
56 BclkSlaveFrameSyncMaster = 3,
58}
59
60#[derive(Clone, Copy, Default, Eq, PartialEq)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub enum ClockPolarity {
64 #[default]
66 ActiveHigh = 0,
67 ActiveLow = 1,
69}
70
71#[allow(non_upper_case_globals)]
72impl ClockPolarity {
73 pub const SampleOnRising: ClockPolarity = ClockPolarity::ActiveLow;
75 pub const SampleOnFalling: ClockPolarity = ClockPolarity::ActiveHigh;
77}
78
79#[derive(Clone, Copy, Default, Eq, PartialEq)]
81#[cfg_attr(feature = "defmt", derive(defmt::Format))]
82pub enum MclkSource {
83 #[default]
85 Sysclk = 0,
86 Select1 = 1,
88 Select2 = 2,
90 Select3 = 3,
92}
93
94#[derive(Clone, Copy, Default, Eq, PartialEq)]
96#[cfg_attr(feature = "defmt", derive(defmt::Format))]
97pub enum SyncMode {
98 #[default]
100 Async = 0,
101 TxFollowRx = 1,
103 RxFollowTx = 2,
105}
106
107#[derive(Clone, Copy, Default, Eq, PartialEq)]
109#[cfg_attr(feature = "defmt", derive(defmt::Format))]
110pub enum SyncWidth {
111 #[default]
113 WordSize,
114}
115
116#[derive(Clone, Copy, Default, Eq, PartialEq)]
118#[cfg_attr(feature = "defmt", derive(defmt::Format))]
119pub enum BclkSource {
120 #[default]
122 Bus = 0,
123 Opt1 = 1,
125 Opt2 = 2,
127 Opt3 = 3,
129}
130
131bitflags::bitflags! {
132 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
136 pub struct Interrupts : u32 {
137 const WORD_START = 1 << 12;
139 const SYNC_ERROR = 1 << 11;
141 const FIFO_ERROR = 1 << 10;
143 const FIFO_WARNING = 1 << 9;
145 const FIFO_REQUEST = 1 << 8;
147 }
148}
149
150bitflags::bitflags! {
151 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
153 pub struct Status : u32 {
154 const WORD_START = 1 << 20;
158 const SYNC_ERROR = 1 << 19;
162 const FIFO_ERROR = 1 << 18;
168 const FIFO_WARNING = 1 << 17;
174 const FIFO_REQUEST = 1 << 16;
180 }
181}
182
183impl Status {
184 const W1C: Self = Self::from_bits_truncate(
185 Self::WORD_START.bits() | Self::SYNC_ERROR.bits() | Self::FIFO_ERROR.bits(),
186 );
187}
188
189#[derive(Clone, Copy, Default, Debug, Eq, PartialEq)]
194#[cfg_attr(feature = "defmt", derive(defmt::Format))]
195#[repr(u32)]
196pub enum Packing {
197 #[default]
201 None = 0b00,
202 Pack8bit = 0b10,
207 Pack16bit = 0b11,
212}
213
214impl Packing {
215 const fn is_valid_for_word_size(self, word_size: u8) -> bool {
216 match self {
217 Self::None => true,
218 Self::Pack8bit => word_size == 8,
219 Self::Pack16bit => word_size == 16,
220 }
221 }
222}
223
224#[derive(Debug, Clone, Copy, Eq, PartialEq)]
229#[cfg_attr(feature = "defmt", derive(defmt::Format))]
230pub struct InvalidPackingError {
231 pub word_size: u8,
233 pub packing: Packing,
235}
236
237#[allow(non_upper_case_globals)]
238impl BclkSource {
239 pub const MclkDiv: BclkSource = BclkSource::Opt1;
241}
242
243fn reset_tx(regs: &ral::sai::RegisterBlock) {
244 ral::write_reg!(ral::sai, regs, TCSR, SR: 1, FR: 1);
245 ral::modify_reg!(ral::sai, regs, TCSR, SR: 0);
246}
247
248fn reset_rx(regs: &ral::sai::RegisterBlock) {
249 ral::write_reg!(ral::sai, regs, RCSR, SR: 1, FR: 1);
250 ral::modify_reg!(ral::sai, regs, RCSR, SR: 0);
251}
252
253fn reset(regs: &ral::sai::RegisterBlock) {
254 reset_tx(regs);
255 reset_rx(regs);
256}
257
258pub struct Pins<Sync, Bclk, Data> {
262 pub sync: Sync,
264 pub bclk: Bclk,
266 pub data: Data,
268}
269
270#[derive(Default)]
272#[cfg_attr(feature = "defmt", derive(defmt::Format))]
273pub struct SaiConfig {
274 pub mclk_source: MclkSource,
276 pub tx_fifo_wm: u32,
278 pub tx_stop_en: bool,
280 pub tx_debug_en: bool,
282 pub tx_bclk_div: u32,
284 pub rx_fifo_wm: u32,
286 pub rx_stop_en: bool,
288 pub rx_debug_en: bool,
290 pub rx_bclk_div: u32,
292 pub byte_order: ByteOrder,
294 pub mode: Mode,
296 pub sync_width: SyncWidth,
298 pub sync_early: bool,
300 pub sync_polarity: ClockPolarity,
302 pub sync_mode: SyncMode,
304 pub bclk_src_swap: bool,
306 pub bclk_input_delay: bool,
308 pub bclk_polarity: ClockPolarity,
310}
311
312const MIN_BCLK_DIV: u32 = 2;
313const MAX_BCLK_DIV: u32 = 512;
314
315pub fn bclk_div(bclk_div: u32) -> u32 {
317 bclk_div.clamp(MIN_BCLK_DIV, MAX_BCLK_DIV).div_ceil(2) - 1
318}
319
320impl SaiConfig {
321 pub const fn i2s(bclk_div: u32) -> Self {
323 Self {
326 mclk_source: MclkSource::Sysclk,
327 tx_fifo_wm: 16,
328 tx_stop_en: false,
329 tx_debug_en: false,
330 tx_bclk_div: bclk_div,
331 rx_fifo_wm: 16,
332 rx_stop_en: false,
333 rx_debug_en: false,
334 rx_bclk_div: bclk_div,
335 byte_order: ByteOrder::MSB,
336 mode: Mode::Master,
337 sync_early: true,
338 sync_width: SyncWidth::WordSize,
339 sync_polarity: ClockPolarity::ActiveLow,
340 sync_mode: SyncMode::Async,
341 bclk_src_swap: false,
342 bclk_input_delay: false,
343 bclk_polarity: ClockPolarity::SampleOnRising,
344 }
345 }
346}
347
348type AnyInstance = crate::AnyInstance<ral::sai::RegisterBlock>;
349
350pub struct Sai {
352 sai: AnyInstance,
353 tx_chan_mask: u32,
354 rx_chan_mask: u32,
355}
356
357impl Sai {
358 pub fn new<const N: u8, Chan, Mclk, TxSync, TxBclk, TxData, RxSync, RxBclk, RxData>(
360 sai: ral::sai::Instance<N>,
361 mut mclk_pin: Mclk,
362 mut tx_pins: Pins<TxSync, TxBclk, TxData>,
363 mut rx_pins: Pins<RxSync, RxBclk, RxData>,
364 ) -> Self
365 where
366 Mclk: sai::Pin<consts::Const<N>, Signal = sai::Mclk>,
367 TxSync: sai::Pin<consts::Const<N>, Signal = sai::TxSync>,
368 TxBclk: sai::Pin<consts::Const<N>, Signal = sai::TxBclk>,
369 TxData: sai::Pin<consts::Const<N>>,
370 RxSync: sai::Pin<consts::Const<N>, Signal = sai::RxSync>,
371 RxBclk: sai::Pin<consts::Const<N>, Signal = sai::RxBclk>,
372 RxData: sai::Pin<consts::Const<N>>,
373 Chan: consts::Unsigned,
374 <TxData as sai::Pin<consts::Const<N>>>::Signal: sai::TxDataSignal<Index = Chan>,
375 <RxData as sai::Pin<consts::Const<N>>>::Signal: sai::RxDataSignal<Index = Chan>,
376 {
377 reset(&sai);
378
379 sai::prepare(&mut mclk_pin);
380 sai::prepare(&mut tx_pins.sync);
381 sai::prepare(&mut tx_pins.bclk);
382 sai::prepare(&mut tx_pins.data);
383 sai::prepare(&mut rx_pins.sync);
384 sai::prepare(&mut rx_pins.bclk);
385 sai::prepare(&mut rx_pins.data);
386
387 Self {
388 sai: crate::into_any(sai),
389 tx_chan_mask: 1 << Chan::to_usize(),
390 rx_chan_mask: 1 << Chan::to_usize(),
391 }
392 }
393}
394
395pub struct Tx {
397 pub(crate) sai: AnyInstance,
398 word_size: u8,
399 frame_size: usize,
400 channel: usize,
401}
402
403impl Tx {
404 pub fn word_size(&self) -> u8 {
406 self.word_size
407 }
408
409 pub fn frame_size(&self) -> usize {
411 self.frame_size
412 }
413
414 pub fn set_enable(&mut self, en: bool) {
416 let mut tcsr = ral::read_reg!(ral::sai, self.sai, TCSR) & !Status::W1C.bits();
417 if en {
418 tcsr |= ral::sai::TCSR::TE::mask
419 } else {
420 tcsr &= !ral::sai::TCSR::TE::mask
421 }
422 ral::write_reg!(ral::sai, self.sai, TCSR, tcsr);
423 self.clear_status(Status::W1C);
424 }
425
426 pub fn interrupts(&self) -> Interrupts {
430 let tcsr = ral::read_reg!(ral::sai, self.sai, TCSR);
431 Interrupts::from_bits_truncate(tcsr)
432 }
433
434 pub fn set_interrupts(&mut self, interrupts: Interrupts) {
436 ral::modify_reg!(ral::sai, self.sai, TCSR, |tcsr| {
437 let tcsr = tcsr & !Interrupts::all().bits();
438 tcsr | interrupts.bits()
439 })
440 }
441
442 pub fn status(&mut self) -> Status {
445 let tcsr = ral::read_reg!(ral::sai, self.sai, TCSR);
446 Status::from_bits_truncate(tcsr)
447 }
448
449 pub fn clear_status(&mut self, flags: Status) {
451 let flags = flags & Status::W1C;
452 ral::modify_reg!(ral::sai, self.sai, TCSR, |tcsr| { tcsr | flags.bits() });
453 }
454
455 pub fn reg_dump(&mut self) -> [u32; 6] {
457 [
458 ral::read_reg!(ral::sai, self.sai, TCR1),
459 ral::read_reg!(ral::sai, self.sai, TCR2),
460 ral::read_reg!(ral::sai, self.sai, TCR3),
461 ral::read_reg!(ral::sai, self.sai, TCR4),
462 ral::read_reg!(ral::sai, self.sai, TCR5),
463 ral::read_reg!(ral::sai, self.sai, TCSR),
464 ]
465 }
466
467 pub fn fifo_position(&mut self, chan: usize) -> (u32, u32) {
478 ral::read_reg!(ral::sai, self.sai, TFR[chan], WFP, RFP)
479 }
480
481 pub fn channel(&self) -> usize {
483 self.channel
484 }
485
486 pub fn tdr(&self, chan: usize) -> *const u32 {
490 core::ptr::addr_of!(self.sai.TDR[chan]).cast()
491 }
492
493 pub fn enable_dma_transmit(&mut self) {
498 ral::modify_reg!(ral::sai, self.sai, TCSR, |tcsr| {
499 (tcsr & !Status::W1C.bits()) | ral::sai::TCSR::FWDE::mask
500 });
501 }
502
503 pub fn disable_dma_transmit(&mut self) {
505 ral::modify_reg!(ral::sai, self.sai, TCSR, |tcsr| {
506 (tcsr & !Status::W1C.bits()) & !ral::sai::TCSR::FWDE::mask
507 });
508 }
509
510 pub fn write_frame_u32(&mut self, chan: usize, frame: &[u32]) {
518 for &sample in frame {
519 ral::write_reg!(ral::sai, self.sai, TDR[chan], sample);
520 }
521 }
522
523 pub fn write_frame_u16(&mut self, chan: usize, frame: &[u16]) {
531 for &sample in frame {
532 ral::write_reg!(ral::sai, self.sai, TDR[chan], sample as u32);
533 }
534 }
535
536 pub fn write_frame_u8(&mut self, chan: usize, frame: &[u8]) {
544 for &sample in frame {
545 ral::write_reg!(ral::sai, self.sai, TDR[chan], sample as u32);
546 }
547 }
548}
549
550pub struct Rx {
552 pub(crate) sai: AnyInstance,
553 word_size: u8,
554 frame_size: usize,
555 channel: usize,
556}
557
558impl Rx {
559 pub fn word_size(&self) -> u8 {
561 self.word_size
562 }
563
564 pub fn frame_size(&self) -> usize {
566 self.frame_size
567 }
568
569 pub fn set_enable(&mut self, en: bool) {
571 let mut rcsr = ral::read_reg!(ral::sai, self.sai, RCSR) & !Status::W1C.bits();
572 if en {
573 rcsr |= ral::sai::RCSR::RE::mask
574 } else {
575 rcsr &= !ral::sai::RCSR::RE::mask
576 }
577 ral::write_reg!(ral::sai, self.sai, RCSR, rcsr);
578 self.clear_status(Status::W1C);
579 }
580
581 pub fn interrupts(&self) -> Interrupts {
585 let rcsr = ral::read_reg!(ral::sai, self.sai, RCSR);
586 Interrupts::from_bits_truncate(rcsr)
587 }
588
589 pub fn set_interrupts(&mut self, interrupts: Interrupts) {
591 ral::modify_reg!(ral::sai, self.sai, RCSR, |rcsr| {
592 let rcsr = rcsr & !Interrupts::all().bits();
593 rcsr | interrupts.bits()
594 })
595 }
596
597 pub fn status(&mut self) -> Status {
600 let rcsr = ral::read_reg!(ral::sai, self.sai, RCSR);
601 Status::from_bits_truncate(rcsr)
602 }
603
604 pub fn clear_status(&mut self, flags: Status) {
606 let flags = flags & Status::W1C;
607 ral::modify_reg!(ral::sai, self.sai, RCSR, |rcsr| { rcsr | flags.bits() });
608 }
609
610 pub fn reg_dump(&mut self) -> [u32; 6] {
612 [
613 ral::read_reg!(ral::sai, self.sai, RCR1),
614 ral::read_reg!(ral::sai, self.sai, RCR2),
615 ral::read_reg!(ral::sai, self.sai, RCR3),
616 ral::read_reg!(ral::sai, self.sai, RCR4),
617 ral::read_reg!(ral::sai, self.sai, RCR5),
618 ral::read_reg!(ral::sai, self.sai, RCSR),
619 ]
620 }
621
622 pub fn fifo_position(&mut self, chan: usize) -> (u32, u32) {
633 ral::read_reg!(ral::sai, self.sai, RFR[chan], WFP, RFP)
634 }
635
636 pub fn channel(&self) -> usize {
638 self.channel
639 }
640
641 pub fn rdr(&self, chan: usize) -> *const u32 {
645 core::ptr::addr_of!(self.sai.RDR[chan]).cast()
646 }
647
648 pub fn enable_dma_receive(&mut self) {
653 ral::modify_reg!(ral::sai, self.sai, RCSR, |rcsr| {
654 (rcsr & !Status::W1C.bits()) | ral::sai::RCSR::FRDE::mask
655 });
656 }
657
658 pub fn disable_dma_receive(&mut self) {
660 ral::modify_reg!(ral::sai, self.sai, RCSR, |rcsr| {
661 (rcsr & !Status::W1C.bits()) & !ral::sai::RCSR::FRDE::mask
662 });
663 }
664
665 pub fn read_frame_u32(&mut self, chan: usize, frame: &mut [u32]) {
673 for sample in frame {
674 *sample = ral::read_reg!(ral::sai, self.sai, RDR[chan]);
675 }
676 }
677
678 pub fn read_frame_u16(&mut self, chan: usize, frame: &mut [u16]) {
686 for sample in frame {
687 *sample = ral::read_reg!(ral::sai, self.sai, RDR[chan]) as u16;
688 }
689 }
690
691 pub fn read_frame_u8(&mut self, chan: usize, frame: &mut [u8]) {
699 for sample in frame {
700 *sample = ral::read_reg!(ral::sai, self.sai, RDR[chan]) as u8;
701 }
702 }
703}
704
705impl Sai {
706 pub fn from_tx<const N: u8, Chan, Mclk, TxSync, TxBclk, TxData>(
708 sai: ral::sai::Instance<N>,
709 mut mclk_pin: Mclk,
710 mut tx_pins: Pins<TxSync, TxBclk, TxData>,
711 ) -> Self
712 where
713 Mclk: sai::Pin<consts::Const<N>, Signal = sai::Mclk>,
714 TxSync: sai::Pin<consts::Const<N>, Signal = sai::TxSync>,
715 TxBclk: sai::Pin<consts::Const<N>, Signal = sai::TxBclk>,
716 TxData: sai::Pin<consts::Const<N>>,
717 Chan: consts::Unsigned,
718 <TxData as sai::Pin<consts::Const<N>>>::Signal: sai::TxDataSignal<Index = Chan>,
719 {
720 reset(&sai);
721
722 sai::prepare(&mut mclk_pin);
723 sai::prepare(&mut tx_pins.sync);
724 sai::prepare(&mut tx_pins.bclk);
725 sai::prepare(&mut tx_pins.data);
726
727 Sai {
728 sai: crate::into_any(sai),
729 tx_chan_mask: 1 << Chan::to_usize(),
730 rx_chan_mask: 0,
731 }
732 }
733
734 pub fn from_rx<const N: u8, Chan, Mclk, RxSync, RxBclk, RxData>(
736 sai: ral::sai::Instance<N>,
737 mut mclk_pin: Mclk,
738 mut rx_pins: Pins<RxSync, RxBclk, RxData>,
739 ) -> Self
740 where
741 Mclk: sai::Pin<consts::Const<N>, Signal = sai::Mclk>,
742 RxSync: sai::Pin<consts::Const<N>, Signal = sai::RxSync>,
743 RxBclk: sai::Pin<consts::Const<N>, Signal = sai::RxBclk>,
744 RxData: sai::Pin<consts::Const<N>>,
745 Chan: consts::Unsigned,
746 <RxData as sai::Pin<consts::Const<N>>>::Signal: sai::RxDataSignal<Index = Chan>,
747 {
748 reset(&sai);
749
750 sai::prepare(&mut mclk_pin);
751 sai::prepare(&mut rx_pins.sync);
752 sai::prepare(&mut rx_pins.bclk);
753 sai::prepare(&mut rx_pins.data);
754
755 Sai {
756 sai: crate::into_any(sai),
757 tx_chan_mask: 0,
758 rx_chan_mask: 1 << Chan::to_usize(),
759 }
760 }
761
762 pub fn without_pins<const N: u8>(
768 sai: ral::sai::Instance<N>,
769 tx_chan_mask: u32,
770 rx_chan_mask: u32,
771 ) -> Self {
772 Sai {
773 sai: crate::into_any(sai),
774 tx_chan_mask,
775 rx_chan_mask,
776 }
777 }
778
779 pub fn split(
788 self,
789 word_size: u8,
790 frame_size: usize,
791 packing: Packing,
792 cfg: &SaiConfig,
793 ) -> Result<(Option<Tx>, Option<Rx>), InvalidPackingError> {
794 if !packing.is_valid_for_word_size(word_size) {
795 return Err(InvalidPackingError { word_size, packing });
796 }
797 let tx_channel = self.tx_chan_mask.trailing_zeros() as usize;
798 let rx_channel = self.rx_chan_mask.trailing_zeros() as usize;
799
800 let tx = (self.tx_chan_mask != 0).then(|| Tx {
801 sai: unsafe { AnyInstance::new(&*self.sai) },
804 word_size,
805 frame_size,
806 channel: tx_channel,
807 });
808 let rx = (self.rx_chan_mask != 0).then(|| Rx {
809 sai: unsafe { AnyInstance::new(&*self.sai) },
812 word_size,
813 frame_size,
814 channel: rx_channel,
815 });
816
817 let frame_sync_dir = match cfg.mode {
818 Mode::Master => 1,
819 Mode::BclkSlaveFrameSyncMaster => 1,
820 _ => 0,
821 };
822
823 let bclk_dir = match cfg.mode {
824 Mode::Master => 1,
825 Mode::BclkMasterFrameSyncSlave => 1,
826 _ => 0,
827 };
828
829 let (tx_sync_mode, rx_sync_mode) = match cfg.sync_mode {
830 SyncMode::Async => (0b00, 0b00),
831 SyncMode::TxFollowRx => (0b01, 0b00),
832 SyncMode::RxFollowTx => (0b00, 0b01),
833 };
834
835 let sync_width = match cfg.sync_width {
836 SyncWidth::WordSize => word_size as u32,
837 };
838
839 if tx.is_some() {
840 ral::write_reg!(ral::sai, self.sai, TCR1, TFW: cfg.tx_fifo_wm);
841 if cfg.mode == Mode::Master || cfg.mode == Mode::BclkMasterFrameSyncSlave {
842 ral::write_reg!(ral::sai, self.sai, TCR2, SYNC: tx_sync_mode,
843 BCS: cfg.bclk_src_swap as u32, BCI: cfg.bclk_input_delay as u32,
844 MSEL: 0x11_u32, BCP: cfg.bclk_polarity as u32, BCD: bclk_dir,
845 DIV: cfg.tx_bclk_div);
846 } else {
847 ral::modify_reg!(ral::sai, self.sai, TCR2, BCP: cfg.bclk_polarity as u32);
848 }
849 ral::modify_reg!(ral::sai, self.sai, TCR3, TCE: self.tx_chan_mask, WDFL: 0_u32);
850 ral::write_reg!(ral::sai, self.sai, TCR4, FRSZ: ((frame_size - 1) as u32),
851 FPACK: packing as u32, SYWD: (sync_width - 1), MF: cfg.byte_order as u32,
852 FSE: cfg.sync_early as u32, FSP: cfg.sync_polarity as u32, FSD: frame_sync_dir);
853 ral::write_reg!(ral::sai, self.sai, TCR5, W0W: ((word_size - 1) as u32), WNW: ((word_size - 1) as u32), FBT: (word_size - 1) as u32);
854 ral::write_reg!(ral::sai, self.sai, TCSR, TE: 0, STOPE: cfg.tx_stop_en as u32,
855 DBGE: cfg.tx_debug_en as u32, BCE: 1, WSF: 1, SEF: 1, FEF: 1, FWF: 0, FRF: 0,
856 WSIE: 0, SEIE: 0, FEIE: 0, FWIE: 0, FWDE: 0, FRDE: 0);
857 }
858
859 if rx.is_some() {
860 ral::write_reg!(ral::sai, self.sai, RCR1, RFW: cfg.rx_fifo_wm);
861 if cfg.mode == Mode::Master || cfg.mode == Mode::BclkMasterFrameSyncSlave {
862 ral::write_reg!(ral::sai, self.sai, RCR2, SYNC: rx_sync_mode,
863 BCS: cfg.bclk_src_swap as u32, BCI: cfg.bclk_input_delay as u32,
864 MSEL: cfg.mclk_source as u32, BCP: cfg.bclk_polarity as u32, BCD: bclk_dir,
865 DIV: cfg.rx_bclk_div);
866 } else {
867 ral::modify_reg!(ral::sai, self.sai, RCR2, BCP: cfg.bclk_polarity as u32);
868 }
869 ral::modify_reg!(ral::sai, self.sai, RCR3, RCE: self.rx_chan_mask);
870 ral::write_reg!(ral::sai, self.sai, RCR4, FRSZ: ((frame_size - 1) as u32),
871 FPACK: packing as u32, SYWD: (sync_width - 1), MF: cfg.byte_order as u32,
872 FSE: cfg.sync_early as u32, FSP: cfg.sync_polarity as u32, FSD: frame_sync_dir);
873 ral::write_reg!(ral::sai, self.sai, RCR5, W0W: ((word_size - 1) as u32), WNW: ((word_size - 1) as u32), FBT: (word_size - 1) as u32);
874 ral::write_reg!(ral::sai, self.sai, RCSR, RE: 0, STOPE: cfg.rx_stop_en as u32,
875 DBGE: cfg.rx_debug_en as u32, BCE: 1, WSF: 1, SEF: 1, FEF: 1, FWF: 0, FRF: 0,
876 WSIE: 0, SEIE: 0, FEIE: 0, FWIE: 0, FWDE: 0, FRDE: 0);
877 }
878
879 Ok((tx, rx))
880 }
881}