revise i2c trait

This commit is contained in:
xoviat 2021-03-05 21:19:56 -06:00
parent a3a36517bd
commit 7a46e66298

View File

@ -97,6 +97,7 @@ pub trait Read<A: AddressMode = SevenBitAddress> {
type Error; type Error;
type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a; type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a;
type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a;
/// Reads enough bytes from slave with `address` to fill `buffer` /// Reads enough bytes from slave with `address` to fill `buffer`
/// ///
@ -117,14 +118,6 @@ pub trait Read<A: AddressMode = SevenBitAddress> {
/// - `NMAK` = master no acknowledge /// - `NMAK` = master no acknowledge
/// - `SP` = stop condition /// - `SP` = stop condition
fn read<'a>(self: Pin<&'a mut Self>, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>; fn read<'a>(self: Pin<&'a mut Self>, address: A, buffer: &mut [u8]) -> Self::ReadFuture<'a>;
}
/// Blocking write
pub trait Write<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type WriteFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a;
/// Sends bytes to slave with address `address` /// Sends bytes to slave with address `address`
/// ///
@ -144,242 +137,3 @@ pub trait Write<A: AddressMode = SevenBitAddress> {
/// - `SP` = stop condition /// - `SP` = stop condition
fn write<'a>(self: Pin<&'a mut Self>, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>; fn write<'a>(self: Pin<&'a mut Self>, address: A, bytes: &[u8]) -> Self::WriteFuture<'a>;
} }
/// Blocking write (iterator version)
pub trait WriteIter<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type WriteIterFuture<'a>: Future<Output = Result<(), Self::Error>> + '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<Item = u8>;
}
/// Blocking write + read
pub trait WriteRead<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type WriteReadFuture<'a>: Future<Output = Result<(), Self::Error>> + '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<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type WriteIterReadFuture<'a>: Future<Output = Result<(), Self::Error>> + '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<Item = u8>;
}
/// 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<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type TransactionalFuture<'a>: Future<Output = Result<(), Self::Error>> + '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<A: AddressMode = SevenBitAddress> {
/// Error type
type Error;
type TransactionalIterFuture<'a>: Future<Output = Result<(), Self::Error>> + '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<Item = Operation<'a>>;
}
/// 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<i2c::SevenBitAddress> 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<i2c::SevenBitAddress> 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<A: AddressMode>: Transactional<A> {}
// impl<A, E, S> Write<A> for S
// where
// A: AddressMode + 'static,
// S: self::Default<A> + Transactional<A, Error = E> + 'static,
// E: 'static,
// {
// type Error = E;
//
// type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a;
//
// fn write<'a>(&mut self, address: A, bytes: &[u8]) -> Self::WriteFuture<'a> {
// self.exec(address, &mut [Operation::Write(bytes)])
// }
// }
/*
impl<A, E, S> Read<A> for S
where
A: AddressMode,
S: self::Default<A> + Transactional<A, Error = E>,
{
type Error = E;
fn read(&mut self, address: A, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.exec(address, &mut [Operation::Read(buffer)])
}
}
impl<A, E, S> WriteRead<A> for S
where
A: AddressMode,
S: self::Default<A> + Transactional<A, Error = E>,
{
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)],
)
}
}
*/
}