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(not(esp_idf_version_major = "4"))]
57 #[inline(always)]
58 pub(super) fn as_sdk<'d>(
59 &self,
60 bclk: impl InputPin + OutputPin + 'd,
61 din: Option<impl InputPin + 'd>,
62 dout: Option<impl OutputPin + 'd>,
63 mclk: Option<impl InputPin + OutputPin + 'd>,
64 ws: impl InputPin + OutputPin + 'd,
65 ) -> i2s_tdm_config_t {
66 i2s_tdm_config_t {
67 clk_cfg: self.clk_cfg.as_sdk(),
68 slot_cfg: self.slot_cfg.as_sdk(),
69 gpio_cfg: self.gpio_cfg.as_sdk(bclk, din, dout, mclk, ws),
70 }
71 }
72
73 #[cfg(esp_idf_version_major = "4")]
80 pub(crate) fn as_sdk(&self) -> i2s_driver_config_t {
81 i2s_driver_config_t {
82 mode: self.channel_cfg.role.as_sdk(),
83 sample_rate: self.clk_cfg.sample_rate_hz,
84 bits_per_sample: self.slot_cfg.data_bit_width.as_sdk(),
85 channel_format: i2s_channel_fmt_t_I2S_CHANNEL_FMT_MULTIPLE, communication_format: self.slot_cfg.comm_fmt.as_sdk(),
87 intr_alloc_flags: 1 << 1, dma_buf_count: self.channel_cfg.dma_buffer_count as i32,
89 dma_buf_len: self.channel_cfg.frames_per_buffer as i32,
90 #[cfg(any(esp32, esp32s2))]
91 use_apll: matches!(self.clk_cfg.clk_src, ClockSource::Apll),
92 #[cfg(not(any(esp32, esp32s2)))]
93 use_apll: false,
94 tx_desc_auto_clear: self.channel_cfg.auto_clear,
95 fixed_mclk: 0,
96 mclk_multiple: self.clk_cfg.mclk_multiple.as_sdk(),
97 bits_per_chan: self.slot_cfg.slot_bit_width.as_sdk(),
98 chan_mask: self.slot_cfg.slot_mask.as_sdk(),
99 total_chan: self.slot_cfg.slot_mask.0.count_ones(),
100 left_align: self.slot_cfg.left_align,
101 big_edin: self.slot_cfg.big_endian,
102 bit_order_msb: !self.slot_cfg.bit_order_lsb,
103 skip_msk: self.slot_cfg.skip_mask,
104 }
105 }
106 }
107
108 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
110 pub struct TdmClkConfig {
111 sample_rate_hz: u32,
113
114 clk_src: ClockSource,
116
117 mclk_multiple: MclkMultiple,
119
120 #[cfg(esp_idf_version_at_least_5_1_0)]
123 bclk_div: u32,
124 }
125
126 pub const TDM_BCLK_DIV_MIN: u32 = 8;
128
129 impl TdmClkConfig {
130 #[cfg(not(esp_idf_version_at_least_5_1_0))]
133 #[inline(always)]
134 pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
135 Self {
136 sample_rate_hz,
137 clk_src,
138 mclk_multiple,
139 }
140 }
141
142 #[cfg(esp_idf_version_at_least_5_1_0)]
145 #[inline(always)]
146 pub fn new(sample_rate_hz: u32, clk_src: ClockSource, mclk_multiple: MclkMultiple) -> Self {
147 Self {
148 sample_rate_hz,
149 clk_src,
150 mclk_multiple,
151 bclk_div: TDM_BCLK_DIV_MIN,
152 }
153 }
154
155 #[cfg(not(esp_idf_version_at_least_5_1_0))]
162 #[inline(always)]
163 pub fn from_sample_rate_hz(rate: u32) -> Self {
164 Self {
165 sample_rate_hz: rate,
166 clk_src: ClockSource::default(),
167 mclk_multiple: MclkMultiple::M256,
168 }
169 }
170
171 #[cfg(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 bclk_div: TDM_BCLK_DIV_MIN,
185 }
186 }
187
188 #[inline(always)]
190 pub fn clk_src(mut self, clk_src: ClockSource) -> Self {
191 self.clk_src = clk_src;
192 self
193 }
194
195 #[inline(always)]
197 pub fn mclk_multiple(mut self, mclk_multiple: MclkMultiple) -> Self {
198 self.mclk_multiple = mclk_multiple;
199 self
200 }
201
202 #[cfg(esp_idf_version_at_least_5_1_0)]
204 #[inline(always)]
205 pub fn bclk_div(mut self, bclk_div: u32) -> Self {
206 self.bclk_div = bclk_div;
207 self
208 }
209
210 #[cfg(not(esp_idf_version_at_least_5_1_0))]
212 #[inline(always)]
213 pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {
214 i2s_tdm_clk_config_t {
215 sample_rate_hz: self.sample_rate_hz,
216 clk_src: self.clk_src.as_sdk(),
217 mclk_multiple: self.mclk_multiple.as_sdk(),
218 }
219 }
220
221 #[cfg(esp_idf_version_at_least_5_1_0)]
223 #[allow(clippy::needless_update)]
224 #[inline(always)]
225 pub(crate) fn as_sdk(&self) -> i2s_tdm_clk_config_t {
226 i2s_tdm_clk_config_t {
227 sample_rate_hz: self.sample_rate_hz,
228 clk_src: self.clk_src.as_sdk(),
229 mclk_multiple: self.mclk_multiple.as_sdk(),
230 bclk_div: self.bclk_div,
231 ..Default::default()
232 }
233 }
234 }
235
236 #[cfg(esp_idf_version_major = "4")]
237 pub type TdmCommFormat = crate::i2s::std::config::StdCommFormat;
238
239 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
241 pub struct TdmGpioConfig {
242 bclk_invert: bool,
244
245 mclk_invert: bool,
247
248 ws_invert: bool,
250 }
251
252 impl TdmGpioConfig {
253 pub fn new(bclk_invert: bool, mclk_invert: bool, ws_invert: bool) -> Self {
255 Self {
256 bclk_invert,
257 mclk_invert,
258 ws_invert,
259 }
260 }
261
262 #[inline(always)]
264 pub fn bclk_invert(mut self, bclk_invert: bool) -> Self {
265 self.bclk_invert = bclk_invert;
266 self
267 }
268
269 #[inline(always)]
271 pub fn mclk_invert(mut self, mclk_invert: bool) -> Self {
272 self.mclk_invert = mclk_invert;
273 self
274 }
275
276 #[inline(always)]
278 pub fn ws_invert(mut self, ws_invert: bool) -> Self {
279 self.ws_invert = ws_invert;
280 self
281 }
282
283 #[cfg(not(esp_idf_version_major = "4"))]
285 pub(crate) fn as_sdk<'d>(
286 &self,
287 bclk: impl InputPin + OutputPin + 'd,
288 din: Option<impl InputPin + 'd>,
289 dout: Option<impl OutputPin + 'd>,
290 mclk: Option<impl InputPin + OutputPin + 'd>,
291 ws: impl InputPin + OutputPin + 'd,
292 ) -> i2s_tdm_gpio_config_t {
293 let invert_flags = i2s_tdm_gpio_config_t__bindgen_ty_1 {
294 _bitfield_1: i2s_tdm_gpio_config_t__bindgen_ty_1::new_bitfield_1(
295 self.mclk_invert as u32,
296 self.bclk_invert as u32,
297 self.ws_invert as u32,
298 ),
299 ..Default::default()
300 };
301
302 i2s_tdm_gpio_config_t {
303 bclk: bclk.pin() as _,
304 din: if let Some(din) = din {
305 din.pin() as _
306 } else {
307 -1
308 },
309 dout: if let Some(dout) = dout {
310 dout.pin() as _
311 } else {
312 -1
313 },
314 mclk: if let Some(mclk) = mclk {
315 mclk.pin() as _
316 } else {
317 -1
318 },
319 ws: ws.pin() as _,
320 invert_flags,
321 }
322 }
323 }
324
325 #[doc = include_str!("tdm_slot_philips.svg")]
340 #[doc = include_str!("tdm_slot_msb.svg")]
345 #[doc = include_str!("tdm_slot_pcm_short.svg")]
349 #[doc = include_str!("tdm_slot_pcm_long.svg")]
353 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
354 pub struct TdmSlotConfig {
357 data_bit_width: DataBitWidth,
359
360 slot_bit_width: SlotBitWidth,
362
363 slot_mask: TdmSlotMask,
365
366 #[cfg(not(esp_idf_version_major = "4"))]
368 ws_width: u32,
369
370 #[cfg(not(esp_idf_version_major = "4"))]
372 ws_polarity: bool,
373
374 #[cfg(not(esp_idf_version_major = "4"))]
376 bit_shift: bool,
377
378 #[cfg(esp_idf_version_major = "4")]
379 comm_fmt: TdmCommFormat,
380
381 left_align: bool,
383
384 big_endian: bool,
386
387 bit_order_lsb: bool,
389
390 skip_mask: bool,
393
394 total_slots: u32,
397 }
398
399 impl TdmSlotConfig {
400 #[inline(always)]
402 #[must_use]
403 pub fn data_bit_width(mut self, data_bit_width: DataBitWidth) -> Self {
404 self.data_bit_width = data_bit_width;
405 self
406 }
407
408 #[inline(always)]
412 #[must_use]
413 pub fn slot_bit_width(mut self, slot_bit_width: SlotBitWidth) -> Self {
414 self.slot_bit_width = slot_bit_width;
415 self
416 }
417
418 #[inline(always)]
420 #[must_use]
421 pub fn slot_mask(mut self, slot_mask: TdmSlotMask) -> Self {
422 self.slot_mask = slot_mask;
423 self
424 }
425
426 #[cfg(not(esp_idf_version_major = "4"))]
431 #[inline(always)]
432 #[must_use]
433 pub fn ws_width(mut self, ws_width: u32) -> Self {
434 self.ws_width = ws_width;
435 self
436 }
437
438 #[cfg(not(esp_idf_version_major = "4"))]
443 #[inline(always)]
444 #[must_use]
445 pub fn ws_polarity(mut self, ws_polarity: bool) -> Self {
446 self.ws_polarity = ws_polarity;
447 self
448 }
449
450 #[cfg(not(esp_idf_version_major = "4"))]
456 #[inline(always)]
457 #[must_use]
458 pub fn bit_shift(mut self, bit_shift: bool) -> Self {
459 self.bit_shift = bit_shift;
460 self
461 }
462
463 #[cfg(esp_idf_version_major = "4")]
465 #[inline(always)]
466 #[must_use]
467 pub fn comm_fmt(mut self, comm_fmt: TdmCommFormat) -> Self {
468 self.comm_fmt = comm_fmt;
469 self
470 }
471
472 #[inline(always)]
479 #[must_use]
480 pub fn left_align(mut self, left_align: bool) -> Self {
481 self.left_align = left_align;
482 self
483 }
484
485 #[inline(always)]
492 #[must_use]
493 pub fn big_endian(mut self, big_endian: bool) -> Self {
494 self.big_endian = big_endian;
495 self
496 }
497
498 #[inline(always)]
503 #[must_use]
504 pub fn bit_order_lsb(mut self, bit_order_lsb: bool) -> Self {
505 self.bit_order_lsb = bit_order_lsb;
506 self
507 }
508
509 #[inline(always)]
514 #[must_use]
515 pub fn skip_mask(mut self, skip_mask: bool) -> Self {
516 self.skip_mask = skip_mask;
517 self
518 }
519
520 #[inline(always)]
525 #[must_use]
526 pub fn total_slots(mut self, total_slots: u32) -> Self {
527 self.total_slots = total_slots;
528 self
529 }
530
531 #[inline(always)]
533 #[must_use]
534 pub fn philips_slot_default(bits_per_sample: DataBitWidth, slot_mask: TdmSlotMask) -> Self {
535 Self {
536 data_bit_width: bits_per_sample,
537 slot_bit_width: SlotBitWidth::Auto,
538 slot_mask,
539 #[cfg(not(esp_idf_version_major = "4"))]
540 ws_width: TDM_AUTO_WS_WIDTH,
541 #[cfg(not(esp_idf_version_major = "4"))]
542 ws_polarity: false,
543 #[cfg(not(esp_idf_version_major = "4"))]
544 bit_shift: true,
545 #[cfg(esp_idf_version_major = "4")]
546 comm_fmt: TdmCommFormat::Philips,
547 left_align: false,
548 big_endian: false,
549 bit_order_lsb: false,
550 skip_mask: false,
551 total_slots: TDM_AUTO_SLOT_NUM,
552 }
553 }
554
555 #[inline(always)]
557 #[must_use]
558 pub fn msb_slot_default(bits_per_sample: DataBitWidth, slot_mask: TdmSlotMask) -> Self {
559 Self {
560 data_bit_width: bits_per_sample,
561 slot_bit_width: SlotBitWidth::Auto,
562 slot_mask,
563 #[cfg(not(esp_idf_version_major = "4"))]
564 ws_width: TDM_AUTO_WS_WIDTH,
565 #[cfg(not(esp_idf_version_major = "4"))]
566 ws_polarity: false,
567 #[cfg(not(esp_idf_version_major = "4"))]
568 bit_shift: false,
569 #[cfg(esp_idf_version_major = "4")]
570 comm_fmt: TdmCommFormat::Msb,
571 left_align: false,
572 big_endian: false,
573 bit_order_lsb: false,
574 skip_mask: false,
575 total_slots: TDM_AUTO_SLOT_NUM,
576 }
577 }
578
579 #[inline(always)]
581 #[must_use]
582 pub fn pcm_short_slot_default(
583 bits_per_sample: DataBitWidth,
584 slot_mask: TdmSlotMask,
585 ) -> Self {
586 Self {
587 data_bit_width: bits_per_sample,
588 slot_bit_width: SlotBitWidth::Auto,
589 slot_mask,
590 #[cfg(not(esp_idf_version_major = "4"))]
591 ws_width: 1,
592 #[cfg(not(esp_idf_version_major = "4"))]
593 ws_polarity: true,
594 #[cfg(not(esp_idf_version_major = "4"))]
595 bit_shift: false,
596 #[cfg(esp_idf_version_major = "4")]
597 comm_fmt: TdmCommFormat::PcmShort,
598 left_align: false,
599 big_endian: false,
600 bit_order_lsb: false,
601 skip_mask: false,
602 total_slots: TDM_AUTO_SLOT_NUM,
603 }
604 }
605
606 #[inline(always)]
608 #[must_use]
609 pub fn pcm_long_slot_default(
610 bits_per_sample: DataBitWidth,
611 slot_mask: TdmSlotMask,
612 ) -> Self {
613 Self {
614 data_bit_width: bits_per_sample,
615 slot_bit_width: SlotBitWidth::Auto,
616 slot_mask,
617 #[cfg(not(esp_idf_version_major = "4"))]
618 ws_width: bits_per_sample.into(),
619 #[cfg(not(esp_idf_version_major = "4"))]
620 ws_polarity: true,
621 #[cfg(not(esp_idf_version_major = "4"))]
622 bit_shift: false,
623 #[cfg(esp_idf_version_major = "4")]
624 comm_fmt: TdmCommFormat::PcmLong,
625 left_align: false,
626 big_endian: false,
627 bit_order_lsb: false,
628 skip_mask: false,
629 total_slots: TDM_AUTO_SLOT_NUM,
630 }
631 }
632
633 #[cfg(not(esp_idf_version_major = "4"))]
635 #[inline(always)]
636 pub(crate) fn as_sdk(&self) -> i2s_tdm_slot_config_t {
637 i2s_tdm_slot_config_t {
638 data_bit_width: self.data_bit_width.as_sdk(),
639 slot_bit_width: self.slot_bit_width.as_sdk(),
640 slot_mode: SlotMode::Stereo.as_sdk(), slot_mask: self.slot_mask.as_sdk(),
642 ws_width: self.ws_width,
643 ws_pol: self.ws_polarity,
644 bit_shift: self.bit_shift,
645 left_align: self.left_align,
646 big_endian: self.big_endian,
647 bit_order_lsb: self.bit_order_lsb,
648 skip_mask: self.skip_mask,
649 total_slot: self.total_slots,
650 }
651 }
652 }
653
654 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
656 pub enum TdmSlot {
657 Slot0,
659
660 Slot1,
662
663 Slot2,
665
666 Slot3,
668
669 Slot4,
671
672 Slot5,
674
675 Slot6,
677
678 Slot7,
680
681 Slot8,
683
684 Slot9,
686
687 Slot10,
689
690 Slot11,
692
693 Slot12,
695
696 Slot13,
698
699 Slot14,
701
702 Slot15,
704 }
705
706 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
708 pub struct TdmSlotMask(u16);
709
710 impl TryFrom<u8> for TdmSlot {
712 type Error = EspError;
713
714 fn try_from(slot: u8) -> Result<Self, Self::Error> {
715 match slot {
716 0 => Ok(Self::Slot0),
717 1 => Ok(Self::Slot1),
718 2 => Ok(Self::Slot2),
719 3 => Ok(Self::Slot3),
720 4 => Ok(Self::Slot4),
721 5 => Ok(Self::Slot5),
722 6 => Ok(Self::Slot6),
723 7 => Ok(Self::Slot7),
724 8 => Ok(Self::Slot8),
725 9 => Ok(Self::Slot9),
726 10 => Ok(Self::Slot10),
727 11 => Ok(Self::Slot11),
728 12 => Ok(Self::Slot12),
729 13 => Ok(Self::Slot13),
730 14 => Ok(Self::Slot14),
731 15 => Ok(Self::Slot15),
732 _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
733 }
734 }
735 }
736
737 impl From<TdmSlot> for u8 {
739 fn from(slot: TdmSlot) -> u8 {
740 match slot {
741 TdmSlot::Slot0 => 0,
742 TdmSlot::Slot1 => 1,
743 TdmSlot::Slot2 => 2,
744 TdmSlot::Slot3 => 3,
745 TdmSlot::Slot4 => 4,
746 TdmSlot::Slot5 => 5,
747 TdmSlot::Slot6 => 6,
748 TdmSlot::Slot7 => 7,
749 TdmSlot::Slot8 => 8,
750 TdmSlot::Slot9 => 9,
751 TdmSlot::Slot10 => 10,
752 TdmSlot::Slot11 => 11,
753 TdmSlot::Slot12 => 12,
754 TdmSlot::Slot13 => 13,
755 TdmSlot::Slot14 => 14,
756 TdmSlot::Slot15 => 15,
757 }
758 }
759 }
760
761 impl From<TdmSlot> for TdmSlotMask {
763 #[inline(always)]
764 fn from(slot: TdmSlot) -> TdmSlotMask {
765 TdmSlotMask(1 << u8::from(slot))
766 }
767 }
768
769 impl BitAnd<TdmSlot> for TdmSlot {
774 type Output = TdmSlotMask;
775
776 #[inline(always)]
777 fn bitand(self, rhs: Self) -> Self::Output {
778 TdmSlotMask::from(self) & TdmSlotMask::from(rhs)
779 }
780 }
781
782 impl BitAnd<TdmSlotMask> for TdmSlot {
787 type Output = TdmSlotMask;
788
789 #[inline(always)]
790 fn bitand(self, rhs: TdmSlotMask) -> Self::Output {
791 TdmSlotMask::from(self) & rhs
792 }
793 }
794
795 impl BitAnd<TdmSlot> for TdmSlotMask {
800 type Output = TdmSlotMask;
801
802 #[inline(always)]
803 fn bitand(self, rhs: TdmSlot) -> Self::Output {
804 self & TdmSlotMask::from(rhs)
805 }
806 }
807
808 impl BitAnd<TdmSlotMask> for TdmSlotMask {
812 type Output = Self;
813
814 #[inline(always)]
815 fn bitand(self, rhs: Self) -> Self::Output {
816 Self(self.0 & rhs.0)
817 }
818 }
819
820 impl BitAndAssign<TdmSlot> for TdmSlotMask {
825 #[inline(always)]
826 fn bitand_assign(&mut self, rhs: TdmSlot) {
827 self.0 &= TdmSlotMask::from(rhs).0;
828 }
829 }
830
831 impl BitAndAssign<TdmSlotMask> for TdmSlotMask {
835 #[inline(always)]
836 fn bitand_assign(&mut self, rhs: Self) {
837 self.0 &= rhs.0;
838 }
839 }
840
841 impl BitOr<TdmSlot> for TdmSlot {
845 type Output = TdmSlotMask;
846
847 #[inline(always)]
848 fn bitor(self, rhs: Self) -> Self::Output {
849 TdmSlotMask::from(self) | TdmSlotMask::from(rhs)
850 }
851 }
852
853 impl BitOr<TdmSlotMask> for TdmSlot {
857 type Output = TdmSlotMask;
858
859 #[inline(always)]
860 fn bitor(self, rhs: TdmSlotMask) -> Self::Output {
861 TdmSlotMask::from(self) | rhs
862 }
863 }
864
865 impl BitOr<TdmSlot> for TdmSlotMask {
869 type Output = TdmSlotMask;
870
871 #[inline(always)]
872 fn bitor(self, rhs: TdmSlot) -> Self::Output {
873 self | TdmSlotMask::from(rhs)
874 }
875 }
876
877 impl BitOr<TdmSlotMask> for TdmSlotMask {
881 type Output = Self;
882
883 #[inline(always)]
884 fn bitor(self, rhs: Self) -> Self::Output {
885 Self(self.0 | rhs.0)
886 }
887 }
888
889 impl BitOrAssign<TdmSlot> for TdmSlotMask {
893 #[inline(always)]
894 fn bitor_assign(&mut self, rhs: TdmSlot) {
895 self.0 |= TdmSlotMask::from(rhs).0;
896 }
897 }
898
899 impl BitOrAssign<TdmSlotMask> for TdmSlotMask {
903 #[inline(always)]
904 fn bitor_assign(&mut self, rhs: Self) {
905 self.0 |= rhs.0;
906 }
907 }
908
909 impl Not for TdmSlot {
912 type Output = TdmSlotMask;
913
914 #[inline(always)]
915 fn not(self) -> Self::Output {
916 !TdmSlotMask::from(self)
917 }
918 }
919
920 impl Not for TdmSlotMask {
923 type Output = Self;
924
925 fn not(self) -> Self::Output {
926 Self(!self.0)
927 }
928 }
929
930 impl TdmSlotMask {
931 #[inline(always)]
933 pub fn from_mask_value(value: u16) -> Self {
934 Self(value)
935 }
936
937 #[inline(always)]
939 pub fn is_empty(&self) -> bool {
940 self.0 == 0
941 }
942
943 #[inline(always)]
945 pub fn len(&self) -> usize {
946 self.0.count_ones() as usize
947 }
948
949 #[inline(always)]
951 pub fn mask_value(&self) -> u16 {
952 self.0
953 }
954
955 #[cfg(not(esp_idf_version_major = "4"))]
957 #[inline(always)]
958 pub(super) fn as_sdk(&self) -> i2s_tdm_slot_mask_t {
959 self.0 as i2s_tdm_slot_mask_t
960 }
961
962 #[cfg(esp_idf_version_major = "4")]
964 #[inline(always)]
965 pub(super) fn as_sdk(&self) -> i2s_channel_t {
966 ((self.0 as u32) << 16) as i2s_channel_t
967 }
968 }
969}
970
971impl<'d, Dir> I2sDriver<'d, Dir> {
972 #[cfg(not(esp_idf_version_major = "4"))]
973 #[allow(clippy::too_many_arguments)]
974 fn internal_new_tdm<I2S: I2s + 'd>(
975 _i2s: I2S,
976 config: &config::TdmConfig,
977 rx: bool,
978 tx: bool,
979 bclk: impl InputPin + OutputPin + 'd,
980 din: Option<impl InputPin + 'd>,
981 dout: Option<impl OutputPin + 'd>,
982 mclk: Option<impl InputPin + OutputPin + 'd>,
983 ws: impl InputPin + OutputPin + 'd,
984 ) -> Result<Self, EspError> {
985 let chan_cfg = config.channel_cfg.as_sdk(I2S::port());
986
987 let this = Self::internal_new::<I2S>(&chan_cfg, rx, tx)?;
988
989 let tdm_config = config.as_sdk(bclk, din, dout, mclk, ws);
991
992 if rx {
993 unsafe {
994 esp!(i2s_channel_init_tdm_mode(this.rx_handle, &tdm_config))?;
996 }
997 }
998
999 if tx {
1000 unsafe {
1001 esp!(i2s_channel_init_tdm_mode(this.tx_handle, &tdm_config))?;
1003 }
1004 }
1005
1006 Ok(this)
1007 }
1008
1009 #[cfg(esp_idf_version_major = "4")]
1010 #[allow(clippy::too_many_arguments)]
1011 fn internal_new_tdm<I2S: I2s + 'd>(
1012 _i2s: I2S,
1013 config: &config::TdmConfig,
1014 rx: bool,
1015 tx: bool,
1016 bclk: impl InputPin + OutputPin + 'd,
1017 din: Option<impl InputPin + 'd>,
1018 dout: Option<impl OutputPin + 'd>,
1019 mclk: Option<impl InputPin + OutputPin + 'd>,
1020 ws: impl InputPin + OutputPin + 'd,
1021 ) -> Result<Self, EspError> {
1022 let mut driver_cfg = config.as_sdk();
1023
1024 if rx {
1025 driver_cfg.mode |= i2s_mode_t_I2S_MODE_RX;
1026 }
1027
1028 if tx {
1029 driver_cfg.mode |= i2s_mode_t_I2S_MODE_TX;
1030 }
1031
1032 let this = Self::internal_new::<I2S>(&driver_cfg)?;
1033
1034 let pin_cfg = i2s_pin_config_t {
1036 bck_io_num: bclk.pin() as _,
1037 data_in_num: din.map(|din| din.pin() as _).unwrap_or(-1),
1038 data_out_num: dout.map(|dout| dout.pin() as _).unwrap_or(-1),
1039 mck_io_num: mclk.map(|mclk| mclk.pin() as _).unwrap_or(-1),
1040 ws_io_num: ws.pin() as _,
1041 };
1042
1043 unsafe {
1045 esp!(i2s_set_pin(this.port as _, &pin_cfg))?;
1046 }
1047
1048 Ok(this)
1049 }
1050}
1051
1052impl<'d> I2sDriver<'d, I2sBiDir> {
1053 #[cfg(not(any(esp32, esp32s2)))]
1055 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1056 #[allow(clippy::too_many_arguments)]
1057 pub fn new_tdm_bidir<I2S: I2s + 'd>(
1058 i2s: I2S,
1059 config: &config::TdmConfig,
1060 bclk: impl InputPin + OutputPin + 'd,
1061 din: impl InputPin + 'd,
1062 dout: impl OutputPin + 'd,
1063 mclk: Option<impl InputPin + OutputPin + 'd>,
1064 ws: impl InputPin + OutputPin + 'd,
1065 ) -> Result<Self, EspError> {
1066 Self::internal_new_tdm(
1067 i2s,
1068 config,
1069 true,
1070 true,
1071 bclk,
1072 Some(din),
1073 Some(dout),
1074 mclk,
1075 ws,
1076 )
1077 }
1078}
1079
1080impl<'d> I2sDriver<'d, I2sRx> {
1081 #[cfg(not(any(esp32, esp32s2)))]
1083 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1084 #[allow(clippy::too_many_arguments)]
1085 pub fn new_tdm_rx<I2S: I2s + 'd>(
1086 i2s: I2S,
1087 config: &config::TdmConfig,
1088 bclk: impl InputPin + OutputPin + 'd,
1089 din: impl InputPin + 'd,
1090 mclk: Option<impl InputPin + OutputPin + 'd>,
1091 ws: impl InputPin + OutputPin + 'd,
1092 ) -> Result<Self, EspError> {
1093 Self::internal_new_tdm(
1094 i2s,
1095 config,
1096 true,
1097 false,
1098 bclk,
1099 Some(din),
1100 AnyIOPin::none(),
1101 mclk,
1102 ws,
1103 )
1104 }
1105}
1106
1107impl<'d> I2sDriver<'d, I2sTx> {
1108 #[cfg(not(any(esp32, esp32s2)))]
1110 #[cfg_attr(feature = "nightly", doc(cfg(not(any(esp32, esp32s2)))))]
1111 #[allow(clippy::too_many_arguments)]
1112 pub fn new_tdm_tx<I2S: I2s + 'd>(
1113 i2s: I2S,
1114 config: &config::TdmConfig,
1115 bclk: impl InputPin + OutputPin + 'd,
1116 dout: impl OutputPin + 'd,
1117 mclk: Option<impl InputPin + OutputPin + 'd>,
1118 ws: impl InputPin + OutputPin + 'd,
1119 ) -> Result<Self, EspError> {
1120 Self::internal_new_tdm(
1121 i2s,
1122 config,
1123 false,
1124 true,
1125 bclk,
1126 AnyIOPin::none(),
1127 Some(dout),
1128 mclk,
1129 ws,
1130 )
1131 }
1132}