Skip to content

Commit 45d4873

Browse files
committed
Implement transactional I2C and add example using it
1 parent 0df951c commit 45d4873

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

Diff for: Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ openpty = "0.1.0"
3232
# we don't need the `Error` implementation
3333
default-features = false
3434
version = "0.2.2"
35+
36+
[patch.crates-io]
37+
embedded-hal = { git = "https://github.com/eldruin/embedded-hal", branch="transactional-i2c" }

Diff for: examples/transactional-i2c.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
extern crate embedded_hal;
2+
extern crate linux_embedded_hal;
3+
use embedded_hal::blocking::i2c::{Operation as I2cOperation, Transactional};
4+
use linux_embedded_hal::I2cdev;
5+
6+
const ADDR: u8 = 0x12;
7+
8+
struct Driver<I2C> {
9+
i2c: I2C,
10+
}
11+
12+
impl<I2C> Driver<I2C>
13+
where
14+
I2C: Transactional,
15+
{
16+
pub fn new(i2c: I2C) -> Self {
17+
Driver { i2c }
18+
}
19+
20+
fn read_something(&mut self) -> Result<u8, I2C::Error> {
21+
let mut read_buffer = [0];
22+
let mut ops = [
23+
I2cOperation::Write(&[0xAB]),
24+
I2cOperation::Read(&mut read_buffer),
25+
];
26+
self.i2c.try_exec(ADDR, &mut ops).and(Ok(read_buffer[0]))
27+
}
28+
}
29+
30+
fn main() {
31+
let dev = I2cdev::new("/dev/i2c-1").unwrap();
32+
let mut driver = Driver::new(dev);
33+
let value = driver.read_something().unwrap();
34+
println!("Read value: {}", value);
35+
}

Diff for: src/lib.rs

+23
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use std::time::Duration;
3434
use std::{ops, thread};
3535

3636
use cast::{u32, u64};
37+
use hal::blocking::i2c::Operation as I2cOperation;
3738
use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer};
3839
use i2cdev::linux::LinuxI2CMessage;
3940
use spidev::SpidevTransfer;
@@ -207,6 +208,28 @@ impl hal::blocking::i2c::WriteRead for I2cdev {
207208
}
208209
}
209210

211+
impl hal::blocking::i2c::Transactional for I2cdev {
212+
type Error = i2cdev::linux::LinuxI2CError;
213+
214+
fn try_exec<'a, O>(&mut self, address: u8, mut operations: O) -> Result<(), Self::Error>
215+
where
216+
O: AsMut<[I2cOperation<'a>]>,
217+
{
218+
// Map operations from generic to linux objects
219+
let mut messages: Vec<_> = operations
220+
.as_mut()
221+
.iter_mut()
222+
.map(|a| match a {
223+
I2cOperation::Write(w) => LinuxI2CMessage::write(w),
224+
I2cOperation::Read(r) => LinuxI2CMessage::read(r),
225+
})
226+
.collect();
227+
228+
self.set_address(address)?;
229+
self.inner.transfer(&mut messages).map(drop)
230+
}
231+
}
232+
210233
impl ops::Deref for I2cdev {
211234
type Target = i2cdev::linux::LinuxI2CDevice;
212235

0 commit comments

Comments
 (0)