Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I2S reconfiguration support #335

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions src/i2s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -573,9 +575,12 @@ pub struct I2sDriver<'d, Dir> {

/// Directionality -- mimics the directionality of the peripheral.
_dir: PhantomData<Dir>,

/// Mode -- mimics the i2s mode
_mode: PhantomData<Mode>,
}

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<I2S: I2s>(
Expand Down Expand Up @@ -610,6 +615,7 @@ impl<'d, Dir> I2sDriver<'d, Dir> {
tx_handle,
_p: PhantomData,
_dir: PhantomData,
_mode: PhantomData,
};

this.subscribe_channel(this.rx_handle)?;
Expand Down Expand Up @@ -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,
{
Expand Down Expand Up @@ -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,
{
Expand Down Expand Up @@ -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")]
{
Expand Down Expand Up @@ -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,
{
Expand All @@ -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,
{
Expand All @@ -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,
{
Expand All @@ -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,
{
Expand Down
6 changes: 4 additions & 2 deletions src/i2s/pdm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down
48 changes: 44 additions & 4 deletions src/i2s/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*};
Expand Down Expand Up @@ -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<I2S: I2s>(
Expand Down Expand Up @@ -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<I2S: I2s>(
Expand All @@ -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<I2S: I2s>(
Expand All @@ -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<I2S: I2s>(
Expand All @@ -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<PeripheralRef<'d, impl InputPin>>,
dout: Option<PeripheralRef<'d, impl OutputPin>>,
mclk: Option<PeripheralRef<'d, impl InputPin + OutputPin>>,
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) })
}
}
Loading