From 749ebffd67b0c658f89f8f9e9dd5978dec2ce3f8 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Wed, 17 Jun 2020 18:08:23 +0200 Subject: [PATCH 1/7] Add transactional I2C trait --- src/blocking/i2c.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs index dedc7facc..95fc5196a 100644 --- a/src/blocking/i2c.rs +++ b/src/blocking/i2c.rs @@ -232,3 +232,39 @@ pub trait WriteIterRead { 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 operation within an I2C transaction. +pub trait Transactional { + /// Error type + type Error; + + /// 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 try_exec<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> + where + O: AsMut<[Operation<'a>]>; +} From 7766a5b9c3a1534158ad13cf46b1edffd1ff1f3a Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Sat, 20 Jun 2020 14:10:04 +0200 Subject: [PATCH 2/7] Use Operation slice type for consistency --- src/blocking/i2c.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs index 95fc5196a..0aa3bb173 100644 --- a/src/blocking/i2c.rs +++ b/src/blocking/i2c.rs @@ -264,7 +264,9 @@ pub trait Transactional { /// - `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 try_exec<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> - where - O: AsMut<[Operation<'a>]>; + fn try_exec<'a>( + &mut self, + address: u8, + operations: &mut [Operation<'a>], + ) -> Result<(), Self::Error>; } From 3d5a165161bd6f5313ee9d37885b6daad9824082 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Sat, 20 Jun 2020 14:30:36 +0200 Subject: [PATCH 3/7] Add default implementation of i2c traits for transactional implementers --- src/blocking/i2c.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs index 0aa3bb173..704aabdaf 100644 --- a/src/blocking/i2c.rs +++ b/src/blocking/i2c.rs @@ -270,3 +270,54 @@ pub trait Transactional { operations: &mut [Operation<'a>], ) -> Result<(), Self::Error>; } + +/// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and +/// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. +pub mod transactional { + use super::{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 {} + + impl Write for S + where + S: self::Default + Transactional, + { + type Error = E; + + fn try_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { + self.try_exec(address, &mut [Operation::Write(bytes)]) + } + } + + impl Read for S + where + S: self::Default + Transactional, + { + type Error = E; + + fn try_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + self.try_exec(address, &mut [Operation::Read(buffer)]) + } + } + + impl WriteRead for S + where + S: self::Default + Transactional, + { + type Error = E; + + fn try_write_read( + &mut self, + address: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.try_exec( + address, + &mut [Operation::Write(bytes), Operation::Read(buffer)], + ) + } + } +} From 1bc7d95c0553654c2b3165f0bbb622f7368be647 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Sat, 20 Jun 2020 15:30:16 +0200 Subject: [PATCH 4/7] Update src/blocking/i2c.rs Co-authored-by: Daniel Egger --- src/blocking/i2c.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs index 704aabdaf..00affc01c 100644 --- a/src/blocking/i2c.rs +++ b/src/blocking/i2c.rs @@ -246,7 +246,7 @@ pub enum Operation<'a> { /// Transactional I2C interface. /// -/// This allows combining operation within an I2C transaction. +/// This allows combining operations within an I2C transaction. pub trait Transactional { /// Error type type Error; From 6b562e0a23d74683c2fe2fb8df6b973bb637ceae Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Sat, 20 Jun 2020 15:32:55 +0200 Subject: [PATCH 5/7] Add Transactional I2C trait to prelude --- src/prelude.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/prelude.rs b/src/prelude.rs index 315acd9c7..9ec6fb52d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -8,8 +8,9 @@ pub use crate::adc::OneShot as _embedded_hal_adc_OneShot; pub use crate::blocking::delay::DelayMs as _embedded_hal_blocking_delay_DelayMs; pub use crate::blocking::delay::DelayUs as _embedded_hal_blocking_delay_DelayUs; pub use crate::blocking::i2c::{ - Read as _embedded_hal_blocking_i2c_Read, Write as _embedded_hal_blocking_i2c_Write, - WriteIter as _embedded_hal_blocking_i2c_WriteIter, + Read as _embedded_hal_blocking_i2c_Read, + Transactional as _embedded_hal_blocking_i2c_Transactional, + Write as _embedded_hal_blocking_i2c_Write, WriteIter as _embedded_hal_blocking_i2c_WriteIter, WriteIterRead as _embedded_hal_blocking_i2c_WriteIterRead, WriteRead as _embedded_hal_blocking_i2c_WriteRead, }; From cfa13de2e9173d8d96903162e0a3713ed1f92229 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Tue, 14 Jul 2020 08:40:05 +0200 Subject: [PATCH 6/7] Add iterator version of transactional interface --- src/blocking/i2c.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs index 00affc01c..e0aa7ca62 100644 --- a/src/blocking/i2c.rs +++ b/src/blocking/i2c.rs @@ -271,6 +271,31 @@ pub trait Transactional { ) -> Result<(), Self::Error>; } +/// Transactional I2C interface (iterator version). +/// +/// This allows combining operation within an I2C transaction. +pub trait TransactionalIter { + /// Error type + type 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 try_exec_iter<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error> + where + O: IntoIterator>; +} + /// Default implementation of `blocking::i2c::Write`, `blocking::i2c::Read` and /// `blocking::i2c::WriteRead` traits for `blocking::i2c::Transactional` implementers. pub mod transactional { From 88e413323b7bb978e751db05b1739c604780b4f1 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Fri, 30 Oct 2020 08:59:51 +0100 Subject: [PATCH 7/7] Add transactional I2C to changelog and remove misplaced entry in alpha.2 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbde76f71..02d231069 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added -- `Transactional` SPI interface for executing groups of SPI transactions +- `Transactional` SPI interface for executing groups of SPI transactions. +- `Transactional` I2C interface for executing groups of I2C transactions. ### Changed @@ -20,7 +21,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - 10-bit addressing mode for I2C traits. - `try_set_state` method for `OutputPin` using an input `PinState` value. -- `Transactional` interface for grouping SPI transactions ### Changed