Skip to content

Commit 9dda466

Browse files
committed
Auto merge of rust-embedded#3 - wose:feature/i2c, r=japaric
embedded-hal i2c traits implementation using i2cdev I tested this on a Raspberry Pi 2 with an SDD1306 OLED display and a Si7021 humidity/temperature sensor (driver crates will follow soon). However, I'm not quite sure about the address parameter. The i2cdev crate will use the address when creating the LinuxI2CDevice, the embedded-hal traits expect the device address as parameter. I just ignore this parameter in this implementation. Is this the right way to do it?
2 parents 17ec9f5 + 8edd7d0 commit 9dda466

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ version = "0.1.0"
1010

1111
[dependencies]
1212
embedded-hal = "0.1.0"
13+
i2cdev = "0.3.1"
1314
spidev = "0.3.0"
1415
sysfs_gpio = "0.5.1"
1516

src/lib.rs

+84-1
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@
1515

1616
extern crate cast;
1717
extern crate embedded_hal as hal;
18+
pub extern crate i2cdev;
1819
pub extern crate spidev;
1920
pub extern crate sysfs_gpio;
2021

2122
use std::io::{self, Write};
22-
use std::path::Path;
23+
use std::path::{Path, PathBuf};
2324
use std::time::Duration;
2425
use std::{ops, thread};
2526

2627
use cast::{u32, u64};
28+
use i2cdev::core::I2CDevice;
2729
use spidev::SpidevTransfer;
2830

2931
/// Empty struct that provides delay functionality on top of `thread::sleep`
@@ -139,6 +141,87 @@ impl ops::DerefMut for Pin {
139141
}
140142
}
141143

144+
/// Newtype around [`i2cdev::linux::LinuxI2CDevice`] that implements the `embedded-hal` traits
145+
///
146+
/// [`i2cdev::linux::LinuxI2CDevice`]: https://docs.rs/i2cdev/0.3.1/i2cdev/linux/struct.LinuxI2CDevice.html
147+
pub struct I2cdev {
148+
inner: i2cdev::linux::LinuxI2CDevice,
149+
path: PathBuf,
150+
address: Option<u8>,
151+
}
152+
153+
impl I2cdev {
154+
/// See [`i2cdev::linux::LinuxI2CDevice::new`][0] for details.
155+
///
156+
/// [0]: https://docs.rs/i2cdev/0.3.1/i2cdev/linux/struct.LinuxI2CDevice.html#method.new
157+
pub fn new<P>(path: P) -> Result<Self, i2cdev::linux::LinuxI2CError>
158+
where
159+
P: AsRef<Path>,
160+
{
161+
let dev = I2cdev {
162+
path: path.as_ref().to_path_buf(),
163+
inner: i2cdev::linux::LinuxI2CDevice::new(path, 0)?,
164+
address: None,
165+
};
166+
Ok(dev)
167+
}
168+
169+
fn set_address(&mut self, address: u8) -> Result<(), i2cdev::linux::LinuxI2CError> {
170+
if self.address != Some(address) {
171+
self.inner = i2cdev::linux::LinuxI2CDevice::new(&self.path, address as u16)?;
172+
self.address = Some(address);
173+
}
174+
Ok(())
175+
}
176+
}
177+
178+
impl hal::blocking::i2c::Read for I2cdev {
179+
type Error = i2cdev::linux::LinuxI2CError;
180+
181+
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
182+
self.set_address(address)?;
183+
self.inner.read(buffer)
184+
}
185+
}
186+
187+
impl hal::blocking::i2c::Write for I2cdev {
188+
type Error = i2cdev::linux::LinuxI2CError;
189+
190+
fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
191+
self.set_address(address)?;
192+
self.inner.write(bytes)
193+
}
194+
}
195+
196+
impl hal::blocking::i2c::WriteRead for I2cdev {
197+
type Error = i2cdev::linux::LinuxI2CError;
198+
199+
fn write_read(
200+
&mut self,
201+
address: u8,
202+
bytes: &[u8],
203+
buffer: &mut [u8],
204+
) -> Result<(), Self::Error> {
205+
self.set_address(address)?;
206+
self.inner.write(bytes)?;
207+
self.inner.read(buffer)
208+
}
209+
}
210+
211+
impl ops::Deref for I2cdev {
212+
type Target = i2cdev::linux::LinuxI2CDevice;
213+
214+
fn deref(&self) -> &Self::Target {
215+
&self.inner
216+
}
217+
}
218+
219+
impl ops::DerefMut for I2cdev {
220+
fn deref_mut(&mut self) -> &mut Self::Target {
221+
&mut self.inner
222+
}
223+
}
224+
142225
/// Newtype around [`spidev::Spidev`] that implements the `embedded-hal` traits
143226
///
144227
/// [`spidev::Spidev`]: https://docs.rs/spidev/0.3.0/spidev/struct.Spidev.html

0 commit comments

Comments
 (0)