From 6ed5cbc7db43e4e303b59d893c886fa0f6f52c5b Mon Sep 17 00:00:00 2001 From: Maxime Borges Date: Sat, 29 Oct 2022 19:02:52 +0200 Subject: [PATCH 1/2] WIP --- embedded-hal/src/lib.rs | 5 ++ embedded-hal/src/sai.rs | 173 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 embedded-hal/src/sai.rs diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index 8b65ded47..ad55356db 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -80,13 +80,18 @@ pub mod delay; pub mod digital; pub mod i2c; +pub mod sai; pub mod serial; pub mod spi; mod private { use crate::i2c::{SevenBitAddress, TenBitAddress}; + use crate::sai::{I2sMode, I2sLeftMode, TdmMode}; pub trait Sealed {} impl Sealed for SevenBitAddress {} impl Sealed for TenBitAddress {} + impl Sealed for I2sMode {} + impl Sealed for I2sLeftMode {} + impl Sealed for TdmMode {} } diff --git a/embedded-hal/src/sai.rs b/embedded-hal/src/sai.rs new file mode 100644 index 000000000..7e3eda240 --- /dev/null +++ b/embedded-hal/src/sai.rs @@ -0,0 +1,173 @@ +//! Blocking Synchronous Audio Interface API + +use crate::private; + +/// SAI mode +/// +/// Note: This trait is sealed and should not be implemented outside of this crate. +pub trait SaiMode: private::Sealed + 'static {} + +/// Standard I2S mode +pub struct I2sMode; + +/// I2S mode with left/MSB alignement +pub struct I2sLeftMode; + +/// TDM mode +pub struct TdmMode; + +impl SaiMode for I2sMode {} +impl SaiMode for I2sLeftMode {} +impl SaiMode for TdmMode {} + +/// I2S trait +pub trait I2s: + I2sRx + + I2sTx {} + +/// I2S receiver-only trait +pub trait I2sRx: + SaiRx + + SaiRxInterlaced {} + +/// I2S transmitter-only trait +pub trait I2sTx: + SaiTx + + SaiTxInterlaced {} + + +/// I2S left/MSB aligned trait +pub trait I2sLeft: + I2sLeftRx + + I2sLeftTx {} + +/// I2S left/MSB aligned receiver-only trait +pub trait I2sLeftRx: + SaiRx + + SaiRxInterlaced {} + +/// I2S left/MSB aligned transmitter-only trait +pub trait I2sLeftTx: + SaiTx + + SaiTxInterlaced {} + + +/// TDM receiver trait +pub trait TdmRx: + SaiRx + + SaiRxInterlaced {} + +/// TDM transmitter trait +pub trait TdmTx: + SaiTx + + SaiTxInterlaced {} + + +/// SAI RX trait +pub trait SaiRx { + /// Error type + type Error: core::fmt::Debug; + + /// Reads enough bytes to fill all `CHANNELS` with `samples`. + fn read<'w>(&mut self, samples: [&'w mut [W]; CHANNELS]) -> Result<(), Self::Error>; +} + +/// SAI RX interlaced trait +pub trait SaiRxInterlaced { + /// Error type + type Error: core::fmt::Debug; + + /// Reads enough bytes to fill the interlaced `samples` buffer. + fn read_interlaced<'w>(&mut self, samples: &'w mut [W]) -> Result<(), Self::Error>; +} + +/// SAI TX trait +pub trait SaiTx { + /// Error type + type Error: core::fmt::Debug; + + /// Sends `samples` to the `CHANNELS`. + fn write<'w>(&mut self, samples: [&'w [W]; CHANNELS]) -> Result<(), Self::Error>; + + /// Sends `samples` to the `CHANNELS`. + fn write_iter(&mut self, samples: [WI; CHANNELS]) -> Result<(), Self::Error> + where WI: core::iter::IntoIterator; +} + +/// SAI TX interlaced trait +pub trait SaiTxInterlaced { + /// Error type + type Error: core::fmt::Debug; + + /// Sends `samples` from an interlaced buffer. + fn write_interlaced<'w>(&mut self, samples: &'w mut [W]) -> Result<(), Self::Error>; + + /// Sends `samples` to the `CHANNELS`. + fn write_interlaced_iter(&mut self, samples: WI) -> Result<(), Self::Error> + where WI: core::iter::IntoIterator; +} + +/// SAI error +pub trait Error: core::fmt::Debug { + /// Convert error to a generic SAI error kind + /// + /// By using this method, SAI errors freely defined by HAL implementations + /// can be converted to a set of generic SAI errors upon which generic + /// code can act. + fn kind(&self) -> ErrorKind; +} + +impl Error for core::convert::Infallible { + fn kind(&self) -> ErrorKind { + match *self {} + } +} + +/// SAI error kind +/// +/// This represents a common set of SPI operation errors. HAL implementations are +/// free to define more specific or additional error types. However, by providing +/// a mapping to these common SPI errors, generic code can still react to them. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[non_exhaustive] +pub enum ErrorKind { + // /// The peripheral receive buffer was overrun + // Overrun, + // /// Multiple devices on the SPI bus are trying to drive the slave select pin, e.g. in a multi-master setup + // ModeFault, + // /// Received data does not conform to the peripheral configuration + // FrameFormat, + // /// An error occurred while asserting or deasserting the Chip Select pin. + // ChipSelectFault, + /// A different error occurred. The original error may contain more information. + Other, +} + +impl Error for ErrorKind { + fn kind(&self) -> ErrorKind { + *self + } +} + +impl core::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Other => write!( + f, + "A different error occurred. The original error may contain more information" + ), + } + } +} + +/// SAI error type trait +/// +/// This just defines the error type, to be used by the other SAI traits. +pub trait ErrorType { + /// Error type + type Error: Error; +} + +impl ErrorType for &mut T { + type Error = T::Error; +} \ No newline at end of file From 517f7c44c8c804bf0cd5db4ee528c98a28beb0f3 Mon Sep 17 00:00:00 2001 From: Maxime Borges Date: Fri, 11 Nov 2022 13:03:30 +0100 Subject: [PATCH 2/2] cargo fmt --- embedded-hal/src/lib.rs | 2 +- embedded-hal/src/sai.rs | 80 ++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index ad55356db..45265e975 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -86,7 +86,7 @@ pub mod spi; mod private { use crate::i2c::{SevenBitAddress, TenBitAddress}; - use crate::sai::{I2sMode, I2sLeftMode, TdmMode}; + use crate::sai::{I2sLeftMode, I2sMode, TdmMode}; pub trait Sealed {} impl Sealed for SevenBitAddress {} diff --git a/embedded-hal/src/sai.rs b/embedded-hal/src/sai.rs index 7e3eda240..e557f2353 100644 --- a/embedded-hal/src/sai.rs +++ b/embedded-hal/src/sai.rs @@ -5,7 +5,7 @@ use crate::private; /// SAI mode /// /// Note: This trait is sealed and should not be implemented outside of this crate. -pub trait SaiMode: private::Sealed + 'static {} +pub trait SaiCommMode: private::Sealed + 'static {} /// Standard I2S mode pub struct I2sMode; @@ -16,95 +16,95 @@ pub struct I2sLeftMode; /// TDM mode pub struct TdmMode; -impl SaiMode for I2sMode {} -impl SaiMode for I2sLeftMode {} -impl SaiMode for TdmMode {} +impl SaiCommMode for I2sMode {} +impl SaiCommMode for I2sLeftMode {} +impl SaiCommMode for TdmMode {} /// I2S trait -pub trait I2s: - I2sRx + - I2sTx {} +pub trait I2s: I2sRx + I2sTx {} /// I2S receiver-only trait -pub trait I2sRx: - SaiRx + - SaiRxInterlaced {} +pub trait I2sRx: SaiRx + SaiRxInterlaced {} /// I2S transmitter-only trait -pub trait I2sTx: - SaiTx + - SaiTxInterlaced {} - +pub trait I2sTx: SaiTx + SaiTxInterlaced {} /// I2S left/MSB aligned trait -pub trait I2sLeft: - I2sLeftRx + - I2sLeftTx {} +pub trait I2sLeft: I2sLeftRx + I2sLeftTx {} + +/// I2S left/MSB aligned receiver-only trait +pub trait I2sLeftRx: SaiRx + SaiRxInterlaced {} -/// I2S left/MSB aligned receiver-only trait -pub trait I2sLeftRx: - SaiRx + - SaiRxInterlaced {} +/// I2S left/MSB aligned transmitter-only trait +pub trait I2sLeftTx: SaiTx + SaiTxInterlaced {} -/// I2S left/MSB aligned transmitter-only trait -pub trait I2sLeftTx: - SaiTx + - SaiTxInterlaced {} +/// TDM trait +pub trait Tdm: TdmRx + TdmTx {} - /// TDM receiver trait pub trait TdmRx: - SaiRx + - SaiRxInterlaced {} + SaiRx + SaiRxInterlaced +{ +} /// TDM transmitter trait pub trait TdmTx: - SaiTx + - SaiTxInterlaced {} - + SaiTx + SaiTxInterlaced +{ +} /// SAI RX trait -pub trait SaiRx { +pub trait SaiRx { /// Error type type Error: core::fmt::Debug; + /// Sample type + type Sample: Sized; /// Reads enough bytes to fill all `CHANNELS` with `samples`. fn read<'w>(&mut self, samples: [&'w mut [W]; CHANNELS]) -> Result<(), Self::Error>; } /// SAI RX interlaced trait -pub trait SaiRxInterlaced { +pub trait SaiRxInterlaced { /// Error type type Error: core::fmt::Debug; - + /// Sample type + type Sample: Sized; + /// Reads enough bytes to fill the interlaced `samples` buffer. fn read_interlaced<'w>(&mut self, samples: &'w mut [W]) -> Result<(), Self::Error>; } /// SAI TX trait -pub trait SaiTx { +pub trait SaiTx { /// Error type type Error: core::fmt::Debug; + /// Sample type + type Sample: Sized; /// Sends `samples` to the `CHANNELS`. fn write<'w>(&mut self, samples: [&'w [W]; CHANNELS]) -> Result<(), Self::Error>; /// Sends `samples` to the `CHANNELS`. fn write_iter(&mut self, samples: [WI; CHANNELS]) -> Result<(), Self::Error> - where WI: core::iter::IntoIterator; + where + WI: core::iter::IntoIterator; } /// SAI TX interlaced trait -pub trait SaiTxInterlaced { +pub trait SaiTxInterlaced { /// Error type type Error: core::fmt::Debug; + /// Sample type + type Sample: Sized; /// Sends `samples` from an interlaced buffer. - fn write_interlaced<'w>(&mut self, samples: &'w mut [W]) -> Result<(), Self::Error>; + fn write_interlaced<'w>(&mut self, samples: &'w [W]) -> Result<(), Self::Error>; /// Sends `samples` to the `CHANNELS`. fn write_interlaced_iter(&mut self, samples: WI) -> Result<(), Self::Error> - where WI: core::iter::IntoIterator; + where + WI: core::iter::IntoIterator; } /// SAI error @@ -170,4 +170,4 @@ pub trait ErrorType { impl ErrorType for &mut T { type Error = T::Error; -} \ No newline at end of file +}