Skip to content

Commit

Permalink
Implement transactional I2C and add example using it
Browse files Browse the repository at this point in the history
  • Loading branch information
eldruin committed Nov 5, 2020
1 parent 4e55504 commit 468b21a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
35 changes: 35 additions & 0 deletions examples/transactional-i2c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extern crate embedded_hal;
extern crate linux_embedded_hal;
use embedded_hal::blocking::i2c::{Operation as I2cOperation, Transactional};
use linux_embedded_hal::I2cdev;

const ADDR: u8 = 0x12;

struct Driver<I2C> {
i2c: I2C,
}

impl<I2C> Driver<I2C>
where
I2C: Transactional,
{
pub fn new(i2c: I2C) -> Self {
Driver { i2c }
}

fn read_something(&mut self) -> Result<u8, I2C::Error> {
let mut read_buffer = [0];
let mut ops = [
I2cOperation::Write(&[0xAB]),
I2cOperation::Read(&mut read_buffer),
];
self.i2c.try_exec(ADDR, &mut ops).and(Ok(read_buffer[0]))
}
}

fn main() {
let dev = I2cdev::new("/dev/i2c-1").unwrap();
let mut driver = Driver::new(dev);
let value = driver.read_something().unwrap();
println!("Read value: {}", value);
}
23 changes: 23 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use std::time::Duration;
use std::{ops, thread};

use cast::{u32, u64};
use hal::blocking::i2c::Operation as I2cOperation;
use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer};
use i2cdev::linux::LinuxI2CMessage;
use spidev::SpidevTransfer;
Expand Down Expand Up @@ -207,6 +208,28 @@ impl hal::blocking::i2c::WriteRead for I2cdev {
}
}

impl hal::blocking::i2c::Transactional for I2cdev {
type Error = i2cdev::linux::LinuxI2CError;

fn try_exec<'a, O>(&mut self, address: u8, mut operations: O) -> Result<(), Self::Error>
where
O: AsMut<[I2cOperation<'a>]>,
{
// Map operations from generic to linux objects
let mut messages: Vec<_> = operations
.as_mut()
.iter_mut()
.map(|a| match a {
I2cOperation::Write(w) => LinuxI2CMessage::write(w),
I2cOperation::Read(r) => LinuxI2CMessage::read(r),
})
.collect();

self.set_address(address)?;
self.inner.transfer(&mut messages).map(drop)
}
}

impl ops::Deref for I2cdev {
type Target = i2cdev::linux::LinuxI2CDevice;

Expand Down

0 comments on commit 468b21a

Please sign in to comment.