1use super::*;
3use crate::gpio::*;
4
5use esp_idf_sys::*;
6
7pub(super) mod config {
8 #[allow(unused)]
9 use crate::{gpio::*, i2s::config::*};
10 use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
11 use esp_idf_sys::*;
12
13 pub const TDM_AUTO_SLOT_NUM: u32 = 0;
15
16 pub const TDM_AUTO_WS_WIDTH: u32 = 0;
18
19 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
21 pub struct TdmConfig {
22 pub(super) channel_cfg: Config,
24
25 clk_cfg: TdmClkConfig,
27
28 slot_cfg: TdmSlotConfig,
30
31 #[cfg(not(esp_idf_version_major = "4"))]
33 gpio_cfg: TdmGpioConfig,
34 }
35
36 impl TdmConfig {
37 #[inline(always)]
40 pub fn new(
41 channel_cfg: Config,
42 clk_cfg: TdmClkConfig,
43 slot_cfg: TdmSlotConfig,
44 #[cfg(not(esp_idf_version_major = "4"))] gpio_cfg: TdmGpioConfig,
45 ) -> Self {
46 Self {
47 channel_cfg,
48 clk_cfg,
49 slot_cfg,
50 #[cfg(not(esp_idf_version_major = "4"))]
51 gpio_cfg,
52 }
53 }
54
55 #[cfg(all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm))]
58 #[inline(always)]
59 pub(crate) fn clk_cfg_as_sdk(&self) -> i2s_tdm_clk_config_t {
60 self.clk_cfg.as_sdk()
61 }
62
63 #[cfg(all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm))]
66 #[inline(always)]
67 pub(crate) fn slot_cfg_as_sdk(&self) -> i2s_tdm_slot_config_t {
68 self.slot_cfg.as_sdk()
69 }
70
71 #[cfg(not(esp_idf_version_major = "4"))]
73 #[inline(always)]
74 pub(super) fn as_sdk<'d>(
75 &self,
76 bclk: impl InputPin + OutputPin + 'd,
77 din: Option<impl InputPin + 'd>,
78 dout: Option<impl OutputPin + 'd>,
79 mclk: Option<impl InputPin + OutputPin + 'd>,
80 ws: impl InputPin + OutputPin + 'd,
81 ) -> i2s_tdm_config_t {
82 i2s_tdm_config_t {
83 clk_cfg: self.clk_cfg.as_sdk(),
84 slot_cfg: self.slot_cfg.as_sdk(),
85 gpio_cfg: self.gpio_cfg.as_sdk(bclk, din, dout, mclk, ws),
86 }
87 }
88
89 #[cfg(esp_idf_version_major = "4")]
96 pub(crate) fn as_sdk(&self) -> i2s_driver_config_t {
97 i2s_driver_config_t {
98 mode: self.channel_cfg.role.as_sdk(),
99 sample_rate: self.clk_cfg.sample_rate_hz,
100 bits_per_sample: self.slot_cfg.data_bit_width.as_sdk(),
101 channel_format: i2s_channel_fmt_t_I2S_CHANNEL_FMT_MULTIPLE, communication_format: self.slot_cfg.comm_fmt.as_sdk(),
103 intr_alloc_flags: 1 << 1, dma_buf_count: self.channel_cfg.dma_buffer_count as i32,
105 dma_buf_len: self.channel_cfg.frames_per_buffer as i32,
106 #[cfg(any(esp32, esp32s2))]
107 use_apll: matches!(self.clk_cfg.clk_src, ClockSource::Apll),
108 #[cfg(not(any(esp32, esp32s2)))]
109 use_apll: false,
110 tx_desc_auto_clear: self.channel_cfg.auto_clear,
111 fixed_mclk: 0,
112 mclk_multiple: self.clk_cfg.mclk_multiple.as_sdk(),
113 bits_per_chan: self.slot_cfg.slot_bit_width.as_sdk(),
114 chan_mask: self.slot_cfg.slot_mask.as_sdk(),
115 total_chan: self.slot_cfg.slot_mask.0.count_ones(),
116 left_align: self.slot_cfg.left_align,
117 big_edin: self.slot_cfg.big_endian,
118 bit_order_msb: !self.slot_cfg.bit_order_lsb,
119 skip_msk: self.slot_cfg.skip_mask,
120 }
121 }
122 }
123
124 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
126 pub struct TdmClkConfig {
127 sample_rate_hz: u32,
129
130 clk_src: ClockSource,
132
133 mclk_multiple: MclkMultiple,
135
136 #[cfg(esp_idf_version_at_least_5_1_0)]
139 bclk_div: u32,
140 }
141
142 pub const TDM_BCLK_DIV_MIN: u32 = 8;
144
145 impl TdmClkConfig {
146 #[cfg(not(esp_idf_version_at_least_5_1_0))]
149 #[inline(always)]
150 pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
151 Self {
152 sample_rate_hz,
153 clk_src,
154 mclk_multiple,
155 }
156 }
157
158 #[cfg(esp_idf_version_at_least_5_1_0)]
161 #[inline(always)]
162 pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
163 Self {
164 sample_rate_hz,
165 clk_src,
166 mclk_multiple,
167 bclk_div: TDM_BCLK_DIV_MIN,
168 }
169 }
170
171 #[cfg(not(esp_idf_version_at_least_5_1_0))]
178 #[inline(always)]
179 pub fn from_sample_rate_hz(rate: u32) -> Self {
180 Self {
181 sample_rate_hz: rate,
182 clk_src: ClockSource::default(),
183 mclk_multiple: MclkMultiple::M256,
184 }
185 }
186
187 #[cfg(esp_idf_version_at_least_5_1_0)]
194 #[inline(always)]
195 pub fn from_sample_rate_hz(rate: u32) -> Self {
196 Self {
197 sample_rate_hz: rate,
198 clk_src: ClockSource::default(),
199 mclk_multiple: MclkMultiple::M256,
200 bclk_div: TDM_BCLK_DIV_MIN,
201 }
202 }
203
204 #[inline(always)]
206 pub fn clk_src(mut self, clk_src: ClockSource) -> Self {
207 self.clk_src = clk_src;
208 self
209 }
210
211 #[inline(always)]
213 pub fn mclk_multiple(mut self, mclk_multiple: MclkMultiple) -> Self {
214 self.mclk_multiple = mclk_multiple;
215 self
216 }
217
218 #[cfg(esp_idf_version_at_least_5_1_0)]
220 #[inline(always)]
221 pub fn bclk_div(mut self, bclk_div: u32) -> Self {
222 self.bclk_div = bclk_div;
223 self
224 }
225
226 #[cfg(not(esp_idf_version_at_least_5_1_0))]
228 #[inline(always)]
229 pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {
230 i2s_tdm_clk_config_t {
231 sample_rate_hz: self.sample_rate_hz,
232 clk_src: self.clk_src.as_sdk(),
233 mclk_multiple: self.mclk_multiple.as_sdk(),
234 }
235 }
236
237 #[cfg(esp_idf_version_at_least_5_1_0)]
239 #[allow(clippy::needless_update)]
240 #[inline(always)]
241 pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {
242 i2s_tdm_clk_config_t {
243 sample_rate_hz: self.sample_rate_hz,
244 clk_src: self.clk_src.as_sdk(),
245 mclk_multiple: self.mclk_multiple.as_sdk(),
246 bclk_div: self.bclk_div,
247 ..Default::default()
248 }
249 }
250 }
251
252 #[cfg(esp_idf_version_major = "4")]
253 pub type TdmCommFormat = crate::i2s::std::config::StdCommFormat;
254
255 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
257 pub struct TdmGpioConfig {
258 bclk_invert: bool,
260
261 mclk_invert: bool,
263
264 ws_invert: bool,
266 }
267
268 impl TdmGpioConfig {
269 pub fn new(bclk_invert: bool, mclk_invert: bool, ws_invert: bool) -> Self {
271 Self {
272 bclk_invert,
273 mclk_invert,
274 ws_invert,
275 }
276 }
277
278 #[inline(always)]
280 pub fn bclk_invert(mut self, bclk_invert: bool) -> Self {
281 self.bclk_invert = bclk_invert;
282 self
283 }
284
285 #[inline(always)]
287 pub fn mclk_invert(mut self, mclk_invert: bool) -> Self {
288 self.mclk_invert = mclk_invert;
289 self
290 }
291
292 #[inline(always)]
294 pub fn ws_invert(mut self, ws_invert: bool) -> Self {
295 self.ws_invert = ws_invert;
296 self
297 }
298
299 #[cfg(not(esp_idf_version_major = "4"))]
301 pub(crate) fn as_sdk<'d>(
302 &self,
303 bclk: impl InputPin + OutputPin + 'd,
304 din: Option<impl InputPin + 'd>,
305 dout: Option<impl OutputPin + 'd>,
306 mclk: Option<impl InputPin + OutputPin + 'd>,
307 ws: impl InputPin + OutputPin + 'd,
308 ) -> i2s_tdm_gpio_config_t {
309 let invert_flags = i2s_tdm_gpio_config_t__bindgen_ty_1 {
310 _bitfield_1: i2s_tdm_gpio_config_t__bindgen_ty_1::new_bitfield_1(
311 self.mclk_invert as u32,
312 self.bclk_invert as u32,
313 self.ws_invert as u32,
314 ),
315 ..Default::default()
316 };
317
318 i2s_tdm_gpio_config_t {
319 bclk: bclk.pin() as _,
320 din: if let Some(din) = din {
321 din.pin() as _
322 } else {
323 -1
324 },
325 dout: if let Some(dout) = dout {
326 dout.pin() as _
327 } else {
328 -1
329 },
330 mclk: if let Some(mclk) = mclk {
331 mclk.pin() as _
332 } else {
333 -1
334 },
335 ws: ws.pin() as _,
336 invert_flags,
337 }
338 }
339 }
340
341 #[doc = include_str!("tdm_slot_philips.svg")]
356 #[doc = include_str!("tdm_slot_msb.svg")]
361 #[doc = include_str!("tdm_slot_pcm_short.svg")]
365 #[doc = include_str!("tdm_slot_pcm_long.svg")]
369 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
370 pub struct TdmSlotConfig {
373 data_bit_width: DataBitWidth,
375
376 slot_bit_width: SlotBitWidth,
378
379 slot_mask: TdmSlotMask,
381
382 #[cfg(not(esp_idf_version_major = "4"))]
384 ws_width: u32,
385
386 #[cfg(not(esp_idf_version_major = "4"))]
388 ws_polarity: bool,
389
390 #[cfg(not(esp_idf_version_major = "4"))]
392 bit_shift: bool,
393
394 #[cfg(esp_idf_version_major = "4")]
395 comm_fmt: TdmCommFormat,
396
397 left_align: bool,
399
400 big_endian: bool,
402
403 bit_order_lsb: bool,
405
406 skip_mask: bool,
409
410 total_slots: u32,
413 }
414
415 impl TdmSlotConfig {
416 #[inline(always)]
418 #[must_use]
419 pub fn data_bit_width(mut self, data_bit_width: DataBitWidth) -> Self {
420 self.data_bit_width = data_bit_width;
421 self
422 }
423
424 #[inline(always)]
428 #[must_use]
429 pub fn slot_bit_width(mut self, slot_bit_width: SlotBitWidth) -> Self {
430 self.slot_bit_width = slot_bit_width;
431 self
432 }
433
434 #[inline(always)]
436 #[must_use]
437 pub fn slot_mask(mut self, slot_mask: TdmSlotMask) -> Self {
438 self.slot_mask = slot_mask;
439 self
440 }
441
442 #[cfg(not(esp_idf_version_major = "4"))]
447 #[inline(always)]
448 #[must_use]
449 pub fn ws_width(mut self, ws_width: u32) -> Self {
450 self.ws_width = ws_width;
451 self
452 }
453
454 #[cfg(not(esp_idf_version_major = "4"))]
459 #[inline(always)]
460 #[must_use]
461 pub fn ws_polarity(mut self, ws_polarity: bool) -> Self {
462 self.ws_polarity = ws_polarity;
463 self
464 }
465
466 #[cfg(not(esp_idf_version_major = "4"))]
472 #[inline(always)]
473 #[must_use]
474 pub fn bit_shift(mut self, bit_shift: bool) -> Self {
475 self.bit_shift = bit_shift;
476 self
477 }
478
479 #[cfg(esp_idf_version_major = "4")]
481 #[inline(always)]
482 #[must_use]
483 pub fn comm_fmt(mut self, comm_fmt: TdmCommFormat) -> Self {
484 self.comm_fmt = comm_fmt;
485 self
486 }
487
488 #[inline(always)]
495 #[must_use]
496 pub fn left_align(mut self, left_align: bool) -> Self {
497 self.left_align = left_align;
498 self
499 }
500
501 #[inline(always)]
508 #[must_use]
509 pub fn big_endian(mut self, big_endian: bool) -> Self {
510 self.big_endian = big_endian;
511 self
512 }
513
514 #[inline(always)]
519 #[must_use]
520 pub fn bit_order_lsb(mut self, bit_order_lsb: bool) -> Self {
521 self.bit_order_lsb = bit_order_lsb;
522 self
523 }
524
525 #[inline(always)]
530 #[must_use]
531 pub fn skip_mask(mut self, skip_mask: bool) -> Self {
532 self.skip_mask = skip_mask;
533 self
534 }
535
536 #[inline(always)]
541 #[must_use]
542 pub fn total_slots(mut self, total_slots: u32) -> Self {
543 self.total_slots = total_slots;
544 self
545 }
546
547 #[inline(always)]
549 #[must_use]
550 pub fn philips_slot_default(bits_per_sample: DataBitWidth, slot_mask: TdmSlotMask) -> Self {
551 Self {
552 data_bit_width: bits_per_sample,
553 slot_bit_width: SlotBitWidth::Auto,
554 slot_mask,
555 #[cfg(not(esp_idf_version_major = "4"))]
556 ws_width: TDM_AUTO_WS_WIDTH,
557 #[cfg(not(esp_idf_version_major = "4"))]
558 ws_polarity: false,
559 #[cfg(not(esp_idf_version_major = "4"))]
560 bit_shift: true,
561 #[cfg(esp_idf_version_major = "4")]
562 comm_fmt: TdmCommFormat::Philips,
563 left_align: false,
564 big_endian: false,
565 bit_order_lsb: false,
566 skip_mask: false,
567 total_slots: TDM_AUTO_SLOT_NUM,
568 }
569 }
570
571 #[inline(always)]
573 #[must_use]
574 pub fn msb_slot_default(bits_per_sample: DataBitWidth, slot_mask: TdmSlotMask) -> Self {
575 Self {
576 data_bit_width: bits_per_sample,
577 slot_bit_width: SlotBitWidth::Auto,
578 slot_mask,
579 #[cfg(not(esp_idf_version_major = "4"))]
580 ws_width: TDM_AUTO_WS_WIDTH,
581 #[cfg(not(esp_idf_version_major = "4"))]
582 ws_polarity: false,
583 #[cfg(not(esp_idf_version_major = "4"))]
584 bit_shift: false,
585 #[cfg(esp_idf_version_major = "4")]
586 comm_fmt: TdmCommFormat::Msb,
587 left_align: false,
588 big_endian: false,
589 bit_order_lsb: false,
590 skip_mask: false,
591 total_slots: TDM_AUTO_SLOT_NUM,
592 }
593 }
594
595 #[inline(always)]
597 #[must_use]
598 pub fn pcm_short_slot_default(
599 bits_per_sample: DataBitWidth,
600 slot_mask: TdmSlotMask,
601 ) -> Self {
602 Self {
603 data_bit_width: bits_per_sample,
604 slot_bit_width: SlotBitWidth::Auto,
605 slot_mask,
606 #[cfg(not(esp_idf_version_major = "4"))]
607 ws_width: 1,
608 #[cfg(not(esp_idf_version_major = "4"))]
609 ws_polarity: true,
610 #[cfg(not(esp_idf_version_major = "4"))]
611 bit_shift: false,
612 #[cfg(esp_idf_version_major = "4")]
613 comm_fmt: TdmCommFormat::PcmShort,
614 left_align: false,
615 big_endian: false,
616 bit_order_lsb: false,
617 skip_mask: false,
618 total_slots: TDM_AUTO_SLOT_NUM,
619 }
620 }
621
622 #[inline(always)]
624 #[must_use]
625 pub fn pcm_long_slot_default(
626 bits_per_sample: DataBitWidth,
627 slot_mask: TdmSlotMask,
628 ) -> Self {
629 Self {
630 data_bit_width: bits_per_sample,
631 slot_bit_width: SlotBitWidth::Auto,
632 slot_mask,
633 #[cfg(not(esp_idf_version_major = "4"))]
634 ws_width: bits_per_sample.into(),
635 #[cfg(not(esp_idf_version_major = "4"))]
636 ws_polarity: true,
637 #[cfg(not(esp_idf_version_major = "4"))]
638 bit_shift: false,
639 #[cfg(esp_idf_version_major = "4")]
640 comm_fmt: TdmCommFormat::PcmLong,
641 left_align: false,
642 big_endian: false,
643 bit_order_lsb: false,
644 skip_mask: false,
645 total_slots: TDM_AUTO_SLOT_NUM,
646 }
647 }
648
649 #[cfg(not(esp_idf_version_major = "4"))]
651 #[inline(always)]
652 pub(crate) fn as_sdk(&self) -> i2s_tdm_slot_config_t {
653 i2s_tdm_slot_config_t {
654 data_bit_width: self.data_bit_width.as_sdk(),
655 slot_bit_width: self.slot_bit_width.as_sdk(),
656 slot_mode: SlotMode::Stereo.as_sdk(), slot_mask: self.slot_mask.as_sdk(),
658 ws_width: self.ws_width,
659 ws_pol: self.ws_polarity,
660 bit_shift: self.bit_shift,
661 left_align: self.left_align,
662 big_endian: self.big_endian,
663 bit_order_lsb: self.bit_order_lsb,
664 skip_mask: self.skip_mask,
665 total_slot: self.total_slots,
666 }
667 }
668 }
669
670 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
672 pub enum TdmSlot {
673 Slot0,
675
676 Slot1,
678
679 Slot2,
681
682 Slot3,
684
685 Slot4,
687
688 Slot5,
690
691 Slot6,
693
694 Slot7,
696
697 Slot8,
699
700 Slot9,
702
703 Slot10,
705
706 Slot11,
708
709 Slot12,
711
712 Slot13,
714
715 Slot14,
717
718 Slot15,
720 }
721
722 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
724 pub struct TdmSlotMask(u16);
725
726 impl TryFrom<u8> for TdmSlot {
728 type Error = EspError;
729
730 fn try_from(slot: u8) -> Result<Self, Self::Error> {
731 match slot {
732 0 => Ok(Self::Slot0),
733 1 => Ok(Self::Slot1),
734 2 => Ok(Self::Slot2),
735 3 => Ok(Self::Slot3),
736 4 => Ok(Self::Slot4),
737 5 => Ok(Self::Slot5),
738 6 => Ok(Self::Slot6),
739 7 => Ok(Self::Slot7),
740 8 => Ok(Self::Slot8),
741 9 => Ok(Self::Slot9),
742 10 => Ok(Self::Slot10),
743 11 => Ok(Self::Slot11),
744 12 => Ok(Self::Slot12),
745 13 => Ok(Self::Slot13),
746 14 => Ok(Self::Slot14),
747 15 => Ok(Self::Slot15),
748 _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
749 }
750 }
751 }
752
753 impl From<TdmSlot> for u8 {
755 fn from(slot: TdmSlot) -> u8 {
756 match slot {
757 TdmSlot::Slot0 => 0,
758 TdmSlot::Slot1 => 1,
759 TdmSlot::Slot2 => 2,
760 TdmSlot::Slot3 => 3,
761 TdmSlot::Slot4 => 4,
762 TdmSlot::Slot5 => 5,
763 TdmSlot::Slot6 => 6,
764 TdmSlot::Slot7 => 7,
765 TdmSlot::Slot8 => 8,
766 TdmSlot::Slot9 => 9,
767 TdmSlot::Slot10 => 10,
768 TdmSlot::Slot11 => 11,
769 TdmSlot::Slot12 => 12,
770 TdmSlot::Slot13 => 13,
771 TdmSlot::Slot14 => 14,
772 TdmSlot::Slot15 => 15,
773 }
774 }
775 }
776
777 impl From<TdmSlot> for TdmSlotMask {
779 #[inline(always)]
780 fn from(slot: TdmSlot) -> TdmSlotMask {
781 TdmSlotMask(1 << u8::from(slot))
782 }
783 }
784
785 impl BitAnd<TdmSlot> for TdmSlot {
790 type Output = TdmSlotMask;
791
792 #[inline(always)]
793 fn bitand(self, rhs: Self) -> Self::Output {
794 TdmSlotMask::from(self) & TdmSlotMask::from(rhs)
795 }
796 }
797
798 impl BitAnd<TdmSlotMask> for TdmSlot {
803 type Output = TdmSlotMask;
804
805 #[inline(always)]
806 fn bitand(self, rhs: TdmSlotMask) -> Self::Output {
807 TdmSlotMask::from(self) & rhs
808 }
809 }
810
811 impl BitAnd<TdmSlot> for TdmSlotMask {
816 type Output = TdmSlotMask;
817
818 #[inline(always)]
819 fn bitand(self, rhs: TdmSlot) -> Self::Output {
820 self & TdmSlotMask::from(rhs)
821 }
822 }
823
824 impl BitAnd<TdmSlotMask> for TdmSlotMask {
828 type Output = Self;
829
830 #[inline(always)]
831 fn bitand(self, rhs: Self) -> Self::Output {
832 Self(self.0 & rhs.0)
833 }
834 }
835
836 impl BitAndAssign<TdmSlot> for TdmSlotMask {
841 #[inline(always)]
842 fn bitand_assign(&mut self, rhs: TdmSlot) {
843 self.0 &= TdmSlotMask::from(rhs).0;
844 }
845 }
846
847 impl BitAndAssign<TdmSlotMask> for TdmSlotMask {
851 #[inline(always)]
852 fn bitand_assign(&mut self, rhs: Self) {
853 self.0 &= rhs.0;
854 }
855 }
856
857 impl BitOr<TdmSlot> for TdmSlot {
861 type Output = TdmSlotMask;
862
863 #[inline(always)]
864 fn bitor(self, rhs: Self) -> Self::Output {
865 TdmSlotMask::from(self) | TdmSlotMask::from(rhs)
866 }
867 }
868
869 impl BitOr<TdmSlotMask> for TdmSlot {
873 type Output = TdmSlotMask;
874
875 #[inline(always)]
876 fn bitor(self, rhs: TdmSlotMask) -> Self::Output {
877 TdmSlotMask::from(self) | rhs
878 }
879 }
880
881 impl BitOr<TdmSlot> for TdmSlotMask {
885 type Output = TdmSlotMask;
886
887 #[inline(always)]
888 fn bitor(self, rhs: TdmSlot) -> Self::Output {
889 self | TdmSlotMask::from(rhs)
890 }
891 }
892
893 impl BitOr<TdmSlotMask> for TdmSlotMask {
897 type Output = Self;
898
899 #[inline(always)]
900 fn bitor(self, rhs: Self) -> Self::Output {
901 Self(self.0 | rhs.0)
902 }
903 }
904
905 impl BitOrAssign<TdmSlot> for TdmSlotMask {
909 #[inline(always)]
910 fn bitor_assign(&mut self, rhs: TdmSlot) {
911 self.0 |= TdmSlotMask::from(rhs).0;
912 }
913 }
914
915 impl BitOrAssign<TdmSlotMask> for TdmSlotMask {
919 #[inline(always)]
920 fn bitor_assign(&mut self, rhs: Self) {
921 self.0 |= rhs.0;
922 }
923 }
924
925 impl Not for TdmSlot {
928 type Output = TdmSlotMask;
929
930 #[inline(always)]
931 fn not(self) -> Self::Output {
932 !TdmSlotMask::from(self)
933 }
934 }
935
936 impl Not for TdmSlotMask {
939 type Output = Self;
940
941 fn not(self) -> Self::Output {
942 Self(!self.0)
943 }
944 }
945
946 impl TdmSlotMask {
947 #[inline(always)]
949 pub fn from_mask_value(value: u16) -> Self {
950 Self(value)
951 }
952
953 #[inline(always)]
955 pub fn is_empty(&self) -> bool {
956 self.0 == 0
957 }
958
959 #[inline(always)]
961 pub fn len(&self) -> usize {
962 self.0.count_ones() as usize
963 }
964
965 #[inline(always)]
967 pub fn mask_value(&self) -> u16 {
968 self.0
969 }
970
971 #[cfg(not(esp_idf_version_major = "4"))]
973 #[inline(always)]
974 pub(super) fn as_sdk(&self) -> i2s_tdm_slot_mask_t {
975 self.0 as i2s_tdm_slot_mask_t
976 }
977
978 #[cfg(esp_idf_version_major = "4")]
980 #[inline(always)]
981 pub(super) fn as_sdk(&self) -> i2s_channel_t {
982 ((self.0 as u32) << 16) as i2s_channel_t
983 }
984 }
985}
986
987impl<'d, Dir> I2sDriver<'d, Dir> {
988 #[cfg(not(esp_idf_version_major = "4"))]
989 #[allow(clippy::too_many_arguments)]
990 fn internal_new_tdm<I2S: I2s + 'd>(
991 _i2s: I2S,
992 config: &config::TdmConfig,
993 rx: bool,
994 tx: bool,
995 bclk: impl InputPin + OutputPin + 'd,
996 din: Option<impl InputPin + 'd>,
997 dout: Option<impl OutputPin + 'd>,
998 mclk: Option<impl InputPin + OutputPin + 'd>,
999 ws: impl InputPin + OutputPin + 'd,
1000 ) -> Result<Self, EspError> {
1001 let chan_cfg = config.channel_cfg.as_sdk(I2S::port());
1002
1003 let this = Self::internal_new::<I2S>(&chan_cfg, rx, tx)?;
1004
1005 let tdm_config = config.as_sdk(bclk, din, dout, mclk, ws);
1007
1008 if rx {
1009 unsafe {
1010 esp!(i2s_channel_init_tdm_mode(this.rx_handle, &tdm_config))?;
1012 }
1013 }
1014
1015 if tx {
1016 unsafe {
1017 esp!(i2s_channel_init_tdm_mode(this.tx_handle, &tdm_config))?;
1019 }
1020 }
1021
1022 Ok(this)
1023 }
1024
1025 #[cfg(esp_idf_version_major = "4")]
1026 #[allow(clippy::too_many_arguments)]
1027 fn internal_new_tdm<I2S: I2s + 'd>(
1028 _i2s: I2S,
1029 config: &config::TdmConfig,
1030 rx: bool,
1031 tx: bool,
1032 bclk: impl InputPin + OutputPin + 'd,
1033 din: Option<impl InputPin + 'd>,
1034 dout: Option<impl OutputPin + 'd>,
1035 mclk: Option<impl InputPin + OutputPin + 'd>,
1036 ws: impl InputPin + OutputPin + 'd,
1037 ) -> Result<Self, EspError> {
1038 let mut driver_cfg = config.as_sdk();
1039
1040 if rx {
1041 driver_cfg.mode |= i2s_mode_t_I2S_MODE_RX;
1042 }
1043
1044 if tx {
1045 driver_cfg.mode |= i2s_mode_t_I2S_MODE_TX;
1046 }
1047
1048 let this = Self::internal_new::<I2S>(&driver_cfg)?;
1049
1050 let pin_cfg = i2s_pin_config_t {
1052 bck_io_num: bclk.pin() as _,
1053 data_in_num: din.map(|din| din.pin() as _).unwrap_or(-1),
1054 data_out_num: dout.map(|dout| dout.pin() as _).unwrap_or(-1),
1055 mck_io_num: mclk.map(|mclk| mclk.pin() as _).unwrap_or(-1),
1056 ws_io_num: ws.pin() as _,
1057 };
1058
1059 unsafe {
1061 esp!(i2s_set_pin(this.port as _, &pin_cfg))?;
1062 }
1063
1064 Ok(this)
1065 }
1066}
1067
1068impl<'d> I2sDriver<'d, I2sBiDir> {
1069 #[cfg(not(any(esp32, esp32s2)))]
1071 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1072 #[allow(clippy::too_many_arguments)]
1073 pub fn new_tdm_bidir<I2S: I2s + 'd>(
1074 i2s: I2S,
1075 config: &config::TdmConfig,
1076 bclk: impl InputPin + OutputPin + 'd,
1077 din: impl InputPin + 'd,
1078 dout: impl OutputPin + 'd,
1079 mclk: Option<impl InputPin + OutputPin + 'd>,
1080 ws: impl InputPin + OutputPin + 'd,
1081 ) -> Result<Self, EspError> {
1082 Self::internal_new_tdm(
1083 i2s,
1084 config,
1085 true,
1086 true,
1087 bclk,
1088 Some(din),
1089 Some(dout),
1090 mclk,
1091 ws,
1092 )
1093 }
1094}
1095
1096impl<'d> I2sDriver<'d, I2sRx> {
1097 #[cfg(not(any(esp32, esp32s2)))]
1099 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1100 #[allow(clippy::too_many_arguments)]
1101 pub fn new_tdm_rx<I2S: I2s + 'd>(
1102 i2s: I2S,
1103 config: &config::TdmConfig,
1104 bclk: impl InputPin + OutputPin + 'd,
1105 din: impl InputPin + 'd,
1106 mclk: Option<impl InputPin + OutputPin + 'd>,
1107 ws: impl InputPin + OutputPin + 'd,
1108 ) -> Result<Self, EspError> {
1109 Self::internal_new_tdm(
1110 i2s,
1111 config,
1112 true,
1113 false,
1114 bclk,
1115 Some(din),
1116 AnyIOPin::none(),
1117 mclk,
1118 ws,
1119 )
1120 }
1121}
1122
1123impl<'d> I2sDriver<'d, I2sTx> {
1124 #[cfg(not(any(esp32, esp32s2)))]
1126 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1127 #[allow(clippy::too_many_arguments)]
1128 pub fn new_tdm_tx<I2S: I2s + 'd>(
1129 i2s: I2S,
1130 config: &config::TdmConfig,
1131 bclk: impl InputPin + OutputPin + 'd,
1132 dout: impl OutputPin + 'd,
1133 mclk: Option<impl InputPin + OutputPin + 'd>,
1134 ws: impl InputPin + OutputPin + 'd,
1135 ) -> Result<Self, EspError> {
1136 Self::internal_new_tdm(
1137 i2s,
1138 config,
1139 false,
1140 true,
1141 bclk,
1142 AnyIOPin::none(),
1143 Some(dout),
1144 mclk,
1145 ws,
1146 )
1147 }
1148}
1149
1150#[cfg(all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm))]
1159impl<Dir> I2sDriver<'_, Dir>
1160where
1161 Dir: I2sRxSupported,
1162{
1163 pub fn rx_reconfigure_tdm(&mut self, config: &config::TdmConfig) -> Result<(), EspError> {
1167 let clk_cfg = config.clk_cfg_as_sdk();
1168 let slot_cfg = config.slot_cfg_as_sdk();
1169 unsafe {
1170 esp!(i2s_channel_disable(self.rx_handle))?;
1171 esp!(i2s_channel_reconfig_tdm_clock(self.rx_handle, &clk_cfg))?;
1172 esp!(i2s_channel_reconfig_tdm_slot(self.rx_handle, &slot_cfg))?;
1173 esp!(i2s_channel_enable(self.rx_handle))?;
1174 }
1175 Ok(())
1176 }
1177}
1178
1179#[cfg(all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm))]
1188impl<Dir> I2sDriver<'_, Dir>
1189where
1190 Dir: I2sTxSupported,
1191{
1192 pub fn tx_reconfigure_tdm(&mut self, config: &config::TdmConfig) -> Result<(), EspError> {
1196 let clk_cfg = config.clk_cfg_as_sdk();
1197 let slot_cfg = config.slot_cfg_as_sdk();
1198 unsafe {
1199 esp!(i2s_channel_disable(self.tx_handle))?;
1200 esp!(i2s_channel_reconfig_tdm_clock(self.tx_handle, &clk_cfg))?;
1201 esp!(i2s_channel_reconfig_tdm_slot(self.tx_handle, &slot_cfg))?;
1202 esp!(i2s_channel_enable(self.tx_handle))?;
1203 }
1204 Ok(())
1205 }
1206}