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        #[cfg(not(any(esp32h2, esp32c2)))]
123        #[default]
124        Pll160M,
125
126        /// Use PLL_F60M as the source clock
127        #[cfg(esp32c2)]
128        #[default]
129        Pll60M,
130
131        /// Use PLL_F64M as the source clock
132        #[cfg(esp32h2)]
133        #[default]
134        Pll64M,
135
136        /// Use APLL as the source clock
137        #[cfg(any(esp32, esp32s2))]
138        Apll,
139    }
140
141    impl ClockSource {
142        #[cfg(not(esp_idf_version_major = "4"))]
143        #[allow(clippy::unnecessary_cast)]
144        pub(super) fn as_sdk(&self) -> i2s_clock_src_t {
145            match self {
146                #[cfg(not(any(esp32h2, esp32c2)))]
147                Self::Pll160M => core::convert::TryInto::try_into(
148                    esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F160M,
149                )
150                .unwrap(),
151                #[cfg(esp32c2)]
152                Self::Pll60M => core::convert::TryInto::try_into(
153                    esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F60M,
154                )
155                .unwrap(),
156                #[cfg(esp32h2)]
157                Self::Pll64M => core::convert::TryInto::try_into(
158                    esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_PLL_F64M,
159                )
160                .unwrap(),
161                #[cfg(any(esp32, esp32s2))]
162                Self::Apll => esp_idf_sys::soc_module_clk_t_SOC_MOD_CLK_APLL,
163            }
164        }
165    }
166
167    /// I2S common channel configuration.
168    ///
169    /// To create a custom configuration, use the builder pattern built-in to this struct. For example:
170    /// ```
171    /// use esp_idf_hal::i2s::config::{ChannelOpen, Config, Role};
172    /// let config = Config::default().role(Role::Target).channels(ChannelOpen::Rx);
173    /// ```
174    ///
175    /// The default configuration is:
176    /// * [`role`][Config::role]: [`Role::Controller`] (master)
177    /// * [`dma_buffer_count`][Config::dma_buffer_count]: 6 ([`DEFAULT_DMA_BUFFER_COUNT`])
178    /// * [`frames_per_buffer`][Config::frames_per_buffer]: 240 ([`DEFAULT_FRAMES_PER_DMA_BUFFER`])
179    /// * [`auto_clear`][Config::auto_clear]: `false`
180    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
181    pub struct Config {
182        /// The role of this channel: controller (master) or target (slave)
183        pub(super) role: Role,
184
185        /// The number of DMA buffers number to use.
186        pub(super) dma_buffer_count: u32,
187
188        /// The number of I2S frames in one DMA buffer.
189        pub(super) frames_per_buffer: u32,
190
191        /// If true, the transmit buffer will be automatically cleared upon sending.
192        pub(super) auto_clear: bool,
193    }
194
195    impl Default for Config {
196        #[inline(always)]
197        fn default() -> Self {
198            Self::new()
199        }
200    }
201
202    impl Config {
203        #[inline(always)]
204        /// Create a new Config with the default settings.
205        pub const fn new() -> Self {
206            Self {
207                role: Role::Controller,
208                dma_buffer_count: DEFAULT_DMA_BUFFER_COUNT,
209                frames_per_buffer: DEFAULT_FRAMES_PER_DMA_BUFFER,
210                auto_clear: false,
211            }
212        }
213
214        /// Set the role of this channel: controller (master) or target (slave).
215        #[must_use]
216        #[inline(always)]
217        pub fn role(mut self, role: Role) -> Self {
218            self.role = role;
219            self
220        }
221
222        /// Set the number of DMA buffers to use.
223        #[must_use]
224        #[inline(always)]
225        pub fn dma_buffer_count(mut self, dma_buffer_count: u32) -> Self {
226            self.dma_buffer_count = dma_buffer_count;
227            self
228        }
229
230        /// Set the number of I2S frames in one DMA buffer.
231        #[must_use]
232        #[inline(always)]
233        pub fn frames_per_buffer(mut self, frames: u32) -> Self {
234            self.frames_per_buffer = frames;
235            self
236        }
237
238        /// Set if the transmit buffer will be automatically cleared upon sending.
239        #[must_use]
240        #[inline(always)]
241        pub fn auto_clear(mut self, auto_clear: bool) -> Self {
242            self.auto_clear = auto_clear;
243            self
244        }
245
246        /// Convert to the ESP-IDF SDK `i2s_chan_config_t` representation.
247        #[allow(clippy::needless_update)]
248        #[cfg(not(esp_idf_version_major = "4"))]
249        #[inline(always)]
250        pub(super) fn as_sdk(&self, id: i2s_port_t) -> i2s_chan_config_t {
251            i2s_chan_config_t {
252                id,
253                role: self.role.as_sdk(),
254                dma_desc_num: self.dma_buffer_count,
255                dma_frame_num: self.frames_per_buffer,
256                #[cfg(any(
257                    esp_idf_version_major = "4",
258                    all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
259                    all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
260                    all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
261                ))]
262                auto_clear: self.auto_clear,
263                // ESP-IDF 5.3 introduced auto_clear for before_cb & after_cb 
264                #[cfg(not(any(
265                    esp_idf_version_major = "4",
266                    all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
267                    all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
268                    all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
269                )))] // For ESP-IDF v5.3 and later
270                __bindgen_anon_1: i2s_chan_config_t__bindgen_ty_1{
271                    auto_clear_after_cb: self.auto_clear,
272                },
273                ..Default::default()
274            }
275        }
276    }
277
278    /// Available data bit width in one slot.
279    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
280    pub enum DataBitWidth {
281        /// Channel data bit width is 8 bits.
282        Bits8,
283
284        /// Channel data bit width is 16 bits.
285        Bits16,
286
287        /// Channel data bit width is 24 bits.
288        Bits24,
289
290        /// Channel data bit width is 32 bits.
291        Bits32,
292    }
293
294    impl From<DataBitWidth> for u32 {
295        #[inline(always)]
296        fn from(value: DataBitWidth) -> Self {
297            match value {
298                DataBitWidth::Bits8 => 8,
299                DataBitWidth::Bits16 => 16,
300                DataBitWidth::Bits24 => 24,
301                DataBitWidth::Bits32 => 32,
302            }
303        }
304    }
305
306    impl DataBitWidth {
307        /// Convert to the ESP-IDF SDK `i2s_data_bit_width_t` representation.
308        #[cfg(not(esp_idf_version_major = "4"))]
309        #[inline(always)]
310        pub(super) fn as_sdk(&self) -> i2s_data_bit_width_t {
311            match self {
312                Self::Bits8 => 8,
313                Self::Bits16 => 16,
314                Self::Bits24 => 24,
315                Self::Bits32 => 32,
316            }
317        }
318
319        /// Convert to the ESP-IDF SDK `i2s_bits_per_sample_t` representation.
320        #[cfg(esp_idf_version_major = "4")]
321        #[inline(always)]
322        pub(super) fn as_sdk(&self) -> i2s_bits_per_sample_t {
323            match self {
324                Self::Bits8 => 8,
325                Self::Bits16 => 16,
326                Self::Bits24 => 24,
327                Self::Bits32 => 32,
328            }
329        }
330    }
331
332    impl TryFrom<usize> for DataBitWidth {
333        type Error = EspError;
334
335        fn try_from(value: usize) -> Result<Self, Self::Error> {
336            match value {
337                8 => Ok(Self::Bits8),
338                16 => Ok(Self::Bits16),
339                24 => Ok(Self::Bits24),
340                32 => Ok(Self::Bits32),
341                _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
342            }
343        }
344    }
345
346    /// The multiple of MCLK to the sample rate.
347    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
348    pub enum MclkMultiple {
349        /// MCLK = sample rate * 128
350        M128,
351
352        /// MCLK = sample rate * 256
353        M256,
354
355        /// MCLK = sample rate * 384
356        M384,
357
358        /// MCLK = sample rate * 512
359        #[cfg(not(esp_idf_version_major = "4"))]
360        M512,
361    }
362
363    impl MclkMultiple {
364        /// Convert to the ESP-IDF SDK `i2s_mclk_multiple_t` representation.
365        #[inline(always)]
366        pub(super) fn as_sdk(&self) -> i2s_mclk_multiple_t {
367            match self {
368                Self::M128 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_128,
369                Self::M256 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_256,
370                Self::M384 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_384,
371                #[cfg(not(esp_idf_version_major = "4"))]
372                Self::M512 => i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_512,
373            }
374        }
375    }
376
377    impl From<MclkMultiple> for u32 {
378        #[inline(always)]
379        fn from(mclk_multiple: MclkMultiple) -> Self {
380            match mclk_multiple {
381                MclkMultiple::M128 => 128,
382                MclkMultiple::M256 => 256,
383                MclkMultiple::M384 => 384,
384                #[cfg(not(esp_idf_version_major = "4"))]
385                MclkMultiple::M512 => 512,
386            }
387        }
388    }
389
390    /// I2S channel operating role
391    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
392    pub enum Role {
393        /// Controller (master)
394        #[default]
395        Controller,
396
397        /// Target (slave)
398        Target,
399    }
400
401    /// I2S peripheral in controller (master) role, bclk and ws signal will be set to output.
402    #[cfg(not(esp_idf_version_major = "4"))]
403    const I2S_ROLE_CONTROLLER: i2s_role_t = 0;
404
405    /// I2S peripheral in target (slave) role, bclk and ws signal will be set to input.
406    #[cfg(not(esp_idf_version_major = "4"))]
407    const I2S_ROLE_TARGET: i2s_role_t = 1;
408
409    impl Role {
410        /// Convert to the ESP-IDF SDK `i2s_role_t` representation.
411        #[cfg(not(esp_idf_version_major = "4"))]
412        #[inline(always)]
413        pub(super) fn as_sdk(&self) -> i2s_role_t {
414            match self {
415                Self::Controller => I2S_ROLE_CONTROLLER,
416                Self::Target => I2S_ROLE_TARGET,
417            }
418        }
419
420        /// Convert to the ESP-IDF SDK `i2s_mode_t` representation.
421        #[cfg(esp_idf_version_major = "4")]
422        #[inline(always)]
423        pub(super) fn as_sdk(&self) -> i2s_mode_t {
424            match self {
425                Self::Controller => i2s_mode_t_I2S_MODE_MASTER,
426                Self::Target => i2s_mode_t_I2S_MODE_SLAVE,
427            }
428        }
429    }
430
431    /// The total slot bit width in one slot.
432    ///
433    /// This is not necessarily the number of data bits in one slot. A slot may have additional bits padded to fill out
434    /// the slot.
435    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
436    pub enum SlotBitWidth {
437        /// Slot bit width is automatically set to the data bit width.
438        #[default]
439        Auto,
440
441        /// Slot bit width is 8 bits.
442        Bits8,
443
444        /// Slot bit width is 16 bits.
445        Bits16,
446
447        /// Slot bit width is 24 bits.
448        Bits24,
449
450        /// Slot bit width is 32 bits.
451        Bits32,
452    }
453
454    #[cfg(not(esp_idf_version_major = "4"))]
455    type SlotBitWidthSdkType = i2s_slot_bit_width_t;
456
457    #[cfg(esp_idf_version_major = "4")]
458    type SlotBitWidthSdkType = i2s_bits_per_chan_t;
459
460    impl SlotBitWidth {
461        /// Convert this to the ESP-IDF SDK `i2s_slot_bit_width_t`/`i2s_bits_per_chan_t` representation.
462        #[inline(always)]
463        pub(super) fn as_sdk(&self) -> SlotBitWidthSdkType {
464            match self {
465                Self::Auto => 0,
466                Self::Bits8 => 8,
467                Self::Bits16 => 16,
468                Self::Bits24 => 24,
469                Self::Bits32 => 32,
470            }
471        }
472    }
473
474    impl TryFrom<u32> for SlotBitWidth {
475        type Error = EspError;
476
477        fn try_from(value: u32) -> Result<Self, Self::Error> {
478            match value {
479                0 => Ok(Self::Auto),
480                8 => Ok(Self::Bits8),
481                16 => Ok(Self::Bits16),
482                24 => Ok(Self::Bits24),
483                32 => Ok(Self::Bits32),
484                _ => Err(EspError::from(ESP_ERR_INVALID_ARG).unwrap()),
485            }
486        }
487    }
488
489    /// I2S channel slot mode.
490    ///
491    /// See the documentation for the mode of operation to see how this affects the data layout:
492    /// * [PDM Rx][PdmRxSlotConfig]
493    /// * [PDM Tx][PdmTxSlotConfig]
494    /// * [Standard Rx/Tx][StdSlotConfig]
495    /// * [TDM Rx/Tx][TdmSlotConfig]
496    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
497    pub enum SlotMode {
498        /// Mono mode:
499        /// * When transmitting, transmit the same data in all slots.
500        /// * When receiving, only receive data from the first slot.
501        Mono,
502
503        /// Stereo mode:
504        /// * When transmitting, transmit different data in each slot.
505        /// * When receiving, receive data from all slots.
506        #[default]
507        Stereo,
508    }
509
510    impl SlotMode {
511        /// Convert this to the ESP-IDF SDK `i2s_slot_mode_t` representation.
512        #[cfg(not(esp_idf_version_major = "4"))]
513        #[inline(always)]
514        pub(super) fn as_sdk(&self) -> i2s_slot_mode_t {
515            match self {
516                Self::Mono => 1,
517                Self::Stereo => 2,
518            }
519        }
520    }
521}
522
523/// Trait implemented by I2S peripherals to obtain their port number.
524pub trait I2s: Send + sealed::Sealed {
525    /// Return the port number for the peripheral.
526    fn port() -> i2s_port_t;
527}
528
529mod sealed {
530    pub trait Sealed {}
531
532    impl Sealed for super::I2S0<'_> {}
533    #[cfg(any(esp32, esp32s3))]
534    impl Sealed for super::I2S1<'_> {}
535}
536
537pub trait I2sPort {
538    /// Returns the I2S port number of this driver.
539    fn port(&self) -> i2s_port_t;
540}
541
542/// Marker trait indicating that a driver supports receiving data via the [`I2sRx`] trait.
543pub trait I2sRxSupported {}
544
545/// Concrete implementation of [`I2sRxSupported`] for use in clients.
546///
547/// Example usage:
548/// ```
549/// use esp_idf_hal::gpio::*;
550/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
551/// use esp_idf_hal::i2s::{I2sDriver, I2sRx};
552/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
553/// let peripherals = Peripherals::take().unwrap();
554/// let bclk = peripherals.pins.gpio1;
555/// let din = peripherals.pins.gpio4;
556/// let mclk = AnyIOPin::none();
557/// let ws = peripherals.pins.gpio2;
558/// let i2s = I2sDriver::<I2sRx>::new_std_rx(peripherals.i2s0, &std_config, bclk, din, mclk, ws).unwrap();
559/// ```
560pub struct I2sRx {}
561impl I2sRxSupported for I2sRx {}
562
563/// Marker trait indicating that a driver supports transmitting data via the [`I2sTx`] trait.
564pub trait I2sTxSupported {}
565
566/// Concrete implementation of [`I2sTxSupported`] for use in clients.
567///
568/// Example usage:
569/// ```
570/// use esp_idf_hal::gpio::*;
571/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
572/// use esp_idf_hal::i2s::{I2sDriver, I2sTx};
573/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
574/// let peripherals = Peripherals::take().unwrap();
575/// let bclk = peripherals.pins.gpio1;
576/// let dout = peripherals.pins.gpio6;
577/// let mclk = AnyIOPin::none();
578/// let ws = peripherals.pins.gpio2;
579/// let i2s = I2sDriver::<I2sTx>::new_std_tx(peripherals.i2s0, &std_config, bclk, dout, mclk, ws).unwrap();
580/// ```
581pub struct I2sTx {}
582impl I2sTxSupported for I2sTx {}
583
584/// Concrete implementation of both [`I2sRxSupported`] and [`I2sTxSupported`] for use in clients.
585///
586/// Example usage:
587/// ```
588/// use esp_idf_hal::{gpio::*, peripherals::Peripherals};
589/// use esp_idf_hal::i2s::{config::{StdConfig, DataBitWidth}};
590/// use esp_idf_hal::i2s::{I2sDriver, I2sBiDir};
591/// let std_config = StdConfig::philips(48000, DataBitWidth::Bits16);
592/// let peripherals = Peripherals::take().unwrap();
593/// let bclk = peripherals.pins.gpio1;
594/// let din = peripherals.pins.gpio4;
595/// let dout = peripherals.pins.gpio6;
596/// let mclk = AnyIOPin::none();
597/// let ws = peripherals.pins.gpio2;
598/// let i2s = I2sDriver::<I2sBiDir>::new_std_bidir(peripherals.i2s0, &std_config, bclk, din, dout, mclk, ws).unwrap();
599/// ```
600pub struct I2sBiDir {}
601impl I2sRxSupported for I2sBiDir {}
602impl I2sTxSupported for I2sBiDir {}
603
604/// Reference for I2S driver
605pub struct I2sDriverRef<'d, Dir>(NonNull<I2sDriver<'d, Dir>>);
606
607impl<'d, Dir> Deref for I2sDriverRef<'d, Dir> {
608    type Target = I2sDriver<'d, Dir>;
609
610    fn deref(&self) -> &Self::Target {
611        unsafe { self.0.as_ref() }
612    }
613}
614
615impl<Dir> DerefMut for I2sDriverRef<'_, Dir> {
616    fn deref_mut(&mut self) -> &mut Self::Target {
617        unsafe { self.0.as_mut() }
618    }
619}
620
621/// Inter-IC Sound (I2S) driver.
622pub struct I2sDriver<'d, Dir> {
623    /// The Rx channel, possibly null.
624    #[cfg(not(esp_idf_version_major = "4"))]
625    rx_handle: i2s_chan_handle_t,
626
627    /// The Tx channel, possibly null.
628    #[cfg(not(esp_idf_version_major = "4"))]
629    tx_handle: i2s_chan_handle_t,
630
631    /// The I2S peripheral number. Either 0 (all devices) or 1 (ESP32 and ESP32-S3 only).
632    port: u8,
633
634    /// Driver lifetime -- mimics the lifetime of the peripheral.
635    _p: PhantomData<&'d ()>,
636
637    /// Directionality -- mimics the directionality of the peripheral.
638    _dir: PhantomData<Dir>,
639}
640
641impl<Dir> I2sDriver<'_, Dir> {
642    /// Create a new standard mode driver for the given I2S peripheral with both the receive and transmit channels open.
643    #[cfg(not(esp_idf_version_major = "4"))]
644    fn internal_new<I2S: I2s>(
645        config: &i2s_chan_config_t,
646        rx: bool,
647        tx: bool,
648    ) -> Result<Self, EspError> {
649        let port = I2S::port();
650
651        let mut rx_handle: i2s_chan_handle_t = null_mut();
652        let mut tx_handle: i2s_chan_handle_t = null_mut();
653
654        unsafe {
655            esp!(i2s_new_channel(
656                config,
657                if tx {
658                    &mut tx_handle as _
659                } else {
660                    core::ptr::null_mut()
661                },
662                if rx {
663                    &mut rx_handle as _
664                } else {
665                    core::ptr::null_mut()
666                },
667            ))?
668        };
669
670        let mut this = Self {
671            port: port as u8,
672            rx_handle,
673            tx_handle,
674            _p: PhantomData,
675            _dir: PhantomData,
676        };
677
678        this.subscribe_channel(this.rx_handle)?;
679        this.subscribe_channel(this.tx_handle)?;
680
681        Ok(this)
682    }
683
684    #[cfg(esp_idf_version_major = "4")]
685    #[allow(clippy::too_many_arguments)]
686    pub fn internal_new<I2S: I2s>(config: &i2s_config_t) -> Result<Self, EspError> {
687        let port = I2S::port();
688
689        unsafe {
690            esp!(i2s_driver_install(port, config, 0, core::ptr::null_mut()))?;
691        }
692
693        Ok(Self {
694            port: port as u8,
695            _p: PhantomData,
696            _dir: PhantomData,
697        })
698    }
699
700    #[cfg(not(esp_idf_version_major = "4"))]
701    fn subscribe_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
702        if !handle.is_null() {
703            let callbacks = i2s_event_callbacks_t {
704                on_recv: Some(dispatch_recv),
705                on_recv_q_ovf: Some(dispatch_recv),
706                on_sent: Some(dispatch_send),
707                on_send_q_ovf: Some(dispatch_send),
708            };
709
710            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
711            esp!(unsafe {
712                i2s_channel_register_event_callback(
713                    handle,
714                    &callbacks,
715                    self.port as u32 as *mut core::ffi::c_void,
716                )
717            })?;
718        }
719
720        Ok(())
721    }
722
723    #[cfg(not(esp_idf_version_major = "4"))]
724    fn unsubscribe_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
725        if !handle.is_null() {
726            let callbacks = i2s_event_callbacks_t {
727                on_recv: None,
728                on_recv_q_ovf: None,
729                on_sent: None,
730                on_send_q_ovf: None,
731            };
732
733            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
734            esp!(unsafe {
735                i2s_channel_register_event_callback(
736                    handle,
737                    &callbacks,
738                    self.port as u32 as *mut core::ffi::c_void,
739                )
740            })?;
741        }
742
743        Ok(())
744    }
745
746    #[cfg(not(esp_idf_version_major = "4"))]
747    fn del_channel(&mut self, handle: i2s_chan_handle_t) -> Result<(), EspError> {
748        if !handle.is_null() {
749            let callbacks = i2s_event_callbacks_t {
750                on_recv: None,
751                on_recv_q_ovf: None,
752                on_sent: None,
753                on_send_q_ovf: None,
754            };
755
756            // Safety: chan_handle is a valid pointer to an i2s_chan_handle_t and callbacks is initialized.
757            esp!(unsafe {
758                i2s_channel_register_event_callback(handle, &callbacks, core::ptr::null_mut())
759            })?;
760
761            // Safety: chan_handle is a valid, non-null i2s_chan_handle_t.
762            esp!(unsafe { i2s_del_channel(handle) })?;
763        }
764
765        Ok(())
766    }
767
768    fn remap_result(
769        result: Result<(), EspError>,
770        bytes_processed: usize,
771    ) -> Result<usize, EspError> {
772        match result {
773            Ok(_) => Ok(bytes_processed),
774            Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT && bytes_processed > 0 => {
775                Ok(bytes_processed)
776            }
777            Err(err) => Err(err),
778        }
779    }
780
781    /// Borrow the I2S driver by a reference
782    pub fn as_ref(&mut self) -> I2sDriverRef<'_, Dir> {
783        I2sDriverRef(unsafe { NonNull::new_unchecked(self) })
784    }
785}
786
787/// Functions for receive channels.
788impl<Dir> I2sDriver<'_, Dir>
789where
790    Dir: I2sRxSupported,
791{
792    /// Enable the I2S receive channel.
793    ///
794    /// # Note
795    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
796    /// constructor, or disabled from the `RUNNING` state via [`rx_disable()`][I2sDriver::rx_disable]. The channel
797    /// will enter the `RUNNING` state if it is enabled successfully.
798    ///
799    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
800    /// this is a controller. MCLK will be generated once initialization is finished.
801    ///
802    /// # Errors
803    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
804    #[cfg(esp_idf_version_major = "4")]
805    pub fn rx_enable(&mut self) -> Result<(), EspError> {
806        unsafe { esp!(i2s_start(self.port as _)) }
807    }
808
809    /// Enable the I2S receive channel.
810    ///
811    /// # Note
812    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
813    /// constructor, or disabled from the `RUNNING` state via [`rx_enable()`][I2sRxChannel::rx_disable]. The channel
814    /// will enter the `RUNNING` state if it is enabled successfully.
815    ///
816    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
817    /// this is a controller. MCLK will be generated once initialization is finished.
818    ///
819    /// # Errors
820    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
821    #[cfg(not(esp_idf_version_major = "4"))]
822    pub fn rx_enable(&mut self) -> Result<(), EspError> {
823        unsafe { esp!(i2s_channel_enable(self.rx_handle)) }
824    }
825
826    /// Disable the I2S receive channel.
827    ///
828    /// # Note
829    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
830    /// via a call to [`rx_enable()`][I2sRxChannel::rx_enable]. The channel will enter the `READY` state if it is
831    /// disabled successfully.
832    ///
833    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
834    /// generated if this is a controller. MCLK will continue to be generated.
835    ///
836    /// # Errors
837    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
838    #[cfg(esp_idf_version_major = "4")]
839    pub fn rx_disable(&mut self) -> Result<(), EspError> {
840        unsafe { esp!(i2s_stop(self.port as _)) }
841    }
842
843    /// Disable the I2S receive channel.
844    ///
845    /// # Note
846    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
847    /// via a call to [`rx_enable()`][I2sRxChannel::rx_enable]. The channel will enter the `READY` state if it is
848    /// disabled successfully.
849    ///
850    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
851    /// generated if this is a controller. MCLK will continue to be generated.
852    ///
853    /// # Errors
854    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
855    #[cfg(not(esp_idf_version_major = "4"))]
856    pub fn rx_disable(&mut self) -> Result<(), EspError> {
857        unsafe { esp!(i2s_channel_disable(self.rx_handle)) }
858    }
859
860    /// Read data from the channel asynchronously.
861    ///
862    /// This may be called only when the channel is in the `RUNNING` state.
863    ///
864    /// # Returns
865    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
866    #[cfg(not(esp_idf_version_major = "4"))]
867    pub async fn read_async(&mut self, buffer: &mut [u8]) -> Result<usize, EspError> {
868        loop {
869            match self.read(buffer, crate::delay::NON_BLOCK) {
870                Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
871                    RECV_NOTIFIER[self.port as usize].wait().await;
872                }
873                other => break other,
874            }
875        }
876    }
877
878    /// Read data from the channel.
879    ///
880    /// This may be called only when the channel is in the `RUNNING` state.
881    ///
882    /// # Returns
883    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
884    #[cfg(esp_idf_version_major = "4")]
885    pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
886        if buffer.is_empty() {
887            Ok(0)
888        } else {
889            let mut bytes_read: usize = 0;
890
891            Self::remap_result(
892                unsafe {
893                    esp!(i2s_read(
894                        self.port as _,
895                        buffer.as_mut_ptr() as *mut c_void,
896                        buffer.len(),
897                        &mut bytes_read,
898                        crate::delay::TickType(timeout).as_millis_u32(),
899                    ))
900                },
901                bytes_read,
902            )
903        }
904    }
905
906    /// Read data from the channel.
907    ///
908    /// This may be called only when the channel is in the `RUNNING` state.
909    ///
910    /// # Returns
911    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
912    #[cfg(not(esp_idf_version_major = "4"))]
913    pub fn read(&mut self, buffer: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
914        if buffer.is_empty() {
915            Ok(0)
916        } else {
917            let mut bytes_read: usize = 0;
918
919            Self::remap_result(
920                unsafe {
921                    esp!(i2s_channel_read(
922                        self.rx_handle,
923                        buffer.as_mut_ptr() as *mut c_void,
924                        buffer.len(),
925                        &mut bytes_read,
926                        crate::delay::TickType(timeout).as_millis_u32(),
927                    ))
928                },
929                bytes_read,
930            )
931        }
932    }
933
934    /// Read data from the channel into an uninitalized buffer asynchronously.
935    ///
936    /// This may be called only when the channel is in the `RUNNING` state.
937    ///
938    /// # Returns
939    /// This returns the number of bytes read, or an [EspError] if an error occurred.
940    ///
941    /// # Safety
942    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
943    #[cfg(not(esp_idf_version_major = "4"))]
944    pub async fn read_uninit_async(
945        &mut self,
946        buffer: &mut [MaybeUninit<u8>],
947    ) -> Result<usize, EspError> {
948        loop {
949            match self.read_uninit(buffer, crate::delay::NON_BLOCK) {
950                Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
951                    RECV_NOTIFIER[self.port as usize].wait().await;
952                }
953                other => break other,
954            }
955        }
956    }
957
958    /// Read data from the channel into an uninitalized buffer.
959    ///
960    /// This may be called only when the channel is in the `RUNNING` state.
961    ///
962    /// # Returns
963    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
964    ///
965    /// # Safety
966    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
967    #[cfg(esp_idf_version_major = "4")]
968    pub fn read_uninit(
969        &mut self,
970        buffer: &mut [MaybeUninit<u8>],
971        timeout: TickType_t,
972    ) -> Result<usize, EspError> {
973        if buffer.is_empty() {
974            Ok(0)
975        } else {
976            let mut bytes_read: usize = 0;
977
978            Self::remap_result(
979                unsafe {
980                    esp!(i2s_read(
981                        self.port as _,
982                        buffer.as_mut_ptr() as *mut c_void,
983                        buffer.len(),
984                        &mut bytes_read,
985                        crate::delay::TickType(timeout).as_millis_u32(),
986                    ))
987                },
988                bytes_read,
989            )
990        }
991    }
992
993    /// Read data from the channel into an uninitalized buffer.
994    ///
995    /// This may be called only when the channel is in the `RUNNING` state.
996    ///
997    /// # Returns
998    /// This returns the number of bytes read, or an [`EspError`] if an error occurred.
999    ///
1000    /// # Safety
1001    /// Upon a successful return with `Ok(n_read)`, `buffer[..n_read]` will be initialized.
1002    #[cfg(not(esp_idf_version_major = "4"))]
1003    pub fn read_uninit(
1004        &mut self,
1005        buffer: &mut [MaybeUninit<u8>],
1006        timeout: TickType_t,
1007    ) -> Result<usize, EspError> {
1008        if buffer.is_empty() {
1009            Ok(0)
1010        } else {
1011            let mut bytes_read: usize = 0;
1012
1013            Self::remap_result(
1014                unsafe {
1015                    esp!(i2s_channel_read(
1016                        self.rx_handle,
1017                        buffer.as_mut_ptr() as *mut c_void,
1018                        buffer.len(),
1019                        &mut bytes_read,
1020                        crate::delay::TickType(timeout).as_millis_u32(),
1021                    ))
1022                },
1023                bytes_read,
1024            )
1025        }
1026    }
1027}
1028
1029/// Functions for transmit channels.
1030impl<Dir> I2sDriver<'_, Dir>
1031where
1032    Dir: I2sTxSupported,
1033{
1034    /// Enable the I2S transmit channel.
1035    ///
1036    /// # Note
1037    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
1038    /// constructor, or disabled from the `RUNNING` state via [`tx_disable()`][I2sTxChannel::tx_disable]. The channel
1039    /// will enter the `RUNNING` state if it is enabled successfully.
1040    ///
1041    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
1042    /// this is a controller. MCLK will be generated once initialization is finished.
1043    ///
1044    /// # Errors
1045    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
1046    #[cfg(esp_idf_version_major = "4")]
1047    pub fn tx_enable(&mut self) -> Result<(), EspError> {
1048        unsafe { esp!(i2s_start(self.port as _)) }
1049    }
1050
1051    /// Enable the I2S transmit channel.
1052    ///
1053    /// # Note
1054    /// This can only be called when the channel is in the `READY` state: initialized but not yet started from a driver
1055    /// constructor, or disabled from the `RUNNING` state via [`tx_disable()`][I2sTxChannel::tx_disable]. The channel
1056    /// will enter the `RUNNING` state if it is enabled successfully.
1057    ///
1058    /// Enabling the channel will start I2S communications on the hardware. BCLK and WS signals will be generated if
1059    /// this is a controller. MCLK will be generated once initialization is finished.
1060    ///
1061    /// # Errors
1062    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `READY` state.
1063    #[cfg(not(esp_idf_version_major = "4"))]
1064    pub fn tx_enable(&mut self) -> Result<(), EspError> {
1065        unsafe { esp!(i2s_channel_enable(self.tx_handle)) }
1066    }
1067
1068    /// Disable the I2S transmit channel.
1069    ///
1070    /// # Note
1071    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
1072    /// via a call to [`tx_enable()`][I2sTxChannel::tx_enable]. The channel will enter the `READY` state if it is
1073    /// disabled successfully.
1074    ///
1075    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
1076    /// generated if this is a controller. MCLK will continue to be generated.
1077    ///
1078    /// # Errors
1079    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
1080    #[cfg(esp_idf_version_major = "4")]
1081    pub fn tx_disable(&mut self) -> Result<(), EspError> {
1082        unsafe { esp!(i2s_stop(self.port())) }
1083    }
1084
1085    /// Disable the I2S transmit channel.
1086    ///
1087    /// # Note
1088    /// This can only be called when the channel is in the `RUNNING` state: the channel has been previously enabled
1089    /// via a call to [`tx_enable()`][I2sTxChannel::tx_enable]. The channel will enter the `READY` state if it is disabled
1090    /// successfully.
1091    ///
1092    /// Disabling the channel will stop I2S communications on the hardware. BCLK and WS signals will stop being
1093    /// generated if this is a controller. MCLK will continue to be generated.
1094    ///
1095    /// # Errors
1096    /// This will return an [`EspError`] with `ESP_ERR_INVALID_STATE` if the channel is not in the `RUNNING` state.
1097    #[cfg(not(esp_idf_version_major = "4"))]
1098    pub fn tx_disable(&mut self) -> Result<(), EspError> {
1099        unsafe { esp!(i2s_channel_disable(self.tx_handle)) }
1100    }
1101
1102    /// Preload data into the transmit channel DMA buffer.
1103    ///
1104    /// This may be called only when the channel is in the `READY` state: initialized but not yet started.
1105    ///
1106    /// This is used to preload data into the DMA buffer so that valid data can be transmitted immediately after the
1107    /// channel is enabled via [`tx_enable()`][I2sTxChannel::tx_enable]. If this function is not called before enabling the channel,
1108    /// empty data will be transmitted.
1109    ///
1110    /// This function can be called multiple times before enabling the channel. Additional calls will concatenate the
1111    /// data to the end of the buffer until the buffer is full.
1112    ///
1113    /// # Returns
1114    /// This returns the number of bytes that have been loaded into the buffer. If this is less than the length of
1115    /// the data provided, the buffer is full and no more data can be loaded.
1116    #[cfg(all(
1117        not(esp_idf_version_major = "4"),
1118        not(all(esp_idf_version_major = "5", esp_idf_version_minor = "0"))
1119    ))]
1120    pub fn preload_data(&mut self, data: &[u8]) -> Result<usize, EspError> {
1121        let mut bytes_loaded: usize = 0;
1122
1123        unsafe {
1124            esp!(esp_idf_sys::i2s_channel_preload_data(
1125                self.tx_handle,
1126                data.as_ptr() as *const c_void,
1127                data.len(),
1128                &mut bytes_loaded as *mut usize
1129            ))?;
1130        }
1131
1132        Ok(bytes_loaded)
1133    }
1134
1135    /// Write data to the channel asynchronously.
1136    ///
1137    /// This may be called only when the channel is in the `RUNNING` state.
1138    ///
1139    /// # Returns
1140    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1141    #[cfg(not(esp_idf_version_major = "4"))]
1142    pub async fn write_async(&mut self, data: &[u8]) -> Result<usize, EspError> {
1143        loop {
1144            match self.write(data, crate::delay::NON_BLOCK) {
1145                Err(err) if err.code() == esp_idf_sys::ESP_ERR_TIMEOUT => {
1146                    SEND_NOTIFIER[self.port as usize].wait().await;
1147                }
1148                other => break other,
1149            }
1150        }
1151    }
1152
1153    /// Write all data to the channel asynchronously.
1154    ///
1155    /// This may be called only when the channel is in the `RUNNING` state.
1156    #[cfg(not(esp_idf_version_major = "4"))]
1157    pub async fn write_all_async(&mut self, data: &[u8]) -> Result<(), EspError> {
1158        let mut offset = 0;
1159
1160        while offset < data.len() {
1161            offset += self.write_async(&data[offset..]).await?;
1162        }
1163
1164        Ok(())
1165    }
1166
1167    /// Write data to the channel.
1168    ///
1169    /// This may be called only when the channel is in the `RUNNING` state.
1170    ///
1171    /// # Returns
1172    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1173    #[cfg(esp_idf_version_major = "4")]
1174    pub fn write(&mut self, data: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
1175        if data.is_empty() {
1176            Ok(0)
1177        } else {
1178            let mut bytes_written: usize = 0;
1179
1180            Self::remap_result(
1181                unsafe {
1182                    esp!(i2s_write(
1183                        self.port(),
1184                        data.as_ptr() as *mut c_void,
1185                        data.len(),
1186                        &mut bytes_written,
1187                        crate::delay::TickType(timeout).as_millis_u32(),
1188                    ))
1189                },
1190                bytes_written,
1191            )
1192        }
1193    }
1194
1195    /// Write data to the channel.
1196    ///
1197    /// This may be called only when the channel is in the `RUNNING` state.
1198    ///
1199    /// # Returns
1200    /// This returns the number of bytes sent. This may be less than the length of the data provided.
1201    #[cfg(not(esp_idf_version_major = "4"))]
1202    pub fn write(&mut self, data: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
1203        if data.is_empty() {
1204            Ok(0)
1205        } else {
1206            let mut bytes_written: usize = 0;
1207
1208            Self::remap_result(
1209                unsafe {
1210                    esp!(i2s_channel_write(
1211                        self.tx_handle,
1212                        data.as_ptr() as *mut c_void,
1213                        data.len(),
1214                        &mut bytes_written,
1215                        crate::delay::TickType(timeout).as_millis_u32(),
1216                    ))
1217                },
1218                bytes_written,
1219            )
1220        }
1221    }
1222
1223    /// Write all data to the channel.
1224    ///
1225    /// This may be called only when the channel is in the `RUNNING` state.
1226    pub fn write_all(&mut self, data: &[u8], timeout: TickType_t) -> Result<(), EspError> {
1227        let mut offset = 0;
1228
1229        while offset < data.len() {
1230            offset += self.write(&data[offset..], timeout)?;
1231        }
1232
1233        Ok(())
1234    }
1235}
1236
1237impl I2sDriver<'_, I2sBiDir> {
1238    /// Split the bidirectional I2S driver into two parts (Rx, Tx)
1239    ///
1240    /// # Safety
1241    /// It is safe to use the two parts separately
1242    /// - esp-idf guarantees thread safety
1243    /// - esp-idf-hal guarantees asynchronous safety
1244    pub fn split(&mut self) -> (I2sDriverRef<'_, I2sRx>, I2sDriverRef<'_, I2sTx>) {
1245        // Safe because self cannot be null
1246        let this = unsafe { NonNull::new_unchecked(self) };
1247
1248        (I2sDriverRef(this.cast()), I2sDriverRef(this.cast()))
1249    }
1250}
1251
1252impl<Dir> Drop for I2sDriver<'_, Dir> {
1253    fn drop(&mut self) {
1254        #[cfg(esp_idf_version_major = "4")]
1255        {
1256            let _ = unsafe { esp!(i2s_stop(self.port as _)) };
1257
1258            esp!(unsafe { i2s_driver_uninstall(self.port as _) }).unwrap();
1259        }
1260
1261        #[cfg(not(esp_idf_version_major = "4"))]
1262        {
1263            if !self.rx_handle.is_null() {
1264                let _ = unsafe { esp!(i2s_channel_disable(self.rx_handle)) };
1265            }
1266
1267            if !self.tx_handle.is_null() {
1268                let _ = unsafe { esp!(i2s_channel_disable(self.tx_handle)) };
1269            }
1270
1271            self.unsubscribe_channel(self.rx_handle).unwrap();
1272            self.unsubscribe_channel(self.tx_handle).unwrap();
1273
1274            if !self.rx_handle.is_null() {
1275                self.del_channel(self.rx_handle).unwrap();
1276            }
1277
1278            if !self.tx_handle.is_null() {
1279                self.del_channel(self.tx_handle).unwrap();
1280            }
1281
1282            SEND_NOTIFIER[self.port as usize].reset();
1283            RECV_NOTIFIER[self.port as usize].reset();
1284        }
1285    }
1286}
1287
1288unsafe impl<Dir> Send for I2sDriver<'_, Dir> {}
1289
1290impl<Dir> I2sPort for I2sDriver<'_, Dir> {
1291    fn port(&self) -> i2s_port_t {
1292        self.port as _
1293    }
1294}
1295
1296impl<Dir> embedded_io::ErrorType for I2sDriver<'_, Dir> {
1297    type Error = EspIOError;
1298}
1299
1300impl<Dir> embedded_io::Read for I2sDriver<'_, Dir>
1301where
1302    Dir: I2sRxSupported,
1303{
1304    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1305        self.read(buf, delay::BLOCK).map_err(EspIOError)
1306    }
1307}
1308
1309impl<Dir> embedded_io::Write for I2sDriver<'_, Dir>
1310where
1311    Dir: I2sTxSupported,
1312{
1313    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1314        self.write(buf, delay::BLOCK).map_err(EspIOError)
1315    }
1316
1317    fn flush(&mut self) -> Result<(), Self::Error> {
1318        Ok(())
1319    }
1320}
1321
1322#[cfg(not(esp_idf_version_major = "4"))]
1323impl<Dir> embedded_io_async::Read for I2sDriver<'_, Dir>
1324where
1325    Dir: I2sRxSupported,
1326{
1327    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
1328        self.read_async(buf).await.map_err(EspIOError)
1329    }
1330}
1331
1332#[cfg(not(esp_idf_version_major = "4"))]
1333impl<Dir> embedded_io_async::Write for I2sDriver<'_, Dir>
1334where
1335    Dir: I2sTxSupported,
1336{
1337    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1338        self.write_async(buf).await.map_err(EspIOError)
1339    }
1340
1341    async fn flush(&mut self) -> Result<(), Self::Error> {
1342        Ok(())
1343    }
1344}
1345
1346/// C-facing ISR dispatcher for on_send_* callbacks.
1347#[cfg(not(esp_idf_version_major = "4"))]
1348unsafe extern "C" fn dispatch_send(
1349    _handle: i2s_chan_handle_t,
1350    _raw_event: *mut i2s_event_data_t,
1351    user_ctx: *mut c_void,
1352) -> bool {
1353    let port = user_ctx as u32 as i2s_port_t;
1354
1355    SEND_NOTIFIER[port as usize].notify_lsb()
1356}
1357
1358/// C-facing ISR dispatcher for on_recv_* callbacks.
1359#[cfg(not(esp_idf_version_major = "4"))]
1360unsafe extern "C" fn dispatch_recv(
1361    _handle: i2s_chan_handle_t,
1362    _raw_event: *mut i2s_event_data_t,
1363    user_ctx: *mut c_void,
1364) -> bool {
1365    let port = user_ctx as u32 as i2s_port_t;
1366
1367    RECV_NOTIFIER[port as usize].notify_lsb()
1368}
1369
1370macro_rules! impl_i2s {
1371    ($i2s:ident: $port:expr) => {
1372        crate::impl_peripheral!($i2s);
1373
1374        impl I2s for $i2s<'_> {
1375            #[inline(always)]
1376            fn port() -> i2s_port_t {
1377                $port
1378            }
1379        }
1380    };
1381}
1382
1383impl_i2s!(I2S0: 0);
1384#[cfg(any(esp32, esp32s3))]
1385impl_i2s!(I2S1: 1);
1386
1387#[cfg(not(esp_idf_version_major = "4"))]
1388#[cfg(not(any(esp32, esp32s3)))]
1389static SEND_NOTIFIER: [HalIsrNotification; 1] = [HalIsrNotification::new()];
1390#[cfg(not(esp_idf_version_major = "4"))]
1391#[cfg(not(any(esp32, esp32s3)))]
1392static RECV_NOTIFIER: [HalIsrNotification; 1] = [HalIsrNotification::new()];
1393
1394#[cfg(not(esp_idf_version_major = "4"))]
1395#[cfg(any(esp32, esp32s3))]
1396static SEND_NOTIFIER: [HalIsrNotification; 2] =
1397    [HalIsrNotification::new(), HalIsrNotification::new()];
1398#[cfg(not(esp_idf_version_major = "4"))]
1399#[cfg(any(esp32, esp32s3))]
1400static RECV_NOTIFIER: [HalIsrNotification; 2] =
1401    [HalIsrNotification::new(), HalIsrNotification::new()];