-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from ryankurte/feature/hal
Adding HAL to support abstract underlying devices
- Loading branch information
Showing
9 changed files
with
853 additions
and
374 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "embedded-spi" | ||
description = "Rust embedded driver helper package (new releases at spi-hal)" | ||
description = "Rust embedded driver helper package" | ||
repository = "https://github.com/ryankurte/rust-spi-hal" | ||
version = "0.6.2" | ||
authors = ["Ryan Kurte <[email protected]>"] | ||
|
@@ -17,23 +17,18 @@ hal-linux = [ "linux-embedded-hal" ] | |
default = [ "mock", "hal", "hal-cp2130", "hal-linux" ] | ||
|
||
[dependencies] | ||
embedded-hal = { version = "0.2.3", features = ["unproven"] } | ||
embedded-hal = { version = "1.0.0-alpha.0" } | ||
linux-embedded-hal = { version = "0.3.0", optional = true } | ||
libc = { version = "0.2.54", optional = true } | ||
log = "0.4.6" | ||
serde = { version = "1.0.91", features = ["derive"], optional = true } | ||
toml = { version = "0.5.1", optional = true } | ||
structopt = { version = "0.3.11", optional = true } | ||
simplelog = { version = "0.5.3", optional = true } | ||
driver-cp2130 = { version = "0.3.1", optional = true } | ||
driver-cp2130 = { version = "1.0.0-alpha.0", optional = true, features = ["transactional"] } | ||
|
||
|
||
[patch.crates-io] | ||
#embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" } | ||
#linux-embedded-hal = { git = "https://github.com/ryankurte/linux-embedded-hal.git", branch = "feature/spi-transactions" } | ||
#driver-cp2130 = { git = "https://github.com/ryankurte/rust-driver-cp2130", branch = "master" } | ||
embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" } | ||
linux-embedded-hal = { git = "https://github.com/ryankurte/linux-embedded-hal.git", branch = "feature/spi-transactions" } | ||
|
||
|
||
#driver-cp2130 = { path = "../rust-driver-cp2130", optional=true } | ||
#embedded-hal = { path = "../embedded-hal" } | ||
#linux-embedded-hal = { path = "../linux-embedded-hal" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
|
||
use std::convert::{TryFrom, TryInto}; | ||
|
||
use driver_cp2130::prelude::*; | ||
|
||
use crate::*; | ||
use super::{HalInst, HalPins, HalBase, HalSpi, HalInputPin, HalOutputPin, HalError, SpiConfig, PinConfig}; | ||
|
||
/// Convert a generic SPI config object into a CP2130 object | ||
impl TryInto<driver_cp2130::SpiConfig> for SpiConfig { | ||
type Error = HalError; | ||
|
||
fn try_into(self) -> Result<driver_cp2130::SpiConfig, Self::Error> { | ||
Ok(driver_cp2130::SpiConfig { | ||
clock: SpiClock::try_from(self.baud as usize)?, | ||
..driver_cp2130::SpiConfig::default() | ||
}) | ||
} | ||
} | ||
|
||
/// CP2130 `Hal` implementation | ||
pub struct Cp2130Driver; | ||
|
||
impl Cp2130Driver { | ||
/// Load base CP2130 instance | ||
pub fn new<'a>(index: usize, spi: &SpiConfig, pins: &PinConfig) -> Result<HalInst<'a>, HalError> { | ||
// Fetch the matching device and descriptor | ||
let (device, descriptor) = Manager::device(Filter::default(), index)?; | ||
|
||
// Create CP2130 object | ||
let cp2130 = Cp2130::new(device, descriptor)?; | ||
|
||
// Connect SPI | ||
let spi_config = spi.clone().try_into()?; | ||
let spi = cp2130.spi(0, spi_config)?; | ||
|
||
// Connect pins | ||
|
||
let chip_select = cp2130.gpio_out(pins.chip_select as u8, GpioMode::PushPull, GpioLevel::High)?; | ||
|
||
let reset = cp2130.gpio_out(pins.reset as u8, GpioMode::PushPull, GpioLevel::High)?; | ||
|
||
let busy = match pins.busy { | ||
Some(p) => HalInputPin::Cp2130(cp2130.gpio_in(p as u8)?), | ||
None => HalInputPin::None, | ||
}; | ||
|
||
let ready = match pins.ready { | ||
Some(p) => HalInputPin::Cp2130(cp2130.gpio_in(p as u8)?), | ||
None => HalInputPin::None, | ||
}; | ||
|
||
let pins = HalPins { | ||
cs: HalOutputPin::Cp2130(chip_select), | ||
reset: HalOutputPin::Cp2130(reset), | ||
busy, | ||
ready, | ||
}; | ||
|
||
// Return object | ||
Ok(HalInst{ | ||
base: HalBase::Cp2130(cp2130), | ||
spi: HalSpi::Cp2130(spi), | ||
pins, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
/// Error type combining SPI and Pin errors for utility | ||
#[derive(Debug)] | ||
pub enum HalError { | ||
InvalidConfig, | ||
InvalidSpiMode, | ||
NoPin, | ||
|
||
#[cfg(feature = "hal-cp2130")] | ||
Cp2130(driver_cp2130::Error), | ||
|
||
#[cfg(feature = "hal-linux")] | ||
Io(std::io::ErrorKind), | ||
|
||
#[cfg(feature = "hal-linux")] | ||
Sysfs(linux_embedded_hal::sysfs_gpio::Error), | ||
} | ||
|
||
#[cfg(feature = "hal-cp2130")] | ||
impl From<driver_cp2130::Error> for HalError { | ||
fn from(e: driver_cp2130::Error) -> Self { | ||
Self::Cp2130(e) | ||
} | ||
} | ||
|
||
#[cfg(feature = "hal-linux")] | ||
impl From<std::io::Error> for HalError { | ||
fn from(e: std::io::Error) -> Self { | ||
Self::Io(e.kind()) | ||
} | ||
} | ||
|
||
#[cfg(feature = "hal-linux")] | ||
impl From<linux_embedded_hal::sysfs_gpio::Error> for HalError { | ||
fn from(e: linux_embedded_hal::sysfs_gpio::Error) -> Self { | ||
Self::Sysfs(e) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
|
||
extern crate linux_embedded_hal; | ||
pub use linux_embedded_hal::sysfs_gpio::{Direction, Error as PinError}; | ||
pub use linux_embedded_hal::{spidev, Delay, SysfsPin as Pindev, Spidev, spidev::SpiModeFlags}; | ||
|
||
use super::*; | ||
|
||
pub struct LinuxDriver; | ||
|
||
impl LinuxDriver { | ||
/// Load an SPI device using the provided configuration | ||
pub fn new<'a>(path: &str, spi: &SpiConfig, pins: &PinConfig) -> Result<HalInst<'a>, HalError> { | ||
let mut flags = match spi.mode { | ||
0 => SpiModeFlags::SPI_MODE_0, | ||
1 => SpiModeFlags::SPI_MODE_1, | ||
2 => SpiModeFlags::SPI_MODE_2, | ||
3 => SpiModeFlags::SPI_MODE_3, | ||
_ => return Err(HalError::InvalidSpiMode), | ||
}; | ||
|
||
flags |= SpiModeFlags::SPI_NO_CS; | ||
|
||
debug!( | ||
"Conecting to spi: {} at {} baud with mode: {:?}", | ||
path, spi.baud, flags | ||
); | ||
|
||
let spi = load_spi(path, spi.baud, flags)?; | ||
|
||
let pins = Self::load_pins(pins)?; | ||
|
||
Ok(HalInst{ | ||
base: HalBase::None, | ||
spi: HalSpi::Linux(spi), | ||
pins, | ||
}) | ||
} | ||
|
||
/// Load pins using the provided config | ||
fn load_pins<'a>(pins: &PinConfig) -> Result<HalPins<'a>, HalError> { | ||
|
||
let chip_select = load_pin(pins.chip_select, Direction::Out)?; | ||
|
||
let reset = load_pin(pins.reset, Direction::Out)?; | ||
|
||
let busy = match pins.busy { | ||
Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?), | ||
None => HalInputPin::None, | ||
}; | ||
|
||
let ready = match pins.ready { | ||
Some(p) => HalInputPin::Linux(load_pin(p, Direction::In)?), | ||
None => HalInputPin::None, | ||
}; | ||
|
||
let pins = HalPins{ | ||
cs: HalOutputPin::Linux(chip_select), | ||
reset: HalOutputPin::Linux(reset), | ||
busy, | ||
ready, | ||
}; | ||
|
||
Ok(pins) | ||
} | ||
} | ||
|
||
/// Load an SPI device using the provided configuration | ||
fn load_spi(path: &str, baud: u32, mode: spidev::SpiModeFlags) -> Result<Spidev, HalError> { | ||
debug!( | ||
"Conecting to spi: {} at {} baud with mode: {:?}", | ||
path, baud, mode | ||
); | ||
|
||
let mut spi = Spidev::open(path)?; | ||
|
||
let mut config = spidev::SpidevOptions::new(); | ||
config.mode(SpiModeFlags::SPI_MODE_0 | SpiModeFlags::SPI_NO_CS); | ||
config.max_speed_hz(baud); | ||
spi.configure(&config)?; | ||
|
||
Ok(spi) | ||
} | ||
|
||
/// Load a Pin using the provided configuration | ||
fn load_pin(index: u64, direction: Direction) -> Result<Pindev, HalError> { | ||
debug!( | ||
"Connecting to pin: {} with direction: {:?}", | ||
index, direction | ||
); | ||
|
||
let p = Pindev::new(index); | ||
p.export()?; | ||
p.set_direction(direction)?; | ||
|
||
Ok(p) | ||
} |
Oops, something went wrong.