diff --git a/CHANGELOG.md b/CHANGELOG.md index f038d47..1470504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - [Integration](https://crates.io/crates/mcan-core) with the [`mcan`](https://crates.io/crates/mcan) crate. +- Implementation of blocking::i2c::Transactional trait from [embedded-hal](https://crates.io/crates/embedded-hal) for TWI device. ### Changed diff --git a/hal/src/serial/twi.rs b/hal/src/serial/twi.rs index 63a584b..e60b799 100644 --- a/hal/src/serial/twi.rs +++ b/hal/src/serial/twi.rs @@ -353,3 +353,59 @@ impl blocking::i2c::WriteRead for Twi { Ok(()) } } + +#[derive(PartialEq)] +enum TransactionalState { + Reading, + Writing, + Uninitialized, +} + +impl blocking::i2c::Transactional for Twi { + type Error = TwiError; + + fn exec<'a>( + &mut self, + address: u8, + operations: &mut [blocking::i2c::Operation<'a>], + ) -> Result<(), Self::Error> { + let mut state = TransactionalState::Uninitialized; + + for operation in operations { + match operation { + blocking::i2c::Operation::Read(buffer) => { + // If not already reading setup for read. + if state != TransactionalState::Reading { + self.setup_transaction(address, TwiAction::Read); + self.start_transaction(); + state = TransactionalState::Reading; + } + + self.read(buffer)?; + } + blocking::i2c::Operation::Write(buffer) => { + // If not already writing setup for write. + if state != TransactionalState::Writing { + self.setup_transaction(address, TwiAction::Write); + state = TransactionalState::Writing; + } + + self.write(buffer)?; + } + } + } + + // end transaction + match state { + TransactionalState::Reading => { + self.finalize_transaction(TwiAction::Read)?; + } + TransactionalState::Writing => { + self.finalize_transaction(TwiAction::Write)?; + } + TransactionalState::Uninitialized => (), // Since no operation was done do not finalize transaction. + } + + Ok(()) + } +}