1use core::ffi::c_void;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6use core::ops::{Deref, DerefMut};
7use core::ptr::NonNull;
8
9use esp_idf_sys::{esp, EspError, TickType_t};
10
11#[cfg(esp_idf_version_major = "5")]
12use esp_idf_sys::i2s_port_t;
13
14#[cfg(not(esp_idf_version_major = "4"))]
15use {
16 core::ptr::null_mut,
17 esp_idf_sys::{
18 i2s_chan_config_t, i2s_chan_handle_t, i2s_channel_disable, i2s_channel_enable,
19 i2s_channel_read, i2s_channel_register_event_callback, i2s_channel_write, i2s_del_channel,
20 i2s_event_callbacks_t, i2s_event_data_t, i2s_new_channel,
21 },
22};
23
24#[cfg(esp_idf_version_major = "4")]
25use esp_idf_sys::{
26 i2s_config_t, i2s_driver_install, i2s_driver_uninstall, i2s_read, i2s_start, i2s_stop,
27 i2s_write,
28};
29
30#[cfg(not(esp_idf_version_major = "4"))]
31use crate::interrupt::asynch::HalIsrNotification;
32use crate::{delay, io::EspIOError};
33
34#[cfg(any(
37 all(
38 not(esp_idf_version_major = "4"),
39 any(esp_idf_soc_i2s_supports_pdm_rx, esp_idf_soc_i2s_supports_pdm_tx)
40 ),
41 all(esp_idf_version_major = "4", any(esp32, esp32s3, esp32c3, esp32c6))
42))]
43mod pdm;
44
45mod std;
46
47#[cfg(any(
48 all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm),
49 all(esp_idf_version_major = "4", any(esp32s3, esp32c3, esp32c6))
50))]
51mod tdm;
52
53#[cfg(esp_idf_version_at_least_6_0_0)]
54#[allow(non_camel_case_types)]
55type i2s_port_t = i32;
56
57pub type I2sConfig = config::Config;
59
60pub mod config {
62 #[cfg(any(
63 all(
64 not(esp_idf_version_major = "4"),
65 any(esp_idf_soc_i2s_supports_pdm_rx, esp_idf_soc_i2s_supports_pdm_tx)
66 ),
67 all(esp_idf_version_major = "4", any(esp32, esp32s3, esp32c3, esp32c6))
68 ))]
69 pub use super::pdm::config::*;
70
71 pub use super::std::config::*;
72
73 #[cfg(any(
74 all(not(esp_idf_version_major = "4"), esp_idf_soc_i2s_supports_tdm),
75 all(esp_idf_version_major = "4", any(esp32s3, esp32c3, esp32c6))
76 ))]
77 pub use super::tdm::config::*;
78
79 use esp_idf_sys::{
80 i2s_mclk_multiple_t, i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_128,
81 i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_256, i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_384,
82 EspError, ESP_ERR_INVALID_ARG,
83 };
84
85 #[cfg(esp_idf_version_major = "5")]
86 use esp_idf_sys::i2s_port_t;
87 #[cfg(not(esp_idf_version_major = "4"))]
88 use esp_idf_sys::{
89 i2s_chan_config_t, i2s_clock_src_t, i2s_data_bit_width_t,
90 i2s_mclk_multiple_t_I2S_MCLK_MULTIPLE_512, i2s_role_t, i2s_slot_bit_width_t,
91 i2s_slot_mode_t,
92 };
93
94 #[cfg(esp_idf_version_major = "4")]
95 use esp_idf_sys::{
96 i2s_bits_per_chan_t, i2s_bits_per_sample_t, i2s_mode_t, i2s_mode_t_I2S_MODE_MASTER,
97 i2s_mode_t_I2S_MODE_SLAVE,
98 };
99
100 #[cfg(not(any(
101 esp_idf_version_major = "4",
102 all(esp_idf_version_major = "5", esp_idf_version_minor = "0"),
103 all(esp_idf_version_major = "5", esp_idf_version_minor = "1"),
104 all(esp_idf_version_major = "5", esp_idf_version_minor = "2"),
105 )))] use esp_idf_sys::i2s_chan_config_t__bindgen_ty_1; #[cfg(esp_idf_version_at_least_6_0_0)]
109 #[allow(non_camel_case_types)]
110 type i2s_port_t = i32;
111
112 pub const DEFAULT_DMA_BUFFER_COUNT: u32 = 6;
114
115 pub const DEFAULT_FRAMES_PER_DMA_BUFFER: u32 = 240;
117
118 #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
120 pub enum ClockSource {
121 #[cfg(not(any(esp32h2, esp32c2)))]
123 #[default]
124 Pll160M,
125
126 #[cfg(esp32c2)]
128 #[default]
129 Pll60M,
130
131 #[cfg(esp32h2)]
133 #[default]
134 Pll64M,
135
136 #[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 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
181 pub struct Config {
182 pub(super) role: Role,
184
185 pub(super) dma_buffer_count: u32,
187
188 pub(super) frames_per_buffer: u32,
190
191 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 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 #[must_use]
216 #[inline(always)]
217 pub fn role(mut self, role: Role) -> Self {
218 self.role = role;
219 self
220 }
221
222 #[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 #[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 #[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 #[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 #[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 )))] __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 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
280 pub enum DataBitWidth {
281 Bits8,
283
284 Bits16,
286
287 Bits24,
289
290 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 #[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 #[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 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
348 pub enum MclkMultiple {
349 M128,
351
352 M256,
354
355 M384,
357
358 #[cfg(not(esp_idf_version_major = "4"))]
360 M512,
361 }
362
363 impl MclkMultiple {
364 #[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 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
392 pub enum Role {
393 #[default]
395 Controller,
396
397 Target,
399 }
400
401 #[cfg(not(esp_idf_version_major = "4"))]
403 const I2S_ROLE_CONTROLLER: i2s_role_t = 0;
404
405 #[cfg(not(esp_idf_version_major = "4"))]
407 const I2S_ROLE_TARGET: i2s_role_t = 1;
408
409 impl Role {
410 #[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 #[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 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
436 pub enum SlotBitWidth {
437 #[default]
439 Auto,
440
441 Bits8,
443
444 Bits16,
446
447 Bits24,
449
450 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 #[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 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
497 pub enum SlotMode {
498 Mono,
502
503 #[default]
507 Stereo,
508 }
509
510 impl SlotMode {
511 #[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
523pub trait I2s: Send + sealed::Sealed {
525 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 fn port(&self) -> i2s_port_t;
540}
541
542pub trait I2sRxSupported {}
544
545pub struct I2sRx {}
561impl I2sRxSupported for I2sRx {}
562
563pub trait I2sTxSupported {}
565
566pub struct I2sTx {}
582impl I2sTxSupported for I2sTx {}
583
584pub struct I2sBiDir {}
601impl I2sRxSupported for I2sBiDir {}
602impl I2sTxSupported for I2sBiDir {}
603
604pub 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
621pub struct I2sDriver<'d, Dir> {
623 #[cfg(not(esp_idf_version_major = "4"))]
625 rx_handle: i2s_chan_handle_t,
626
627 #[cfg(not(esp_idf_version_major = "4"))]
629 tx_handle: i2s_chan_handle_t,
630
631 port: u8,
633
634 _p: PhantomData<&'d ()>,
636
637 _dir: PhantomData<Dir>,
639}
640
641impl<Dir> I2sDriver<'_, Dir> {
642 #[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 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 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 esp!(unsafe {
758 i2s_channel_register_event_callback(handle, &callbacks, core::ptr::null_mut())
759 })?;
760
761 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 pub fn as_ref(&mut self) -> I2sDriverRef<'_, Dir> {
783 I2sDriverRef(unsafe { NonNull::new_unchecked(self) })
784 }
785}
786
787impl<Dir> I2sDriver<'_, Dir>
789where
790 Dir: I2sRxSupported,
791{
792 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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
1029impl<Dir> I2sDriver<'_, Dir>
1031where
1032 Dir: I2sTxSupported,
1033{
1034 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 pub fn split(&mut self) -> (I2sDriverRef<'_, I2sRx>, I2sDriverRef<'_, I2sTx>) {
1245 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#[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#[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()];