diff --git a/embassy-traits/src/i2c.rs b/embassy-traits/src/i2c.rs index 02755b57..f9f462b5 100644 --- a/embassy-traits/src/i2c.rs +++ b/embassy-traits/src/i2c.rs @@ -97,6 +97,7 @@ pub trait Read { type Error; type ReadFuture<'a>: Future> + 'a; + type WriteFuture<'a>: Future> + 'a; /// Reads enough bytes from slave with `address` to fill `buffer` /// @@ -117,14 +118,6 @@ pub trait Read { /// - `NMAK` = master no acknowledge /// - `SP` = stop condition fn read<'a>(self: Pin<&'a mut Self>, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>; -} - -/// Blocking write -pub trait Write { - /// Error type - type Error; - - type WriteFuture<'a>: Future> + 'a; /// Sends bytes to slave with address `address` /// @@ -144,242 +137,3 @@ pub trait Write { /// - `SP` = stop condition fn write<'a>(self: Pin<&'a mut Self>, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>; } - -/// Blocking write (iterator version) -pub trait WriteIter { - /// Error type - type Error; - - type WriteIterFuture<'a>: Future> + 'a; - - /// Sends bytes to slave with address `address` - /// - /// # I2C Events (contract) - /// - /// Same as `Write` - fn write_iter<'a, B>( - self: Pin<&'a mut Self>, - address: A, - bytes: B, - ) -> Self::WriteIterFuture<'a> - where - B: IntoIterator; -} - -/// Blocking write + read -pub trait WriteRead { - /// Error type - type Error; - - type WriteReadFuture<'a>: Future> + 'a; - - /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a - /// single transaction* - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP - /// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+W` = slave address followed by bit 0 to indicate writing - /// - `SAK` = slave acknowledge - /// - `Oi` = ith outgoing byte of data - /// - `SR` = repeated start condition - /// - `SAD+R` = slave address followed by bit 1 to indicate reading - /// - `Ii` = ith incoming byte of data - /// - `MAK` = master acknowledge - /// - `NMAK` = master no acknowledge - /// - `SP` = stop condition - fn write_read<'a>( - self: Pin<&'a mut Self>, - address: A, - bytes: &[u8], - buffer: &mut [u8], - ) -> Self::WriteReadFuture<'a>; -} - -/// Blocking write (iterator version) + read -pub trait WriteIterRead { - /// Error type - type Error; - - type WriteIterReadFuture<'a>: Future> + 'a; - - /// Sends bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a - /// single transaction* - /// - /// # I2C Events (contract) - /// - /// Same as the `WriteRead` trait - fn write_iter_read<'a, B>( - self: Pin<&'a mut Self>, - address: A, - bytes: B, - buffer: &mut [u8], - ) -> Self::WriteIterReadFuture<'a> - where - B: IntoIterator; -} - -/// Transactional I2C operation. -/// -/// Several operations can be combined as part of a transaction. -#[derive(Debug, PartialEq)] -pub enum Operation<'a> { - /// Read data into the provided buffer - Read(&'a mut [u8]), - /// Write data from the provided buffer - Write(&'a [u8]), -} - -/// Transactional I2C interface. -/// -/// This allows combining operations within an I2C transaction. -pub trait Transactional { - /// Error type - type Error; - - type TransactionalFuture<'a>: Future> + 'a; - - /// Execute the provided operations on the I2C bus. - /// - /// Transaction contract: - /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate. - /// - Data from adjacent operations of the same type are sent after each other without an SP or SR. - /// - Between adjacent operations of a different type an SR and SAD+R/W is sent. - /// - After executing the last operation an SP is sent automatically. - /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte. - /// - /// - `ST` = start condition - /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing - /// - `SR` = repeated start condition - /// - `SP` = stop condition - fn exec<'a>( - &mut self, - address: A, - operations: &mut [Operation<'a>], - ) -> Self::TransactionalFuture<'a>; -} - -/// Transactional I2C interface (iterator version). -/// -/// This allows combining operation within an I2C transaction. -pub trait TransactionalIter { - /// Error type - type Error; - - type TransactionalIterFuture<'a>: Future> + 'a; - - /// Execute the provided operations on the I2C bus (iterator version). - /// - /// Transaction contract: - /// - Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate. - /// - Data from adjacent operations of the same type are sent after each other without an SP or SR. - /// - Between adjacent operations of a different type an SR and SAD+R/W is sent. - /// - After executing the last operation an SP is sent automatically. - /// - If the last operation is a `Read` the master does not send an acknowledge for the last byte. - /// - /// - `ST` = start condition - /// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing - /// - `SR` = repeated start condition - /// - `SP` = stop condition - fn exec_iter<'a, O>(&mut self, address: A, operations: O) -> Self::TransactionalIterFuture<'a> - where - O: IntoIterator>; -} - -/// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and -/// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. -/// -/// If you implement `blocking::i2c::Transactional` for your I2C peripheral, -/// you can use this default implementation so that you do not need to implement -/// the `blocking::i2c::Write`, `blocking::i2c::Read` and `blocking::i2c::WriteRead` -/// traits as well. -/// ``` -/// use embedded_hal::blocking::i2c; -/// -/// struct I2c1; -/// -/// impl i2c::Transactional for I2c1 { -/// # type Error = (); -/// fn try_exec<'a>( -/// &mut self, -/// address: i2c::SevenBitAddress, -/// operations: &mut [i2c::Operation<'a>], -/// ) -> Result<(), Self::Error> { -/// // ... -/// # Ok(()) -/// } -/// } -/// -/// // This is all you need to do: -/// impl i2c::transactional::Default for I2c1 {}; -/// -/// // Then you can use `Write` and so on: -/// use i2c::Write; -/// -/// let mut i2c1 = I2c1{}; -/// i2c1.try_write(0x01, &[0xAB, 0xCD]).unwrap(); -/// ``` -pub mod transactional { - use core::future::Future; - - use super::{AddressMode, Operation, Read, Transactional, Write, WriteRead}; - - /// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and - /// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. - pub trait Default: Transactional {} - - // impl Write for S - // where - // A: AddressMode + 'static, - // S: self::Default + Transactional + 'static, - // E: 'static, - // { - // type Error = E; - // - // type WriteFuture<'a> = impl Future> + 'a; - // - // fn write<'a>(&mut self, address: A, bytes: &[u8]) -> Self::WriteFuture<'a> { - // self.exec(address, &mut [Operation::Write(bytes)]) - // } - // } - /* - impl Read for S - where - A: AddressMode, - S: self::Default + Transactional, - { - type Error = E; - - fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.exec(address, &mut [Operation::Read(buffer)]) - } - } - - impl WriteRead for S - where - A: AddressMode, - S: self::Default + Transactional, - { - type Error = E; - - fn write_read( - &mut self, - address: A, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Self::Error> { - self.exec( - address, - &mut [Operation::Write(bytes), Operation::Read(buffer)], - ) - } - } - */ -}