Skip to content

I2c: simplify trait. #441

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

Closed
wants to merge 4 commits into from
Closed
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
56 changes: 34 additions & 22 deletions embedded-hal-async/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
async fn read<'a>(&'a mut self, address: A, read: &'a mut [u8]) -> Result<(), Self::Error>;
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
self.transaction(address, &mut [Operation::Read(read)])
.await
}

/// Writes bytes to slave with address `address`
///
Expand All @@ -59,7 +62,10 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `SAK` = slave acknowledge
/// - `Bi` = ith byte of data
/// - `SP` = stop condition
async fn write<'a>(&'a mut self, address: A, write: &'a [u8]) -> Result<(), Self::Error>;
async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
self.transaction(address, &mut [Operation::Write(write)])
.await
}

/// Writes bytes to slave with address `address` and then reads enough bytes to fill `read` *in a
/// single transaction*.
Expand All @@ -83,12 +89,18 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
async fn write_read<'a>(
&'a mut self,
async fn write_read(
&mut self,
address: A,
write: &'a [u8],
read: &'a mut [u8],
) -> Result<(), Self::Error>;
write: &[u8],
read: &mut [u8],
) -> Result<(), Self::Error> {
self.transaction(
address,
&mut [Operation::Write(write), Operation::Read(read)],
)
.await
}

/// Execute the provided operations on the I2C bus as a single transaction.
///
Expand All @@ -103,35 +115,35 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `SAD+R/W` = slave address followed by bit 1 to indicate reading or 0 to indicate writing
/// - `SR` = repeated start condition
/// - `SP` = stop condition
async fn transaction<'a, 'b>(
&'a mut self,
async fn transaction(
&mut self,
address: A,
operations: &'a mut [Operation<'b>],
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error>;
}

impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
async fn read<'a>(&'a mut self, address: A, buffer: &'a mut [u8]) -> Result<(), Self::Error> {
T::read(self, address, buffer).await
async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
T::read(self, address, read).await
}

async fn write<'a>(&'a mut self, address: A, bytes: &'a [u8]) -> Result<(), Self::Error> {
T::write(self, address, bytes).await
async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
T::write(self, address, write).await
}

async fn write_read<'a>(
&'a mut self,
async fn write_read(
&mut self,
address: A,
bytes: &'a [u8],
buffer: &'a mut [u8],
write: &[u8],
read: &mut [u8],
) -> Result<(), Self::Error> {
T::write_read(self, address, bytes, buffer).await
T::write_read(self, address, write, read).await
}

async fn transaction<'a, 'b>(
&'a mut self,
async fn transaction(
&mut self,
address: A,
operations: &'a mut [Operation<'b>],
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error> {
T::transaction(self, address, operations).await
}
Expand Down
170 changes: 27 additions & 143 deletions embedded-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,63 +29,15 @@
//! # impl ErrorType for I2c0 { type Error = ErrorKind; }
//! impl I2c<SevenBitAddress> for I2c0
//! {
//! fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_iter<B: IntoIterator<Item = u8>>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_iter_read<B: IntoIterator<Item = u8>>(&mut self, addr: u8, bytes: B, buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn transaction_iter<'a, O: IntoIterator<Item = Operation<'a>>>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> {
//! fn transaction(&mut self, address: u8, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! }
//!
//! impl I2c<TenBitAddress> for I2c0
//! {
//! fn read(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write(&mut self, addr: u16, bytes: &[u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_iter<B: IntoIterator<Item = u8>>(&mut self, addr: u16, bytes: B) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_read(&mut self, addr: u16, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn write_iter_read<B: IntoIterator<Item = u8>>(&mut self, addr: u16, bytes: B, buffer: &mut [u8]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn transaction<'a>(&mut self, address: u16, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
//! fn transaction_iter<'a, O: IntoIterator<Item = Operation<'a>>>(&mut self, address: u16, operations: O) -> Result<(), Self::Error> {
//! fn transaction(&mut self, address: u16, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> {
//! // ...
//! # Ok(())
//! }
Expand Down Expand Up @@ -256,7 +208,7 @@ impl AddressMode for SevenBitAddress {}

impl AddressMode for TenBitAddress {}

/// Transactional I2C operation.
/// I2C operation.
///
/// Several operations can be combined as part of a transaction.
#[derive(Debug, PartialEq, Eq)]
Expand All @@ -269,7 +221,7 @@ pub enum Operation<'a> {

/// Blocking I2C
pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// Reads enough bytes from slave with `address` to fill `buffer`
/// Reads enough bytes from slave with `address` to fill `read`
///
/// # I2C Events (contract)
///
Expand All @@ -287,7 +239,9 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error>;
fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
self.transaction(address, &mut [Operation::Read(read)])
}

/// Writes bytes to slave with address `address`
///
Expand All @@ -305,18 +259,11 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `SAK` = slave acknowledge
/// - `Bi` = ith byte of data
/// - `SP` = stop condition
fn write(&mut self, address: A, bytes: &[u8]) -> Result<(), Self::Error>;

/// Writes bytes to slave with address `address`
///
/// # I2C Events (contract)
///
/// Same as the `write` method
fn write_iter<B>(&mut self, address: A, bytes: B) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>;
fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
self.transaction(address, &mut [Operation::Write(write)])
}

/// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
/// Writes bytes to slave with address `address` and then reads enough bytes to fill `read` *in a
/// single transaction*
///
/// # I2C Events (contract)
Expand All @@ -338,27 +285,12 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn write_read(
&mut self,
address: A,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error>;

/// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
/// single transaction*
///
/// # I2C Events (contract)
///
/// Same as the `write_read` method
fn write_iter_read<B>(
&mut self,
address: A,
bytes: B,
buffer: &mut [u8],
) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>;
fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
self.transaction(
address,
&mut [Operation::Write(write), Operation::Read(read)],
)
}

/// Execute the provided operations on the I2C bus.
///
Expand All @@ -373,79 +305,31 @@ pub trait I2c<A: AddressMode = SevenBitAddress>: ErrorType {
/// - `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 transaction<'a>(
fn transaction(
&mut self,
address: A,
operations: &mut [Operation<'a>],
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error>;

/// 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 transaction_iter<'a, O>(&mut self, address: A, operations: O) -> Result<(), Self::Error>
where
O: IntoIterator<Item = Operation<'a>>;
}

impl<A: AddressMode, T: I2c<A>> I2c<A> for &mut T {
fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> {
T::read(self, address, buffer)
fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error> {
T::read(self, address, read)
}

fn write(&mut self, address: A, bytes: &[u8]) -> Result<(), Self::Error> {
T::write(self, address, bytes)
fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error> {
T::write(self, address, write)
}

fn write_iter<B>(&mut self, address: A, bytes: B) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>,
{
T::write_iter(self, address, bytes)
fn write_read(&mut self, address: A, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> {
T::write_read(self, address, write, read)
}

fn write_read(
fn transaction(
&mut self,
address: A,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
T::write_read(self, address, bytes, buffer)
}

fn write_iter_read<B>(
&mut self,
address: A,
bytes: B,
buffer: &mut [u8],
) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>,
{
T::write_iter_read(self, address, bytes, buffer)
}

fn transaction<'a>(
&mut self,
address: A,
operations: &mut [Operation<'a>],
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error> {
T::transaction(self, address, operations)
}

fn transaction_iter<'a, O>(&mut self, address: A, operations: O) -> Result<(), Self::Error>
where
O: IntoIterator<Item = Operation<'a>>,
{
T::transaction_iter(self, address, operations)
}
}