From 255ccdbc36b75e6db187c64d6a96416c03817a76 Mon Sep 17 00:00:00 2001 From: Borna Butkovic Date: Thu, 9 Nov 2023 18:27:45 +0100 Subject: [PATCH] i2s reconfig support --- src/i2s.rs | 30 ++++++++++++++++++------------ src/i2s/pdm.rs | 6 ++++-- src/i2s/std.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/i2s.rs b/src/i2s.rs index 8aa14ade31a..a4fffe927bb 100644 --- a/src/i2s.rs +++ b/src/i2s.rs @@ -4,6 +4,8 @@ use core::{ffi::c_void, marker::PhantomData, mem::MaybeUninit}; use esp_idf_sys::{esp, i2s_port_t, EspError, TickType_t}; +pub use std::I2sStd; + #[cfg(not(esp_idf_version_major = "4"))] use { core::ptr::null_mut, @@ -556,7 +558,7 @@ impl I2sRxSupported for I2sBiDir {} impl I2sTxSupported for I2sBiDir {} /// Inter-IC Sound (I2S) driver. -pub struct I2sDriver<'d, Dir> { +pub struct I2sDriver<'d, Dir, Mode> { /// The Rx channel, possibly null. #[cfg(not(esp_idf_version_major = "4"))] rx_handle: i2s_chan_handle_t, @@ -573,9 +575,12 @@ pub struct I2sDriver<'d, Dir> { /// Directionality -- mimics the directionality of the peripheral. _dir: PhantomData, + + /// Mode -- mimics the i2s mode + _mode: PhantomData, } -impl<'d, Dir> I2sDriver<'d, Dir> { +impl<'d, Dir, Mode> I2sDriver<'d, Dir, Mode> { /// Create a new standard mode driver for the given I2S peripheral with both the receive and transmit channels open. #[cfg(not(esp_idf_version_major = "4"))] fn internal_new( @@ -610,6 +615,7 @@ impl<'d, Dir> I2sDriver<'d, Dir> { tx_handle, _p: PhantomData, _dir: PhantomData, + _mode: PhantomData, }; this.subscribe_channel(this.rx_handle)?; @@ -717,7 +723,7 @@ impl<'d, Dir> I2sDriver<'d, Dir> { } /// Functions for receive channels. -impl<'d, Dir> I2sDriver<'d, Dir> +impl<'d, Dir, Mode> I2sDriver<'d, Dir, Mode> where Dir: I2sRxSupported, { @@ -959,7 +965,7 @@ where } /// Functions for transmit channels. -impl<'d, Dir> I2sDriver<'d, Dir> +impl<'d, Dir, Mode> I2sDriver<'d, Dir, Mode> where Dir: I2sTxSupported, { @@ -1166,7 +1172,7 @@ where } } -impl<'d, Dir> Drop for I2sDriver<'d, Dir> { +impl<'d, Dir, Mode> Drop for I2sDriver<'d, Dir, Mode> { fn drop(&mut self) { #[cfg(esp_idf_version_major = "4")] { @@ -1202,19 +1208,19 @@ impl<'d, Dir> Drop for I2sDriver<'d, Dir> { } } -unsafe impl<'d, Dir> Send for I2sDriver<'d, Dir> {} +unsafe impl<'d, Dir, Mode> Send for I2sDriver<'d, Dir, Mode> {} -impl<'d, Dir> I2sPort for I2sDriver<'d, Dir> { +impl<'d, Dir, Mode> I2sPort for I2sDriver<'d, Dir, Mode> { fn port(&self) -> i2s_port_t { self.port as _ } } -impl<'d, Dir> embedded_io::ErrorType for I2sDriver<'d, Dir> { +impl<'d, Dir, Mode> embedded_io::ErrorType for I2sDriver<'d, Dir, Mode> { type Error = EspIOError; } -impl<'d, Dir> embedded_io::Read for I2sDriver<'d, Dir> +impl<'d, Dir, Mode> embedded_io::Read for I2sDriver<'d, Dir, Mode> where Dir: I2sRxSupported, { @@ -1223,7 +1229,7 @@ where } } -impl<'d, Dir> embedded_io::Write for I2sDriver<'d, Dir> +impl<'d, Dir, Mode> embedded_io::Write for I2sDriver<'d, Dir, Mode> where Dir: I2sTxSupported, { @@ -1238,7 +1244,7 @@ where #[cfg(feature = "nightly")] #[cfg(not(esp_idf_version_major = "4"))] -impl<'d, Dir> embedded_io_async::Read for I2sDriver<'d, Dir> +impl<'d, Dir, Mode> embedded_io_async::Read for I2sDriver<'d, Dir, Mode> where Dir: I2sRxSupported, { @@ -1249,7 +1255,7 @@ where #[cfg(feature = "nightly")] #[cfg(not(esp_idf_version_major = "4"))] -impl<'d, Dir> embedded_io_async::Write for I2sDriver<'d, Dir> +impl<'d, Dir, Mode> embedded_io_async::Write for I2sDriver<'d, Dir, Mode> where Dir: I2sTxSupported, { diff --git a/src/i2s/pdm.rs b/src/i2s/pdm.rs index 3f0f2db22a6..6528afa4aba 100644 --- a/src/i2s/pdm.rs +++ b/src/i2s/pdm.rs @@ -1185,12 +1185,14 @@ pub(super) mod config { } } +pub struct I2sPdm {} + #[cfg(esp_idf_soc_i2s_supports_pdm_rx)] #[cfg_attr( feature = "nightly", doc(cfg(all(any(esp32, esp32s3), not(esp_idf_version_major = "4")))) )] -impl<'d> I2sDriver<'d, I2sRx> { +impl<'d> I2sDriver<'d, I2sRx, I2sPdm> { /// Create a new pulse density modulation (PDM) mode driver for the given I2S peripheral with only the receive /// channel open. #[allow(clippy::too_many_arguments)] @@ -1328,7 +1330,7 @@ impl<'d> I2sDriver<'d, I2sRx> { not(esp_idf_version_major = "4") ))) )] -impl<'d> I2sDriver<'d, I2sTx> { +impl<'d> I2sDriver<'d, I2sTx, I2sPdm> { /// Create a new pulse density modulation (PDM) mode driver for the given I2S peripheral with only the transmit /// channel open. #[allow(clippy::too_many_arguments)] diff --git a/src/i2s/std.rs b/src/i2s/std.rs index 71a3f925194..cdd5ed4bb95 100644 --- a/src/i2s/std.rs +++ b/src/i2s/std.rs @@ -12,11 +12,18 @@ //! | ESP32-C6 | I2S0 | I2S0 | //! | ESP32-H2 | I2S0 | I2S0 | +use self::config::{StdClkConfig, StdGpioConfig, StdSlotConfig}; + use super::*; use crate::{gpio::*, peripheral::*}; use esp_idf_sys::*; +pub struct I2sStd {} +pub trait I2sStdConfigSupported {} + +impl I2sStdConfigSupported for I2sStd {} + pub(super) mod config { #[allow(unused)] use crate::{gpio::*, i2s::config::*, peripheral::*}; @@ -706,7 +713,7 @@ pub(super) mod config { } } -impl<'d, Dir> I2sDriver<'d, Dir> { +impl<'d, Dir> I2sDriver<'d, Dir, I2sStd> { #[cfg(not(esp_idf_version_major = "4"))] #[allow(clippy::too_many_arguments)] fn internal_new_std( @@ -793,7 +800,7 @@ impl<'d, Dir> I2sDriver<'d, Dir> { } } -impl<'d> I2sDriver<'d, I2sBiDir> { +impl<'d> I2sDriver<'d, I2sBiDir, I2sStd> { /// Create a new standard mode driver for the given I2S peripheral with both the receive and transmit channels open. #[allow(clippy::too_many_arguments)] pub fn new_std_bidir( @@ -819,7 +826,7 @@ impl<'d> I2sDriver<'d, I2sBiDir> { } } -impl<'d> I2sDriver<'d, I2sRx> { +impl<'d> I2sDriver<'d, I2sRx, I2sStd> { /// Create a new standard mode driver for the given I2S peripheral with only the receive channel open. #[allow(clippy::too_many_arguments)] pub fn new_std_rx( @@ -844,7 +851,7 @@ impl<'d> I2sDriver<'d, I2sRx> { } } -impl<'d> I2sDriver<'d, I2sTx> { +impl<'d> I2sDriver<'d, I2sTx, I2sStd> { /// Create a new standard mode driver for the given I2S peripheral with only the transmit channel open. #[allow(clippy::too_many_arguments)] pub fn new_std_tx( @@ -868,3 +875,36 @@ impl<'d> I2sDriver<'d, I2sTx> { ) } } + +#[cfg(not(esp_idf_version_major = "4"))] +impl<'d, Dir> I2sDriver<'d, Dir, I2sStd> { + /// Reconfigure the slot configuration for the given I2S STD handle. + pub fn reconfig_slot(&mut self, config: &StdSlotConfig) -> Result<(), EspError> { + let config = config.as_sdk(); + esp!(unsafe { i2s_channel_reconfig_std_slot(self.tx_handle, &config) })?; + esp!(unsafe { i2s_channel_reconfig_std_slot(self.rx_handle, &config) }) + } + + + /// Reconfigure the clock configuration for the given I2S STD handle. + pub fn reconfig_clk(&mut self, config: &StdClkConfig) -> Result<(), EspError> { + let config = config.as_sdk(); + esp!(unsafe { i2s_channel_reconfig_std_clock(self.tx_handle, &config) })?; + esp!(unsafe { i2s_channel_reconfig_std_clock(self.rx_handle, &config) }) + } + + /// Reconfigure the gpio configuration for the given I2S STD handle. + pub fn reconfig_gpio( + &mut self, + config: &StdGpioConfig, + bclk: PeripheralRef<'d, impl InputPin + OutputPin>, + din: Option>, + dout: Option>, + mclk: Option>, + ws: PeripheralRef<'d, impl InputPin + OutputPin>, + ) -> Result<(), EspError> { + let config = config.as_sdk(bclk, din, dout, mclk, ws); + esp!(unsafe { i2s_channel_reconfig_std_gpio(self.tx_handle, &config) })?; + esp!(unsafe { i2s_channel_reconfig_std_gpio(self.rx_handle, &config) }) + } +}