Skip to main content

esp_idf_hal/
i2s.rs

1//! Driver for the Inter-IC Sound (I2S) peripheral(s).
2
3use 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// For v5+, we rely configuration options for PDM/TDM support.
35// For v4, we have to examine the chip type.
36#[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
57/// I2S channel base configuration.
58pub type I2sConfig = config::Config;
59
60/// I2S configuration
61pub 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    )))] // ESP-IDF 5.3 and later
106    use esp_idf_sys::i2s_chan_config_t__bindgen_ty_1; // introduces union type over auto_clear
107
108    #[cfg(esp_idf_version_at_least_6_0_0)]
109    #[allow(non_camel_case_types)]
110    type i2s_port_t = i32;
111
112    /// The default number of DMA buffers to use.
113    pub const DEFAULT_DMA_BUFFER_COUNT: u32 = 6;
114
115    /// The default number of frames per DMA buffer.
116    pub const DEFAULT_FRAMES_PER_DMA_BUFFER: u32 = 240;
117
118    /// I2S clock source.
119    #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
120    pub enum ClockSource {
121        /// Use PLL_F160M as the source clock
122        ///
123        /// Not the default on `esp32p4`: ESP-IDF only compiles the `I2S_CLK_SRC_PLL_160M` arm
124        /// of `i2s_ll_get_clk_src` under `CONFIG_ESP_REV_MIN_FULL >= 300`, so selecting it from
125        /// a build targeting an earlier minimum revision aborts in `HAL_ASSERT`.
126        #[cfg(not(any(esp32h2, esp32c2)))]
127        #[cfg_attr(not(esp32p4), default)]
128        Pll160M,
129
130        /// Use PLL_F60M as the source clock
131        #[cfg(esp32c2)]
132        #[default]
133        Pll60M,
134
135        /// Use PLL_F64M as the source clock
136        #[cfg(esp32h2)]
137        #[default]
138        Pll64M,
139
140        /// Use XTAL as the source clock
141        #[cfg(esp32p4)]
142        #[default]
143        Xtal,
144
145        /// Use APLL as the source clock
146        ///
147        /// `esp32` and `esp32s2` are named explicitly next to the capability, because the
148        /// `SOC_*` based cfgs are only emitted for ESP-IDF 5.0 and later.
149        #[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    /// I2S common channel configuration.
188    ///
189    /// To create a custom configuration, use the builder pattern built-in to this struct. For example:
190    /// ```
191    /// use esp_idf_hal::i2s::config::{ChannelOpen, Config, Role};
192    /// let config = Config::default().role(Role::Target).channels(ChannelOpen::Rx);
193    /// ```
194    ///
195    /// The default configuration is:
196    /// * [`role`][Config::role]: [`Role::Controller`] (master)
197    /// * [`dma_buffer_count`][Config::dma_buffer_count]: 6 ([`DEFAULT_DMA_BUFFER_COUNT`])
198    /// * [`frames_per_buffer`][Config::frames_per_buffer]: 240 ([`DEFAULT_FRAMES_PER_DMA_BUFFER`])
199    /// * [`auto_clear`][Config::auto_clear]: `false`
200    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
201    pub struct Config {
202        /// The role of this channel: controller (master) or target (slave)
203        pub(super) role: Role,
204
205        /// The number of DMA buffers number to use.
206        pub(super) dma_buffer_count: u32,
207
208        /// The number of I2S frames in one DMA buffer.
209        pub(super) frames_per_buffer: u32,
210
211        /// If true, the transmit buffer will be automatically cleared upon sending.
212        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        /// Create a new Config with the default settings.
225        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        /// Set the role of this channel: controller (master) or target (slave).
235        #[must_use]
236        #[inline(always)]
237        pub fn role(mut self, role: Role) -> Self {
238            self.role = role;
239            self
240        }
241
242        /// Set the number of DMA buffers to use.
243        #[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        /// Set the number of I2S frames in one DMA buffer.
251        #[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        /// Set if the transmit buffer will be automatically cleared upon sending.
259        #[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        /// Convert to the ESP-IDF SDK `i2s_chan_config_t` representation.
267        #[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                // ESP-IDF 5.3 introduced auto_clear for before_cb & after_cb 
284                #[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                )))] // For ESP-IDF v5.3 and later
290                __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    /// Available data bit width in one slot.
299    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
300    pub enum DataBitWidth {
301        /// Channel data bit width is 8 bits.
302        Bits8,
303
304        /// Channel data bit width is 16 bits.
305        Bits16,
306
307        /// Channel data bit width is 24 bits.
308        Bits24,
309
310        /// Channel data bit width is 32 bits.
311        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        /// Convert to the ESP-IDF SDK `i2s_data_bit_width_t` representation.
328        #[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        /// Convert to the ESP-IDF SDK `i2s_bits_per_sample_t` representation.
340        #[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    /// The multiple of MCLK to the sample rate.
367    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
368    pub enum MclkMultiple {
369        /// MCLK = sample rate * 128
370        M128,
371
372        /// MCLK = sample rate * 256
373        M256,
374
375        /// MCLK = sample rate * 384
376        M384,
377
378        /// MCLK = sample rate * 512
379        #[cfg(not(esp_idf_version_major = "4"))]
380        M512,
381    }
382
383    impl MclkMultiple {
384        /// Convert to the ESP-IDF SDK `i2s_mclk_multiple_t` representation.
385        #[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    /// I2S channel operating role
411    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
412    pub enum Role {
413        /// Controller (master)
414        #[default]
415        Controller,
416
417        /// Target (slave)
418        Target,
419    }
420
421    /// I2S peripheral in controller (master) role, bclk and ws signal will be set to output.
422    #[cfg(not(esp_idf_version_major = "4"))]
423    const I2S_ROLE_CONTROLLER: i2s_role_t = 0;
424
425    /// I2S peripheral in target (slave) role, bclk and ws signal will be set to input.
426    #[cfg(not(esp_idf_version_major = "4"))]
427    const I2S_ROLE_TARGET: i2s_role_t = 1;
428
429    impl Role {
430        /// Convert to the ESP-IDF SDK `i2s_role_t` representation.
431        #[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        /// Convert to the ESP-IDF SDK `i2s_mode_t` representation.
441        #[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    /// The total slot bit width in one slot.
452    ///
453    /// This is not necessarily the number of data bits in one slot. A slot may have additional bits padded to fill out
454    /// the slot.
455    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
456    pub enum SlotBitWidth {
457        /// Slot bit width is automatically set to the data bit width.
458        #[default]
459        Auto,
460
461        /// Slot bit width is 8 bits.
462        Bits8,
463
464        /// Slot bit width is 16 bits.
465        Bits16,
466
467        /// Slot bit width is 24 bits.
468        Bits24,
469
470        /// Slot bit width is 32 bits.
471        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        /// Convert this to the ESP-IDF SDK `i2s_slot_bit_width_t`/`i2s_bits_per_chan_t` representation.
482        #[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    /// I2S channel slot mode.
510    ///
511    /// See the documentation for the mode of operation to see how this affects the data layout:
512    /// * [PDM Rx][PdmRxSlotConfig]
513    /// * [PDM Tx][PdmTxSlotConfig]
514    /// * [Standard Rx/Tx][StdSlotConfig]
515    /// * [TDM Rx/Tx][TdmSlotConfig]
516    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
517    pub enum SlotMode {
518        /// Mono mode:
519        /// * When transmitting, transmit the same data in all slots.
520        /// * When receiving, only receive data from the first slot.
521        Mono,
522
523        /// Stereo mode:
524        /// * When transmitting, transmit different data in each slot.
525        /// * When receiving, receive data from all slots.
526        #[default]
527        Stereo,
528    }
529
530    impl SlotMode {
531        /// Convert this to the ESP-IDF SDK `i2s_slot_mode_t` representation.
532        #[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
543/// Trait implemented by I2S peripherals to obtain their port number.
544pub trait I2s: Send + sealed::Sealed {
545    /// Return the port number for the peripheral.
546    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    /// Returns the I2S port number of this driver.
561    fn port(&self) -> i2s_port_t;
562}
563
564/// Marker trait indicating that a driver supports receiving data via the [`I2sRx`] trait.
565pub trait I2sRxSupported {}
566
567/// Concrete implementation of [`I2sRxSupported`] for use in clients.
568///
569/// Example usage:
570/// ```
571/// use esp_idf_hal::gpio::*;
572/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
573/// use esp_idf_hal::i2s::{I2sDriver, I2sRx};
574/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
575/// let peripherals = Peripherals::take().unwrap();
576/// let bclk = peripherals.pins.gpio1;
577/// let din = peripherals.pins.gpio4;
578/// let mclk = AnyIOPin::none();
579/// let ws = peripherals.pins.gpio2;
580/// let i2s = I2sDriver::<I2sRx>::new_std_rx(peripherals.i2s0, &std_config, bclk, din, mclk, ws).unwrap();
581/// ```
582pub struct I2sRx {}
583impl I2sRxSupported for I2sRx {}
584
585/// Marker trait indicating that a driver supports transmitting data via the [`I2sTx`] trait.
586pub trait I2sTxSupported {}
587
588/// Concrete implementation of [`I2sTxSupported`] for use in clients.
589///
590/// Example usage:
591/// ```
592/// use esp_idf_hal::gpio::*;
593/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
594/// use esp_idf_hal::i2s::{I2sDriver, I2sTx};
595/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
596/// let peripherals = Peripherals::take().unwrap();
597/// let bclk = peripherals.pins.gpio1;
598/// let dout = peripherals.pins.gpio6;
599/// let mclk = AnyIOPin::none();
600/// let ws = peripherals.pins.gpio2;
601/// let i2s = I2sDriver::<I2sTx>::new_std_tx(peripherals.i2s0, &std_config, bclk, dout, mclk, ws).unwrap();
602/// ```
603pub struct I2sTx {}
604impl I2sTxSupported for I2sTx {}
605
606/// Concrete implementation of both [`I2sRxSupported`] and [`I2sTxSupported`] for use in clients.
607///
608/// Example usage:
609/// ```
610/// use esp_idf_hal::{gpio::*, peripherals::Peripherals};
611/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
612/// use esp_idf_hal::i2s::{I2sDriver, I2sBiDir};
613/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
614/// let peripherals = Peripherals::take().unwrap();
615/// let bclk = peripherals.pins.gpio1;
616/// let din = peripherals.pins.gpio4;
617/// let dout = peripherals.pins.gpio6;
618/// let mclk = AnyIOPin::none();
619/// let ws = peripherals.pins.gpio2;
620/// let i2s = I2sDriver::<I2sBiDir>::new_std_bidir(peripherals.i2s0, &std_config, bclk, din, dout, mclk, ws).unwrap();
621/// ```
622pub struct I2sBiDir {}
623impl I2sRxSupported for I2sBiDir {}
624impl I2sTxSupported for I2sBiDir {}
625
626/// Reference for I2S driver
627pub 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
643/// Inter-IC Sound (I2S) driver.
644pub struct I2sDriver<'d, Dir> {
645    /// The Rx channel, possibly null.
646    #[cfg(not(esp_idf_version_major = "4"))]
647    rx_handle: i2s_chan_handle_t,
648
649    /// The Tx channel, possibly null.
650    #[cfg(not(esp_idf_version_major = "4"))]
651    tx_handle: i2s_chan_handle_t,
652
653    /// The I2S peripheral number. Either 0 (all devices) or 1 (ESP32 and ESP32-S3 only).
654    port: u8,
655
656    /// Driver lifetime -- mimics the lifetime of the peripheral.
657    _p: PhantomData<&'d ()>,
658
659    /// Directionality -- mimics the directionality of the peripheral.
660    _dir: PhantomData<Dir>,
661}
662
663impl<Dir> I2sDriver<'_, Dir> {
664    /// Create a new standard mode driver for the given I2S peripheral with both the receive and transmit channels open.
665    #[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            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
733            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            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
756            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            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
779            esp!(unsafe {
780                i2s_channel_register_event_callback(handle, &callbacks, core::ptr::null_mut())
781            })?;
782
783            // Safety: chan_handle is a valid, non-null i2s_chan_handle_t.
784            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    /// Borrow the I2S driver by a reference
804    pub fn as_ref(&mut self) -> I2sDriverRef<'_, Dir> {
805        I2sDriverRef(unsafe { NonNull::new_unchecked(self) })
806    }
807}
808
809/// Functions for receive channels.
810impl<Dir> I2sDriver<'_, Dir>
811where
812    Dir: I2sRxSupported,
813{
814    /// Enable the I2S receive channel.
815    ///
816    /// # Note
817    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
818    /// constructor, or disabled from the `RUNNING` state via [`rx_disable()`][I2sDriver::rx_disable]. The channel
819    /// will enter the `RUNNING` state if it is enabled successfully.
820    ///
821    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
822    /// this is a controller. MCLK will be generated once initialization is finished.
823    ///
824    /// # Errors
825    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
826    #[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    /// Enable the I2S receive channel.
832    ///
833    /// # Note
834    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
835    /// constructor, or disabled from the `RUNNING` state via [`rx_enable()`][I2sRxChannel::rx_disable]. The channel
836    /// will enter the `RUNNING` state if it is enabled successfully.
837    ///
838    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
839    /// this is a controller. MCLK will be generated once initialization is finished.
840    ///
841    /// # Errors
842    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
843    #[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    /// Disable the I2S receive channel.
849    ///
850    /// # Note
851    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
852    /// via a call to [`rx_enable()`][I2sRxChannel::rx_enable]. The channel will enter the `READY` state if it is
853    /// disabled successfully.
854    ///
855    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
856    /// generated if this is a controller. MCLK will continue to be generated.
857    ///
858    /// # Errors
859    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
860    #[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    /// Disable the I2S receive channel.
866    ///
867    /// # Note
868    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
869    /// via a call to [`rx_enable()`][I2sRxChannel::rx_enable]. The channel will enter the `READY` state if it is
870    /// disabled successfully.
871    ///
872    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
873    /// generated if this is a controller. MCLK will continue to be generated.
874    ///
875    /// # Errors
876    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
877    #[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    /// Read data from the channel asynchronously.
883    ///
884    /// This may be called only when the channel is in the `RUNNING` state.
885    ///
886    /// # Returns
887    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
888    #[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    /// Read data from the channel.
901    ///
902    /// This may be called only when the channel is in the `RUNNING` state.
903    ///
904    /// # Returns
905    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
906    #[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    /// Read data from the channel.
929    ///
930    /// This may be called only when the channel is in the `RUNNING` state.
931    ///
932    /// # Returns
933    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
934    #[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    /// Read data from the channel into an uninitalized buffer asynchronously.
957    ///
958    /// This may be called only when the channel is in the `RUNNING` state.
959    ///
960    /// # Returns
961    /// This returns the number of bytes read, or an [EspError] if an error occurred.
962    ///
963    /// # Safety
964    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
965    #[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    /// Read data from the channel into an uninitalized buffer.
981    ///
982    /// This may be called only when the channel is in the `RUNNING` state.
983    ///
984    /// # Returns
985    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
986    ///
987    /// # Safety
988    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
989    #[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    /// Read data from the channel into an uninitalized buffer.
1016    ///
1017    /// This may be called only when the channel is in the `RUNNING` state.
1018    ///
1019    /// # Returns
1020    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
1021    ///
1022    /// # Safety
1023    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
1024    #[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
1051/// Functions for transmit channels.
1052impl<Dir> I2sDriver<'_, Dir>
1053where
1054    Dir: I2sTxSupported,
1055{
1056    /// Enable the I2S transmit channel.
1057    ///
1058    /// # Note
1059    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
1060    /// constructor, or disabled from the `RUNNING` state via [`tx_disable()`][I2sTxChannel::tx_disable]. The channel
1061    /// will enter the `RUNNING` state if it is enabled successfully.
1062    ///
1063    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
1064    /// this is a controller. MCLK will be generated once initialization is finished.
1065    ///
1066    /// # Errors
1067    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
1068    #[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    /// Enable the I2S transmit channel.
1074    ///
1075    /// # Note
1076    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
1077    /// constructor, or disabled from the `RUNNING` state via [`tx_disable()`][I2sTxChannel::tx_disable]. The channel
1078    /// will enter the `RUNNING` state if it is enabled successfully.
1079    ///
1080    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
1081    /// this is a controller. MCLK will be generated once initialization is finished.
1082    ///
1083    /// # Errors
1084    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
1085    #[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    /// Disable the I2S transmit channel.
1091    ///
1092    /// # Note
1093    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
1094    /// via a call to [`tx_enable()`][I2sTxChannel::tx_enable]. The channel will enter the `READY` state if it is
1095    /// disabled successfully.
1096    ///
1097    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
1098    /// generated if this is a controller. MCLK will continue to be generated.
1099    ///
1100    /// # Errors
1101    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
1102    #[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    /// Disable the I2S transmit channel.
1108    ///
1109    /// # Note
1110    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
1111    /// via a call to [`tx_enable()`][I2sTxChannel::tx_enable]. The channel will enter the `READY` state if it is disabled
1112    /// successfully.
1113    ///
1114    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
1115    /// generated if this is a controller. MCLK will continue to be generated.
1116    ///
1117    /// # Errors
1118    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
1119    #[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    /// Preload data into the transmit channel DMA buffer.
1125    ///
1126    /// This may be called only when the channel is in the `READY` state: initialized but not yet started.
1127    ///
1128    /// This is used to preload data into the DMA buffer so that valid data can be transmitted immediately after the
1129    /// channel is enabled via [`tx_enable()`][I2sTxChannel::tx_enable]. If this function is not called before enabling the channel,
1130    /// empty data will be transmitted.
1131    ///
1132    /// This function can be called multiple times before enabling the channel. Additional calls will concatenate the
1133    /// data to the end of the buffer until the buffer is full.
1134    ///
1135    /// # Returns
1136    /// This returns the number of bytes that have been loaded into the buffer. If this is less than the length of
1137    /// the data provided, the buffer is full and no more data can be loaded.
1138    #[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    /// Write data to the channel asynchronously.
1158    ///
1159    /// This may be called only when the channel is in the `RUNNING` state.
1160    ///
1161    /// # Returns
1162    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1163    #[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    /// Write all data to the channel asynchronously.
1176    ///
1177    /// This may be called only when the channel is in the `RUNNING` state.
1178    #[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    /// Write data to the channel.
1190    ///
1191    /// This may be called only when the channel is in the `RUNNING` state.
1192    ///
1193    /// # Returns
1194    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1195    #[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    /// Write data to the channel.
1218    ///
1219    /// This may be called only when the channel is in the `RUNNING` state.
1220    ///
1221    /// # Returns
1222    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1223    #[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    /// Write all data to the channel.
1246    ///
1247    /// This may be called only when the channel is in the `RUNNING` state.
1248    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    /// Split the bidirectional I2S driver into two parts (Rx, Tx)
1261    ///
1262    /// # Safety
1263    /// It is safe to use the two parts separately
1264    /// - esp-idf guarantees thread safety
1265    /// - esp-idf-hal guarantees asynchronous safety
1266    pub fn split(&mut self) -> (I2sDriverRef<'_, I2sRx>, I2sDriverRef<'_, I2sTx>) {
1267        // Safe because self cannot be null
1268        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/// C-facing ISR dispatcher for on_send_* callbacks.
1369#[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/// C-facing ISR dispatcher for on_recv_* callbacks.
1381#[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];