1use core::ffi::c_void;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6use core::ops::{Deref, DerefMut};
7use core::ptr::NonNull;
8
9use esp_idf_sys::{esp, EspError, TickType_t};
10
11#[cfg(esp_idf_version_major = "5")]
12use esp_idf_sys::i2s_port_t;
13
14#[cfg(not(esp_idf_version_major = "4"))]
15use {
16 core::ptr::null_mut,
17 esp_idf_sys::{
18 i2s_chan_config_t, i2s_chan_handle_t, i2s_channel_disable, i2s_channel_enable,
19 i2s_channel_read, i2s_channel_register_event_callback, i2s_channel_write, i2s_del_channel,
20 i2s_event_callbacks_t, i2s_event_data_t, i2s_new_channel,
21 },
22};
23
24#[cfg(esp_idf_version_major = "4")]
25use esp_idf_sys::{
26 i2s_config_t, i2s_driver_install, i2s_driver_uninstall, i2s_read, i2s_start, i2s_stop,
27 i2s_write,
28};
29
30#[cfg(not(esp_idf_version_major = "4"))]
31use crate::interrupt::asynch::HalIsrNotification;
32use crate::{delay, io::EspIOError};
33
34#[cfg(any(
37 all(
38 not(esp_idf_version_major = "4"),
39 any(esp_idf_soc_i2s_supports_pdm_rx, esp_idf_soc_i2s_supports_pdm_tx)
40 ),
41 all(esp_idf_version_major = "4", any(esp32, esp32s3, esp32c3, esp32c6))
42))]
43mod pdm;
44
45mod std;
46
47#[cfg(any(
48 all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm),
49 all(esp_idf_version_major = "4", any(esp32s3, esp32c3, esp32c6))
50))]
51mod tdm;
52
53#[cfg(esp_idf_version_at_least_6_0_0)]
54#[allow(non_camel_case_types)]
55type i2s_port_t = i32;
56
57pub type I2sConfig = config::Config;
59
60pub mod config {
62 #[cfg(any(
63 all(
64 not(esp_idf_version_major = "4"),
65 any(esp_idf_soc_i2s_supports_pdm_rx, esp_idf_soc_i2s_supports_pdm_tx)
66 ),
67 all(esp_idf_version_major = "4", any(esp32, esp32s3, esp32c3, esp32c6))
68 ))]
69 pub use super::pdm::config::*;
70
71 pub use super::std::config::*;
72
73 #[cfg(any(
74 all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm),
75 all(esp_idf_version_major = "4", any(esp32s3, esp32c3, esp32c6))
76 ))]
77 pub use super::tdm::config::*;
78
79 use esp_idf_sys::{
80 i2s_mclk_multiple_t, i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_128,
81 i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_256, i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_384,
82 EspError, ESP_ERR_INVALID_ARG,
83 };
84
85 #[cfg(esp_idf_version_major = "5")]
86 use esp_idf_sys::i2s_port_t;
87 #[cfg(not(esp_idf_version_major = "4"))]
88 use esp_idf_sys::{
89 i2s_chan_config_t, i2s_clock_src_t, i2s_data_bit_width_t,
90 i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_512, i2s_role_t, i2s_slot_bit_width_t,
91 i2s_slot_mode_t,
92 };
93
94 #[cfg(esp_idf_version_major = "4")]
95 use esp_idf_sys::{
96 i2s_bits_per_chan_t, i2s_bits_per_sample_t, i2s_mode_t, i2s_mode_t_I2S_MODE_MASTER,
97 i2s_mode_t_I2S_MODE_SLAVE,
98 };
99
100 #[cfg(not(any(
101 esp_idf_version_major = "4",
102 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
103 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
104 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
105 )))] use esp_idf_sys::i2s_chan_config_t__bindgen_ty_1; #[cfg(esp_idf_version_at_least_6_0_0)]
109 #[allow(non_camel_case_types)]
110 type i2s_port_t = i32;
111
112 pub const DEFAULT_DMA_BUFFER_COUNT: u32 = 6;
114
115 pub const DEFAULT_FRAMES_PER_DMA_BUFFER: u32 = 240;
117
118 #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
120 pub enum ClockSource {
121 #[cfg(not(any(esp32h2, esp32c2)))]
127 #[cfg_attr(not(esp32p4), default)]
128 Pll160M,
129
130 #[cfg(esp32c2)]
132 #[default]
133 Pll60M,
134
135 #[cfg(esp32h2)]
137 #[default]
138 Pll64M,
139
140 #[cfg(esp32p4)]
142 #[default]
143 Xtal,
144
145 #[cfg(any(esp_idf_soc_i2s_supports_apll, esp32, esp32s2))]
150 Apll,
151 }
152
153 impl ClockSource {
154 #[cfg(not(esp_idf_version_major = "4"))]
155 #[allow(clippy::unnecessary_cast)]
156 pub(super) fn as_sdk(&self) -> i2s_clock_src_t {
157 match self {
158 #[cfg(not(any(esp32h2, esp32c2)))]
159 Self::Pll160M => core::convert::TryInto::try_into(
160 esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F160M,
161 )
162 .unwrap(),
163 #[cfg(esp32c2)]
164 Self::Pll60M => core::convert::TryInto::try_into(
165 esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F60M,
166 )
167 .unwrap(),
168 #[cfg(esp32h2)]
169 Self::Pll64M => core::convert::TryInto::try_into(
170 esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F64M,
171 )
172 .unwrap(),
173 #[cfg(esp32p4)]
174 Self::Xtal => {
175 core::convert::TryInto::try_into(esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_XTAL)
176 .unwrap()
177 }
178 #[cfg(any(esp_idf_soc_i2s_supports_apll, esp32, esp32s2))]
179 Self::Apll => {
180 core::convert::TryInto::try_into(esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_APLL)
181 .unwrap()
182 }
183 }
184 }
185 }
186
187 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
201 pub struct Config {
202 pub(super) role: Role,
204
205 pub(super) dma_buffer_count: u32,
207
208 pub(super) frames_per_buffer: u32,
210
211 pub(super) auto_clear: bool,
213 }
214
215 impl Default for Config {
216 #[inline(always)]
217 fn default() -> Self {
218 Self::new()
219 }
220 }
221
222 impl Config {
223 #[inline(always)]
224 pub const fn new() -> Self {
226 Self {
227 role: Role::Controller,
228 dma_buffer_count: DEFAULT_DMA_BUFFER_COUNT,
229 frames_per_buffer: DEFAULT_FRAMES_PER_DMA_BUFFER,
230 auto_clear: false,
231 }
232 }
233
234 #[must_use]
236 #[inline(always)]
237 pub fn role(mut self, role: Role) -> Self {
238 self.role = role;
239 self
240 }
241
242 #[must_use]
244 #[inline(always)]
245 pub fn dma_buffer_count(mut self, dma_buffer_count: u32) -> Self {
246 self.dma_buffer_count = dma_buffer_count;
247 self
248 }
249
250 #[must_use]
252 #[inline(always)]
253 pub fn frames_per_buffer(mut self, frames: u32) -> Self {
254 self.frames_per_buffer = frames;
255 self
256 }
257
258 #[must_use]
260 #[inline(always)]
261 pub fn auto_clear(mut self, auto_clear: bool) -> Self {
262 self.auto_clear = auto_clear;
263 self
264 }
265
266 #[allow(clippy::needless_update)]
268 #[cfg(not(esp_idf_version_major = "4"))]
269 #[inline(always)]
270 pub(super) fn as_sdk(&self, id: i2s_port_t) -> i2s_chan_config_t {
271 i2s_chan_config_t {
272 id,
273 role: self.role.as_sdk(),
274 dma_desc_num: self.dma_buffer_count,
275 dma_frame_num: self.frames_per_buffer,
276 #[cfg(any(
277 esp_idf_version_major = "4",
278 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
279 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
280 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
281 ))]
282 auto_clear: self.auto_clear,
283 #[cfg(not(any(
285 esp_idf_version_major = "4",
286 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
287 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
288 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
289 )))] __bindgen_anon_1: i2s_chan_config_t__bindgen_ty_1{
291 auto_clear_after_cb: self.auto_clear,
292 },
293 ..Default::default()
294 }
295 }
296 }
297
298 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
300 pub enum DataBitWidth {
301 Bits8,
303
304 Bits16,
306
307 Bits24,
309
310 Bits32,
312 }
313
314 impl From<DataBitWidth> for u32 {
315 #[inline(always)]
316 fn from(value: DataBitWidth) -> Self {
317 match value {
318 DataBitWidth::Bits8 => 8,
319 DataBitWidth::Bits16 => 16,
320 DataBitWidth::Bits24 => 24,
321 DataBitWidth::Bits32 => 32,
322 }
323 }
324 }
325
326 impl DataBitWidth {
327 #[cfg(not(esp_idf_version_major = "4"))]
329 #[inline(always)]
330 pub(super) fn as_sdk(&self) -> i2s_data_bit_width_t {
331 match self {
332 Self::Bits8 => 8,
333 Self::Bits16 => 16,
334 Self::Bits24 => 24,
335 Self::Bits32 => 32,
336 }
337 }
338
339 #[cfg(esp_idf_version_major = "4")]
341 #[inline(always)]
342 pub(super) fn as_sdk(&self) -> i2s_bits_per_sample_t {
343 match self {
344 Self::Bits8 => 8,
345 Self::Bits16 => 16,
346 Self::Bits24 => 24,
347 Self::Bits32 => 32,
348 }
349 }
350 }
351
352 impl TryFrom<usize> for DataBitWidth {
353 type Error = EspError;
354
355 fn try_from(value: usize) -> Result<Self, Self::Error> {
356 match value {
357 8 => Ok(Self::Bits8),
358 16 => Ok(Self::Bits16),
359 24 => Ok(Self::Bits24),
360 32 => Ok(Self::Bits32),
361 _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
362 }
363 }
364 }
365
366 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
368 pub enum MclkMultiple {
369 M128,
371
372 M256,
374
375 M384,
377
378 #[cfg(not(esp_idf_version_major = "4"))]
380 M512,
381 }
382
383 impl MclkMultiple {
384 #[inline(always)]
386 pub(super) fn as_sdk(&self) -> i2s_mclk_multiple_t {
387 match self {
388 Self::M128 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_128,
389 Self::M256 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_256,
390 Self::M384 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_384,
391 #[cfg(not(esp_idf_version_major = "4"))]
392 Self::M512 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_512,
393 }
394 }
395 }
396
397 impl From<MclkMultiple> for u32 {
398 #[inline(always)]
399 fn from(mclk_multiple: MclkMultiple) -> Self {
400 match mclk_multiple {
401 MclkMultiple::M128 => 128,
402 MclkMultiple::M256 => 256,
403 MclkMultiple::M384 => 384,
404 #[cfg(not(esp_idf_version_major = "4"))]
405 MclkMultiple::M512 => 512,
406 }
407 }
408 }
409
410 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
412 pub enum Role {
413 #[default]
415 Controller,
416
417 Target,
419 }
420
421 #[cfg(not(esp_idf_version_major = "4"))]
423 const I2S_ROLE_CONTROLLER: i2s_role_t = 0;
424
425 #[cfg(not(esp_idf_version_major = "4"))]
427 const I2S_ROLE_TARGET: i2s_role_t = 1;
428
429 impl Role {
430 #[cfg(not(esp_idf_version_major = "4"))]
432 #[inline(always)]
433 pub(super) fn as_sdk(&self) -> i2s_role_t {
434 match self {
435 Self::Controller => I2S_ROLE_CONTROLLER,
436 Self::Target => I2S_ROLE_TARGET,
437 }
438 }
439
440 #[cfg(esp_idf_version_major = "4")]
442 #[inline(always)]
443 pub(super) fn as_sdk(&self) -> i2s_mode_t {
444 match self {
445 Self::Controller => i2s_mode_t_I2S_MODE_MASTER,
446 Self::Target => i2s_mode_t_I2S_MODE_SLAVE,
447 }
448 }
449 }
450
451 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
456 pub enum SlotBitWidth {
457 #[default]
459 Auto,
460
461 Bits8,
463
464 Bits16,
466
467 Bits24,
469
470 Bits32,
472 }
473
474 #[cfg(not(esp_idf_version_major = "4"))]
475 type SlotBitWidthSdkType = i2s_slot_bit_width_t;
476
477 #[cfg(esp_idf_version_major = "4")]
478 type SlotBitWidthSdkType = i2s_bits_per_chan_t;
479
480 impl SlotBitWidth {
481 #[inline(always)]
483 pub(super) fn as_sdk(&self) -> SlotBitWidthSdkType {
484 match self {
485 Self::Auto => 0,
486 Self::Bits8 => 8,
487 Self::Bits16 => 16,
488 Self::Bits24 => 24,
489 Self::Bits32 => 32,
490 }
491 }
492 }
493
494 impl TryFrom<u32> for SlotBitWidth {
495 type Error = EspError;
496
497 fn try_from(value: u32) -> Result<Self, Self::Error> {
498 match value {
499 0 => Ok(Self::Auto),
500 8 => Ok(Self::Bits8),
501 16 => Ok(Self::Bits16),
502 24 => Ok(Self::Bits24),
503 32 => Ok(Self::Bits32),
504 _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
505 }
506 }
507 }
508
509 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
517 pub enum SlotMode {
518 Mono,
522
523 #[default]
527 Stereo,
528 }
529
530 impl SlotMode {
531 #[cfg(not(esp_idf_version_major = "4"))]
533 #[inline(always)]
534 pub(super) fn as_sdk(&self) -> i2s_slot_mode_t {
535 match self {
536 Self::Mono => 1,
537 Self::Stereo => 2,
538 }
539 }
540 }
541}
542
543pub trait I2s: Send + sealed::Sealed {
545 fn port() -> i2s_port_t;
547}
548
549mod sealed {
550 pub trait Sealed {}
551
552 impl Sealed for super::I2S0<'_> {}
553 #[cfg(any(esp32, esp32s3, esp32p4))]
554 impl Sealed for super::I2S1<'_> {}
555 #[cfg(esp32p4)]
556 impl Sealed for super::I2S2<'_> {}
557}
558
559pub trait I2sPort {
560 fn port(&self) -> i2s_port_t;
562}
563
564pub trait I2sRxSupported {}
566
567pub struct I2sRx {}
583impl I2sRxSupported for I2sRx {}
584
585pub trait I2sTxSupported {}
587
588pub struct I2sTx {}
604impl I2sTxSupported for I2sTx {}
605
606pub struct I2sBiDir {}
623impl I2sRxSupported for I2sBiDir {}
624impl I2sTxSupported for I2sBiDir {}
625
626pub struct I2sDriverRef<'d, Dir>(NonNull<I2sDriver<'d, Dir>>);
628
629impl<'d, Dir> Deref for I2sDriverRef<'d, Dir> {
630 type Target = I2sDriver<'d, Dir>;
631
632 fn deref(&self) -> &Self::Target {
633 unsafe { self.0.as_ref() }
634 }
635}
636
637impl<Dir> DerefMut for I2sDriverRef<'_, Dir> {
638 fn deref_mut(&mut self) -> &mut Self::Target {
639 unsafe { self.0.as_mut() }
640 }
641}
642
643pub struct I2sDriver<'d, Dir> {
645 #[cfg(not(esp_idf_version_major = "4"))]
647 rx_handle: i2s_chan_handle_t,
648
649 #[cfg(not(esp_idf_version_major = "4"))]
651 tx_handle: i2s_chan_handle_t,
652
653 port: u8,
655
656 _p: PhantomData<&'d ()>,
658
659 _dir: PhantomData<Dir>,
661}
662
663impl<Dir> I2sDriver<'_, Dir> {
664 #[cfg(not(esp_idf_version_major = "4"))]
666 fn internal_new<I2S: I2s>(
667 config: &i2s_chan_config_t,
668 rx: bool,
669 tx: bool,
670 ) -> Result<Self, EspError> {
671 let port = I2S::port();
672
673 let mut rx_handle: i2s_chan_handle_t = null_mut();
674 let mut tx_handle: i2s_chan_handle_t = null_mut();
675
676 unsafe {
677 esp!(i2s_new_channel(
678 config,
679 if tx {
680 &mut tx_handle as _
681 } else {
682 core::ptr::null_mut()
683 },
684 if rx {
685 &mut rx_handle as _
686 } else {
687 core::ptr::null_mut()
688 },
689 ))?
690 };
691
692 let mut this = Self {
693 port: port as u8,
694 rx_handle,
695 tx_handle,
696 _p: PhantomData,
697 _dir: PhantomData,
698 };
699
700 this.subscribe_channel(this.rx_handle)?;
701 this.subscribe_channel(this.tx_handle)?;
702
703 Ok(this)
704 }
705
706 #[cfg(esp_idf_version_major = "4")]
707 #[allow(clippy::too_many_arguments)]
708 pub fn internal_new<I2S: I2s>(config: &i2s_config_t) -> Result<Self, EspError> {
709 let port = I2S::port();
710
711 unsafe {
712 esp!(i2s_driver_install(port, config, 0, core::ptr::null_mut()))?;
713 }
714
715 Ok(Self {
716 port: port as u8,
717 _p: PhantomData,
718 _dir: PhantomData,
719 })
720 }
721
722 #[cfg(not(esp_idf_version_major = "4"))]
723 fn subscribe_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
724 if !handle.is_null() {
725 let callbacks = i2s_event_callbacks_t {
726 on_recv: Some(dispatch_recv),
727 on_recv_q_ovf: Some(dispatch_recv),
728 on_sent: Some(dispatch_send),
729 on_send_q_ovf: Some(dispatch_send),
730 };
731
732 esp!(unsafe {
734 i2s_channel_register_event_callback(
735 handle,
736 &callbacks,
737 self.port as u32 as *mut core::ffi::c_void,
738 )
739 })?;
740 }
741
742 Ok(())
743 }
744
745 #[cfg(not(esp_idf_version_major = "4"))]
746 fn unsubscribe_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
747 if !handle.is_null() {
748 let callbacks = i2s_event_callbacks_t {
749 on_recv: None,
750 on_recv_q_ovf: None,
751 on_sent: None,
752 on_send_q_ovf: None,
753 };
754
755 esp!(unsafe {
757 i2s_channel_register_event_callback(
758 handle,
759 &callbacks,
760 self.port as u32 as *mut core::ffi::c_void,
761 )
762 })?;
763 }
764
765 Ok(())
766 }
767
768 #[cfg(not(esp_idf_version_major = "4"))]
769 fn del_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
770 if !handle.is_null() {
771 let callbacks = i2s_event_callbacks_t {
772 on_recv: None,
773 on_recv_q_ovf: None,
774 on_sent: None,
775 on_send_q_ovf: None,
776 };
777
778 esp!(unsafe {
780 i2s_channel_register_event_callback(handle, &callbacks, core::ptr::null_mut())
781 })?;
782
783 esp!(unsafe { i2s_del_channel(handle) })?;
785 }
786
787 Ok(())
788 }
789
790 fn remap_result(
791 result: Result<(), EspError>,
792 bytes_processed: usize,
793 ) -> Result<usize, EspError> {
794 match result {
795 Ok(_) => Ok(bytes_processed),
796 Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT && bytes_processed > 0 => {
797 Ok(bytes_processed)
798 }
799 Err(err) => Err(err),
800 }
801 }
802
803 pub fn as_ref(&mut self) -> I2sDriverRef<'_, Dir> {
805 I2sDriverRef(unsafe { NonNull::new_unchecked(self) })
806 }
807}
808
809impl<Dir> I2sDriver<'_, Dir>
811where
812 Dir: I2sRxSupported,
813{
814 #[cfg(esp_idf_version_major = "4")]
827 pub fn rx_enable(&mut self) -> Result<(), EspError> {
828 unsafe { esp!(i2s_start(self.port as _)) }
829 }
830
831 #[cfg(not(esp_idf_version_major = "4"))]
844 pub fn rx_enable(&mut self) -> Result<(), EspError> {
845 unsafe { esp!(i2s_channel_enable(self.rx_handle)) }
846 }
847
848 #[cfg(esp_idf_version_major = "4")]
861 pub fn rx_disable(&mut self) -> Result<(), EspError> {
862 unsafe { esp!(i2s_stop(self.port as _)) }
863 }
864
865 #[cfg(not(esp_idf_version_major = "4"))]
878 pub fn rx_disable(&mut self) -> Result<(), EspError> {
879 unsafe { esp!(i2s_channel_disable(self.rx_handle)) }
880 }
881
882 #[cfg(not(esp_idf_version_major = "4"))]
889 pub async fn read_async(&mut self, buffer: &mut [u8]) -> Result<usize, EspError> {
890 loop {
891 match self.read(buffer, crate::delay::NON_BLOCK) {
892 Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
893 RECV_NOTIFIER[self.port as usize].wait().await;
894 }
895 other => break other,
896 }
897 }
898 }
899
900 #[cfg(esp_idf_version_major = "4")]
907 pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
908 if buffer.is_empty() {
909 Ok(0)
910 } else {
911 let mut bytes_read: usize = 0;
912
913 Self::remap_result(
914 unsafe {
915 esp!(i2s_read(
916 self.port as _,
917 buffer.as_mut_ptr() as *mut c_void,
918 buffer.len(),
919 &mut bytes_read,
920 crate::delay::TickType(timeout).as_millis_u32(),
921 ))
922 },
923 bytes_read,
924 )
925 }
926 }
927
928 #[cfg(not(esp_idf_version_major = "4"))]
935 pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
936 if buffer.is_empty() {
937 Ok(0)
938 } else {
939 let mut bytes_read: usize = 0;
940
941 Self::remap_result(
942 unsafe {
943 esp!(i2s_channel_read(
944 self.rx_handle,
945 buffer.as_mut_ptr() as *mut c_void,
946 buffer.len(),
947 &mut bytes_read,
948 crate::delay::TickType(timeout).as_millis_u32(),
949 ))
950 },
951 bytes_read,
952 )
953 }
954 }
955
956 #[cfg(not(esp_idf_version_major = "4"))]
966 pub async fn read_uninit_async(
967 &mut self,
968 buffer: &mut [MaybeUninit<u8>],
969 ) -> Result<usize, EspError> {
970 loop {
971 match self.read_uninit(buffer, crate::delay::NON_BLOCK) {
972 Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
973 RECV_NOTIFIER[self.port as usize].wait().await;
974 }
975 other => break other,
976 }
977 }
978 }
979
980 #[cfg(esp_idf_version_major = "4")]
990 pub fn read_uninit(
991 &mut self,
992 buffer: &mut [MaybeUninit<u8>],
993 timeout: TickType_t,
994 ) -> Result<usize, EspError> {
995 if buffer.is_empty() {
996 Ok(0)
997 } else {
998 let mut bytes_read: usize = 0;
999
1000 Self::remap_result(
1001 unsafe {
1002 esp!(i2s_read(
1003 self.port as _,
1004 buffer.as_mut_ptr() as *mut c_void,
1005 buffer.len(),
1006 &mut bytes_read,
1007 crate::delay::TickType(timeout).as_millis_u32(),
1008 ))
1009 },
1010 bytes_read,
1011 )
1012 }
1013 }
1014
1015 #[cfg(not(esp_idf_version_major = "4"))]
1025 pub fn read_uninit(
1026 &mut self,
1027 buffer: &mut [MaybeUninit<u8>],
1028 timeout: TickType_t,
1029 ) -> Result<usize, EspError> {
1030 if buffer.is_empty() {
1031 Ok(0)
1032 } else {
1033 let mut bytes_read: usize = 0;
1034
1035 Self::remap_result(
1036 unsafe {
1037 esp!(i2s_channel_read(
1038 self.rx_handle,
1039 buffer.as_mut_ptr() as *mut c_void,
1040 buffer.len(),
1041 &mut bytes_read,
1042 crate::delay::TickType(timeout).as_millis_u32(),
1043 ))
1044 },
1045 bytes_read,
1046 )
1047 }
1048 }
1049}
1050
1051impl<Dir> I2sDriver<'_, Dir>
1053where
1054 Dir: I2sTxSupported,
1055{
1056 #[cfg(esp_idf_version_major = "4")]
1069 pub fn tx_enable(&mut self) -> Result<(), EspError> {
1070 unsafe { esp!(i2s_start(self.port as _)) }
1071 }
1072
1073 #[cfg(not(esp_idf_version_major = "4"))]
1086 pub fn tx_enable(&mut self) -> Result<(), EspError> {
1087 unsafe { esp!(i2s_channel_enable(self.tx_handle)) }
1088 }
1089
1090 #[cfg(esp_idf_version_major = "4")]
1103 pub fn tx_disable(&mut self) -> Result<(), EspError> {
1104 unsafe { esp!(i2s_stop(self.port())) }
1105 }
1106
1107 #[cfg(not(esp_idf_version_major = "4"))]
1120 pub fn tx_disable(&mut self) -> Result<(), EspError> {
1121 unsafe { esp!(i2s_channel_disable(self.tx_handle)) }
1122 }
1123
1124 #[cfg(all(
1139 not(esp_idf_version_major = "4"),
1140 not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0"))
1141 ))]
1142 pub fn preload_data(&mut self, data: &[u8]) -> Result<usize, EspError> {
1143 let mut bytes_loaded: usize = 0;
1144
1145 unsafe {
1146 esp!(esp_idf_sys::i2s_channel_preload_data(
1147 self.tx_handle,
1148 data.as_ptr() as *const c_void,
1149 data.len(),
1150 &mut bytes_loaded as *mut usize
1151 ))?;
1152 }
1153
1154 Ok(bytes_loaded)
1155 }
1156
1157 #[cfg(not(esp_idf_version_major = "4"))]
1164 pub async fn write_async(&mut self, data: &[u8]) -> Result<usize, EspError> {
1165 loop {
1166 match self.write(data, crate::delay::NON_BLOCK) {
1167 Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
1168 SEND_NOTIFIER[self.port as usize].wait().await;
1169 }
1170 other => break other,
1171 }
1172 }
1173 }
1174
1175 #[cfg(not(esp_idf_version_major = "4"))]
1179 pub async fn write_all_async(&mut self, data: &[u8]) -> Result<(), EspError> {
1180 let mut offset = 0;
1181
1182 while offset < data.len() {
1183 offset += self.write_async(&data[offset..]).await?;
1184 }
1185
1186 Ok(())
1187 }
1188
1189 #[cfg(esp_idf_version_major = "4")]
1196 pub fn write(&mut self, data: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
1197 if data.is_empty() {
1198 Ok(0)
1199 } else {
1200 let mut bytes_written: usize = 0;
1201
1202 Self::remap_result(
1203 unsafe {
1204 esp!(i2s_write(
1205 self.port(),
1206 data.as_ptr() as *mut c_void,
1207 data.len(),
1208 &mut bytes_written,
1209 crate::delay::TickType(timeout).as_millis_u32(),
1210 ))
1211 },
1212 bytes_written,
1213 )
1214 }
1215 }
1216
1217 #[cfg(not(esp_idf_version_major = "4"))]
1224 pub fn write(&mut self, data: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
1225 if data.is_empty() {
1226 Ok(0)
1227 } else {
1228 let mut bytes_written: usize = 0;
1229
1230 Self::remap_result(
1231 unsafe {
1232 esp!(i2s_channel_write(
1233 self.tx_handle,
1234 data.as_ptr() as *mut c_void,
1235 data.len(),
1236 &mut bytes_written,
1237 crate::delay::TickType(timeout).as_millis_u32(),
1238 ))
1239 },
1240 bytes_written,
1241 )
1242 }
1243 }
1244
1245 pub fn write_all(&mut self, data: &[u8], timeout: TickType_t) -> Result<(), EspError> {
1249 let mut offset = 0;
1250
1251 while offset < data.len() {
1252 offset += self.write(&data[offset..], timeout)?;
1253 }
1254
1255 Ok(())
1256 }
1257}
1258
1259impl I2sDriver<'_, I2sBiDir> {
1260 pub fn split(&mut self) -> (I2sDriverRef<'_, I2sRx>, I2sDriverRef<'_, I2sTx>) {
1267 let this = unsafe { NonNull::new_unchecked(self) };
1269
1270 (I2sDriverRef(this.cast()), I2sDriverRef(this.cast()))
1271 }
1272}
1273
1274impl<Dir> Drop for I2sDriver<'_, Dir> {
1275 fn drop(&mut self) {
1276 #[cfg(esp_idf_version_major = "4")]
1277 {
1278 let _ = unsafe { esp!(i2s_stop(self.port as _)) };
1279
1280 esp!(unsafe { i2s_driver_uninstall(self.port as _) }).unwrap();
1281 }
1282
1283 #[cfg(not(esp_idf_version_major = "4"))]
1284 {
1285 if !self.rx_handle.is_null() {
1286 let _ = unsafe { esp!(i2s_channel_disable(self.rx_handle)) };
1287 }
1288
1289 if !self.tx_handle.is_null() {
1290 let _ = unsafe { esp!(i2s_channel_disable(self.tx_handle)) };
1291 }
1292
1293 self.unsubscribe_channel(self.rx_handle).unwrap();
1294 self.unsubscribe_channel(self.tx_handle).unwrap();
1295
1296 if !self.rx_handle.is_null() {
1297 self.del_channel(self.rx_handle).unwrap();
1298 }
1299
1300 if !self.tx_handle.is_null() {
1301 self.del_channel(self.tx_handle).unwrap();
1302 }
1303
1304 SEND_NOTIFIER[self.port as usize].reset();
1305 RECV_NOTIFIER[self.port as usize].reset();
1306 }
1307 }
1308}
1309
1310unsafe impl<Dir> Send for I2sDriver<'_, Dir> {}
1311
1312impl<Dir> I2sPort for I2sDriver<'_, Dir> {
1313 fn port(&self) -> i2s_port_t {
1314 self.port as _
1315 }
1316}
1317
1318impl<Dir> embedded_io::ErrorType for I2sDriver<'_, Dir> {
1319 type Error = EspIOError;
1320}
1321
1322impl<Dir> embedded_io::Read for I2sDriver<'_, Dir>
1323where
1324 Dir: I2sRxSupported,
1325{
1326 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1327 self.read(buf, delay::BLOCK).map_err(EspIOError)
1328 }
1329}
1330
1331impl<Dir> embedded_io::Write for I2sDriver<'_, Dir>
1332where
1333 Dir: I2sTxSupported,
1334{
1335 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1336 self.write(buf, delay::BLOCK).map_err(EspIOError)
1337 }
1338
1339 fn flush(&mut self) -> Result<(), Self::Error> {
1340 Ok(())
1341 }
1342}
1343
1344#[cfg(not(esp_idf_version_major = "4"))]
1345impl<Dir> embedded_io_async::Read for I2sDriver<'_, Dir>
1346where
1347 Dir: I2sRxSupported,
1348{
1349 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1350 self.read_async(buf).await.map_err(EspIOError)
1351 }
1352}
1353
1354#[cfg(not(esp_idf_version_major = "4"))]
1355impl<Dir> embedded_io_async::Write for I2sDriver<'_, Dir>
1356where
1357 Dir: I2sTxSupported,
1358{
1359 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1360 self.write_async(buf).await.map_err(EspIOError)
1361 }
1362
1363 async fn flush(&mut self) -> Result<(), Self::Error> {
1364 Ok(())
1365 }
1366}
1367
1368#[cfg(not(esp_idf_version_major = "4"))]
1370unsafe extern "C" fn dispatch_send(
1371 _handle: i2s_chan_handle_t,
1372 _raw_event: *mut i2s_event_data_t,
1373 user_ctx: *mut c_void,
1374) -> bool {
1375 let port = user_ctx as u32 as i2s_port_t;
1376
1377 SEND_NOTIFIER[port as usize].notify_lsb()
1378}
1379
1380#[cfg(not(esp_idf_version_major = "4"))]
1382unsafe extern "C" fn dispatch_recv(
1383 _handle: i2s_chan_handle_t,
1384 _raw_event: *mut i2s_event_data_t,
1385 user_ctx: *mut c_void,
1386) -> bool {
1387 let port = user_ctx as u32 as i2s_port_t;
1388
1389 RECV_NOTIFIER[port as usize].notify_lsb()
1390}
1391
1392macro_rules! impl_i2s {
1393 ($i2s:ident: $port:expr) => {
1394 crate::impl_peripheral!($i2s);
1395
1396 impl I2s for $i2s<'_> {
1397 #[inline(always)]
1398 fn port() -> i2s_port_t {
1399 $port
1400 }
1401 }
1402 };
1403}
1404
1405impl_i2s!(I2S0: 0);
1406#[cfg(any(esp32, esp32s3, esp32p4))]
1407impl_i2s!(I2S1: 1);
1408#[cfg(esp32p4)]
1409impl_i2s!(I2S2: 2);
1410
1411#[cfg(not(esp_idf_version_major = "4"))]
1412#[cfg(not(any(esp32, esp32s3, esp32p4)))]
1413static SEND_NOTIFIER: [HalIsrNotification; 1] = [HalIsrNotification::new()];
1414#[cfg(not(esp_idf_version_major = "4"))]
1415#[cfg(not(any(esp32, esp32s3, esp32p4)))]
1416static RECV_NOTIFIER: [HalIsrNotification; 1] = [HalIsrNotification::new()];
1417
1418#[cfg(not(esp_idf_version_major = "4"))]
1419#[cfg(any(esp32, esp32s3))]
1420static SEND_NOTIFIER: [HalIsrNotification; 2] =
1421 [HalIsrNotification::new(), HalIsrNotification::new()];
1422#[cfg(not(esp_idf_version_major = "4"))]
1423#[cfg(any(esp32, esp32s3))]
1424static RECV_NOTIFIER: [HalIsrNotification; 2] =
1425 [HalIsrNotification::new(), HalIsrNotification::new()];
1426
1427#[cfg(not(esp_idf_version_major = "4"))]
1428#[cfg(esp32p4)]
1429static SEND_NOTIFIER: [HalIsrNotification; 3] = [
1430 HalIsrNotification::new(),
1431 HalIsrNotification::new(),
1432 HalIsrNotification::new(),
1433];
1434#[cfg(not(esp_idf_version_major = "4"))]
1435#[cfg(esp32p4)]
1436static RECV_NOTIFIER: [HalIsrNotification; 3] = [
1437 HalIsrNotification::new(),
1438 HalIsrNotification::new(),
1439 HalIsrNotification::new(),
1440];