Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
77: Adapt to embedded-hal-1.0.0-alpha.7 r=posborne a=eldruin

For the iterator methods I just collected the results. I have not looked into really using an iterating interface but merging this would be a first step and if there is interest we can look into that later on.
Fixes rust-embedded#76 

Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
  • Loading branch information
bors[bot] and eldruin authored Feb 12, 2022
2 parents 62966e9 + 70012b4 commit 5259b32
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 38 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async-tokio = ["gpio-cdev/async-tokio"]
default = [ "gpio_cdev", "gpio_sysfs" ]

[dependencies]
embedded-hal = "=1.0.0-alpha.6"
embedded-hal = "=1.0.0-alpha.7"
gpio-cdev = { version = "0.5.1", optional = true }
sysfs_gpio = { version = "0.6.1", optional = true }
i2cdev = "0.5.1"
Expand Down
6 changes: 3 additions & 3 deletions examples/transactional-i2c.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use embedded_hal::i2c::blocking::{Operation as I2cOperation, Transactional};
use embedded_hal::i2c::blocking::{I2c, Operation as I2cOperation};
use linux_embedded_hal::I2cdev;

const ADDR: u8 = 0x12;
Expand All @@ -9,7 +9,7 @@ struct Driver<I2C> {

impl<I2C> Driver<I2C>
where
I2C: Transactional,
I2C: I2c,
{
pub fn new(i2c: I2C) -> Self {
Driver { i2c }
Expand All @@ -21,7 +21,7 @@ where
I2cOperation::Write(&[0xAB]),
I2cOperation::Read(&mut read_buffer),
];
self.i2c.exec(ADDR, &mut ops).and(Ok(read_buffer[0]))
self.i2c.transaction(ADDR, &mut ops).and(Ok(read_buffer[0]))
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/cdev_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ fn state_to_value(state: embedded_hal::digital::PinState, is_active_low: bool) -
}
}

impl embedded_hal::digital::blocking::OutputPin for CdevPin {
impl embedded_hal::digital::ErrorType for CdevPin {
type Error = gpio_cdev::errors::Error;
}

impl embedded_hal::digital::blocking::OutputPin for CdevPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.0.set_value(state_to_value(
embedded_hal::digital::PinState::Low,
Expand All @@ -72,8 +74,6 @@ impl embedded_hal::digital::blocking::OutputPin for CdevPin {
}

impl embedded_hal::digital::blocking::InputPin for CdevPin {
type Error = gpio_cdev::errors::Error;

fn is_high(&self) -> Result<bool, Self::Error> {
self.0.get_value().map(|val| {
val == state_to_value(
Expand Down
52 changes: 36 additions & 16 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,32 +57,32 @@ impl ops::DerefMut for I2cdev {

mod embedded_hal_impl {
use super::*;
use embedded_hal::i2c::blocking::{
Operation as I2cOperation, Read, Transactional, Write, WriteRead,
};
use embedded_hal::i2c::blocking::{I2c, Operation as I2cOperation};
use embedded_hal::i2c::ErrorType;
use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer};
use i2cdev::linux::LinuxI2CMessage;

impl Read for I2cdev {
impl ErrorType for I2cdev {
type Error = I2CError;
}

impl I2c for I2cdev {
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.set_address(address)?;
self.inner.read(buffer).map_err(|err| I2CError { err })
}
}

impl Write for I2cdev {
type Error = I2CError;

fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.set_address(address)?;
self.inner.write(bytes).map_err(|err| I2CError { err })
}
}

impl WriteRead for I2cdev {
type Error = I2CError;
fn write_iter<B>(&mut self, address: u8, bytes: B) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>,
{
let bytes: Vec<_> = bytes.into_iter().collect();
self.write(address, &bytes)
}

fn write_read(
&mut self,
Expand All @@ -97,12 +97,24 @@ mod embedded_hal_impl {
.map(drop)
.map_err(|err| I2CError { err })
}
}

impl Transactional for I2cdev {
type Error = I2CError;
fn write_iter_read<B>(
&mut self,
address: u8,
bytes: B,
buffer: &mut [u8],
) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>,
{
let bytes: Vec<_> = bytes.into_iter().collect();
self.transaction(
address,
&mut [I2cOperation::Write(&bytes), I2cOperation::Read(buffer)],
)
}

fn exec(
fn transaction(
&mut self,
address: u8,
operations: &mut [I2cOperation],
Expand All @@ -123,6 +135,14 @@ mod embedded_hal_impl {
.map(drop)
.map_err(|err| I2CError { err })
}

fn transaction_iter<'a, O>(&mut self, address: u8, operations: O) -> Result<(), Self::Error>
where
O: IntoIterator<Item = I2cOperation<'a>>,
{
let mut ops: Vec<_> = operations.into_iter().collect();
self.transaction(address, &mut ops)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ pub use crate::delay::Delay;
pub use crate::i2c::{I2CError, I2cdev};
pub use crate::serial::{Serial, SerialError};
pub use crate::spi::{SPIError, Spidev};
pub use crate::timer::SysTimer;
pub use crate::timer::{CountDown, Periodic, SysTimer};
6 changes: 3 additions & 3 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ fn translate_io_errors(err: std::io::Error) -> nb::Error<SerialError> {
}
}

impl embedded_hal::serial::nb::Read<u8> for Serial {
impl embedded_hal::serial::ErrorType for Serial {
type Error = SerialError;
}

impl embedded_hal::serial::nb::Read<u8> for Serial {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let mut buffer = [0; 1];
let bytes_read = self.0.read(&mut buffer).map_err(translate_io_errors)?;
Expand All @@ -44,8 +46,6 @@ impl embedded_hal::serial::nb::Read<u8> for Serial {
}

impl embedded_hal::serial::nb::Write<u8> for Serial {
type Error = SerialError;

fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.0.write(&[word]).map_err(translate_io_errors)?;
Ok(())
Expand Down
11 changes: 4 additions & 7 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ mod embedded_hal_impl {
use embedded_hal::spi::blocking::{
Operation as SpiOperation, Transactional, Transfer, TransferInplace, Write,
};
use embedded_hal::spi::ErrorType;
use spidev::SpidevTransfer;
use std::io::Write as _;

impl Transfer<u8> for Spidev {
impl ErrorType for Spidev {
type Error = SPIError;
}

impl Transfer<u8> for Spidev {
fn transfer<'b>(&mut self, read: &'b mut [u8], write: &[u8]) -> Result<(), Self::Error> {
self.0
.transfer(&mut SpidevTransfer::read_write(&write, read))
Expand All @@ -57,8 +60,6 @@ mod embedded_hal_impl {
}

impl TransferInplace<u8> for Spidev {
type Error = SPIError;

fn transfer_inplace<'b>(&mut self, buffer: &'b mut [u8]) -> Result<(), Self::Error> {
let tx = buffer.to_owned();
self.0
Expand All @@ -68,17 +69,13 @@ mod embedded_hal_impl {
}

impl Write<u8> for Spidev {
type Error = SPIError;

fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.0.write_all(buffer).map_err(|err| SPIError { err })
}
}

/// Transactional implementation batches SPI operations into a single transaction
impl Transactional<u8> for Spidev {
type Error = SPIError;

fn exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> {
// Map types from generic to linux objects
let mut messages: Vec<_> = operations
Expand Down
6 changes: 3 additions & 3 deletions src/sysfs_pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ impl SysfsPin {
}
}

impl embedded_hal::digital::blocking::OutputPin for SysfsPin {
impl embedded_hal::digital::ErrorType for SysfsPin {
type Error = sysfs_gpio::Error;
}

impl embedded_hal::digital::blocking::OutputPin for SysfsPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
if self.0.get_active_low()? {
self.0.set_value(1)
Expand All @@ -49,8 +51,6 @@ impl embedded_hal::digital::blocking::OutputPin for SysfsPin {
}

impl embedded_hal::digital::blocking::InputPin for SysfsPin {
type Error = sysfs_gpio::Error;

fn is_high(&self) -> Result<bool, Self::Error> {
if !self.0.get_active_low()? {
self.0.get_value().map(|val| val != 0)
Expand Down
89 changes: 88 additions & 1 deletion src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,94 @@
use core::convert::Infallible;
use std::time::{Duration, Instant};

use embedded_hal::timer::{nb::CountDown, Periodic};
/// Marker trait that indicates that a timer is periodic
pub trait Periodic {}

/// A count down timer
///
/// Note that this is borrowed from `embedded-hal` 0.2.x and will be in use until the `1.x` version provides one.
///
/// # Contract
///
/// - `self.start(count); block!(self.wait());` MUST block for AT LEAST the time specified by
/// `count`.
///
/// *Note* that the implementer doesn't necessarily have to be a *downcounting* timer; it could also
/// be an *upcounting* timer as long as the above contract is upheld.
///
/// # Examples
///
/// You can use this timer to create delays
///
/// ```
/// use std::time::Duration;
/// use nb::block;
/// use linux_embedded_hal::{CountDown, SysTimer};
///
/// fn main() {
/// let mut led: Led = {
/// // ..
/// # Led
/// };
/// let mut timer = SysTimer::new();
///
/// Led.on();
/// timer.start(Duration::from_millis(1000)).unwrap();
/// block!(timer.wait()); // blocks for 1 second
/// Led.off();
/// }
///
/// # use core::convert::Infallible;
/// # struct Seconds(u32);
/// # trait U32Ext { fn s(self) -> Seconds; }
/// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } }
/// # struct Led;
/// # impl Led {
/// # pub fn off(&mut self) {}
/// # pub fn on(&mut self) {}
/// # }
/// ```
pub trait CountDown {
/// An enumeration of `CountDown` errors.
///
/// For infallible implementations, will be `Infallible`
type Error: core::fmt::Debug;

/// The unit of time used by this timer
type Time;

/// Starts a new count down
fn start<T>(&mut self, count: T) -> Result<(), Self::Error>
where
T: Into<Self::Time>;

/// Non-blockingly "waits" until the count down finishes
///
/// # Contract
///
/// - If `Self: Periodic`, the timer will start a new count down right after the last one
/// finishes.
/// - Otherwise the behavior of calling `wait` after the last call returned `Ok` is UNSPECIFIED.
/// Implementers are suggested to panic on this scenario to signal a programmer error.
fn wait(&mut self) -> nb::Result<(), Self::Error>;
}

impl<T: CountDown> CountDown for &mut T {
type Error = T::Error;

type Time = T::Time;

fn start<TIME>(&mut self, count: TIME) -> Result<(), Self::Error>
where
TIME: Into<Self::Time>,
{
T::start(self, count)
}

fn wait(&mut self) -> nb::Result<(), Self::Error> {
T::wait(self)
}
}

/// A periodic timer based on [`std::time::Instant`][instant], which is a
/// monotonically nondecreasing clock.
Expand Down

0 comments on commit 5259b32

Please sign in to comment.