Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated to embedded-hal v1 #7

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/qa.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ jobs:
matrix:
target:
- thumbv7m-none-eabi
- thumbv8m.main-none-eabihf
- riscv32imac-unknown-none-elf
rust:
- stable
- beta
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ readme = "README.md"
documentation = "https://docs.rs/pca9539"

[dependencies]
embedded-hal = { version = "0.2.7", features = ["unproven"] }
embedded-hal = { version = "1.0.0" }
bitmaps = { version = "3.1.0", default-features = false }
cortex-m = { version = "0.7.4", optional = true }
spin = { version = "0.9.8", optional = true }
Expand Down
38 changes: 22 additions & 16 deletions src/example.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
//! Dummy I2C bus for examples
use core::convert::Infallible;
use embedded_hal::blocking::i2c::{Read, SevenBitAddress, Write};
use embedded_hal::i2c::{ErrorType, I2c, Operation, SevenBitAddress};

#[derive(Default)]
pub struct DummyI2CBus {
/// Command byte of last write operation
previous_register: u8,
}

impl Write for DummyI2CBus {
impl ErrorType for DummyI2CBus {
type Error = Infallible;

fn write(&mut self, _address: SevenBitAddress, _bytes: &[u8]) -> Result<(), Self::Error> {
self.previous_register = _bytes[0];
Ok(())
}
}

impl Read for DummyI2CBus {
type Error = Infallible;

fn read(&mut self, _address: SevenBitAddress, buffer: &mut [u8]) -> Result<(), Self::Error> {
match self.previous_register {
0x00 => buffer[0] = 0b0010_0110,
0x01 => buffer[0] = 0b1110_0101,
_ => {}
};
impl I2c<SevenBitAddress> for DummyI2CBus {
fn transaction(
&mut self,
_address: SevenBitAddress,
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error> {
for operation in operations {
match operation {
Operation::Read(data) => {
match self.previous_register {
0x00 => data[0] = 0b0010_0110,
0x01 => data[0] = 0b1110_0101,
_ => {}
};
}
Operation::Write(data) => {
self.previous_register = data[0];
}
}
}

Ok(())
}
Expand Down
37 changes: 22 additions & 15 deletions src/expander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ use core::cell::RefCell;
use core::fmt::{Debug, Formatter};
#[cfg(feature = "cortex-m")]
use cortex_m::interrupt::Mutex as CsMutex;
use embedded_hal::blocking::i2c::{Read, SevenBitAddress, Write};
use embedded_hal::digital::ErrorKind;
use embedded_hal::i2c::{I2c, SevenBitAddress};
use heapless::String;
#[cfg(feature = "spin")]
use spin::Mutex as SpinMutex;
Expand Down Expand Up @@ -129,7 +130,7 @@ pub enum Mode {
/// Abstraction of [PCA9539](<https://www.ti.com/lit/ds/symlink/pca9539.pdf?ts=1649342250975>) I/O expander
pub struct PCA9539<B>
where
B: Write<SevenBitAddress> + Read<SevenBitAddress>,
B: I2c<SevenBitAddress>,
{
bus: B,

Expand Down Expand Up @@ -164,9 +165,9 @@ where

/// Wrapped I2C error when refreshing input state
/// Reading input state consists of one write, followed by a read operation
pub enum RefreshInputError<B: Write + Read<u8>> {
WriteError(<B as Write>::Error),
ReadError(<B as Read>::Error),
pub enum RefreshInputError<B: I2c<SevenBitAddress>> {
WriteError(B::Error),
ReadError(B::Error),
}

const COMMAND_INPUT_0: u8 = 0x00;
Expand All @@ -183,7 +184,7 @@ const COMMAND_CONF_1: u8 = 0x07;

impl<B> PCA9539<B>
where
B: Write<SevenBitAddress> + Read<SevenBitAddress>,
B: I2c<SevenBitAddress>,
{
pub fn new(bus: B, address: u8) -> Self {
let mut expander = Self {
Expand Down Expand Up @@ -232,7 +233,7 @@ where
}

/// Switches the given pin to the input/output mode by adjusting the configuration register
pub fn set_mode(&mut self, bank: Bank, id: PinID, mode: Mode) -> Result<(), <B as Write>::Error> {
pub fn set_mode(&mut self, bank: Bank, id: PinID, mode: Mode) -> Result<(), B::Error> {
match bank {
Bank::Bank0 => self.configuration_0.set(id as usize, mode.into()),
Bank::Bank1 => self.configuration_1.set(id as usize, mode.into()),
Expand All @@ -241,7 +242,7 @@ where
}

/// Switches all pins of the given bank to output/input mode1
pub fn set_mode_all(&mut self, bank: Bank, mode: Mode) -> Result<(), <B as Write>::Error> {
pub fn set_mode_all(&mut self, bank: Bank, mode: Mode) -> Result<(), B::Error> {
let mut bitset = Bitmap::<8>::new();

if mode == Mode::Input {
Expand All @@ -267,7 +268,7 @@ where
}

/// Sets output state for all pins of a bank
pub fn set_state_all(&mut self, bank: Bank, is_high: bool) -> Result<(), <B as Write>::Error> {
pub fn set_state_all(&mut self, bank: Bank, is_high: bool) -> Result<(), B::Error> {
let mut bitset = Bitmap::<8>::new();

if is_high {
Expand All @@ -282,7 +283,7 @@ where
}

/// Reveres/Resets the input polarity of the given pin
pub fn reverse_polarity(&mut self, bank: Bank, id: PinID, reversed: bool) -> Result<(), <B as Write>::Error> {
pub fn reverse_polarity(&mut self, bank: Bank, id: PinID, reversed: bool) -> Result<(), B::Error> {
match bank {
Bank::Bank0 => self.polarity_0.set(id as usize, reversed),
Bank::Bank1 => self.polarity_1.set(id as usize, reversed),
Expand Down Expand Up @@ -332,7 +333,7 @@ where
}

/// Writes the configuration register of the given bank
fn write_conf(&mut self, bank: Bank) -> Result<(), <B as Write>::Error> {
fn write_conf(&mut self, bank: Bank) -> Result<(), B::Error> {
match bank {
Bank::Bank0 => self
.bus
Expand All @@ -344,15 +345,15 @@ where
}

/// Writes the output register of the given bank
pub fn write_output_state(&mut self, bank: Bank) -> Result<(), <B as Write>::Error> {
pub fn write_output_state(&mut self, bank: Bank) -> Result<(), B::Error> {
match bank {
Bank::Bank0 => self.bus.write(self.address, &[COMMAND_OUTPUT_0, *self.output_0.as_value()]),
Bank::Bank1 => self.bus.write(self.address, &[COMMAND_OUTPUT_1, *self.output_1.as_value()]),
}
}

/// Writes the polarity register of the given bank
fn write_polarity(&mut self, bank: Bank) -> Result<(), <B as Write>::Error> {
fn write_polarity(&mut self, bank: Bank) -> Result<(), B::Error> {
match bank {
Bank::Bank0 => self.bus.write(self.address, &[COMMAND_POLARITY_0, *self.polarity_0.as_value()]),
Bank::Bank1 => self.bus.write(self.address, &[COMMAND_POLARITY_1, *self.polarity_1.as_value()]),
Expand All @@ -369,7 +370,7 @@ impl From<Mode> for bool {
}
}

impl<B: Read<u8> + Write> Debug for RefreshInputError<B> {
impl<B: I2c> Debug for RefreshInputError<B> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
RefreshInputError::WriteError(_) => f.write_str("RefreshInputError::WriteError"),
Expand All @@ -378,11 +379,17 @@ impl<B: Read<u8> + Write> Debug for RefreshInputError<B> {
}
}

impl<B: Read<u8> + Write> RefreshInputError<B> {
impl<B: I2c> RefreshInputError<B> {
pub fn to_string(&self) -> String<10> {
match self {
RefreshInputError::WriteError(_) => String::try_from("WriteError").unwrap(),
RefreshInputError::ReadError(_) => String::try_from("ReadError").unwrap(),
}
}
}

impl<B: I2c> embedded_hal::digital::Error for RefreshInputError<B> {
fn kind(&self) -> ErrorKind {
ErrorKind::Other
}
}
28 changes: 14 additions & 14 deletions src/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
use crate::expander::PCA9539;
use core::cell::RefCell;
use core::ops::DerefMut;
use embedded_hal::blocking::i2c::{Read, Write};

/// Manages the access of pins to expander reference
pub trait RefGuard<B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
fn access<F>(&self, f: F)
where
Expand All @@ -20,20 +19,20 @@ where
/// Guard which is neither Send or Sync, but is the most efficient
pub struct LockFreeGuard<'a, B>
where
B: Write + Read,
B: I2c<SevenBitAddress>,
{
expander: RefCell<&'a mut PCA9539<B>>,
}

impl<'a, B: Write + Read> LockFreeGuard<'a, B> {
impl<'a, B: I2c<SevenBitAddress>> LockFreeGuard<'a, B> {
pub fn new(expander: RefCell<&'a mut PCA9539<B>>) -> Self {
LockFreeGuard { expander }
}
}

impl<'a, B> RefGuard<B> for LockFreeGuard<'a, B>
impl<B> RefGuard<B> for LockFreeGuard<'_, B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
fn access<F>(&self, mut f: F)
where
Expand All @@ -45,27 +44,28 @@ where

#[cfg(feature = "cortex-m")]
use cortex_m::interrupt::Mutex as CsMutex;
use embedded_hal::i2c::{I2c, SevenBitAddress};

/// Guard bases on Cortex-M mutex, which is using critical sections internally
#[cfg(feature = "cortex-m")]
pub struct CsMutexGuard<'a, B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
expander: CsMutex<RefCell<&'a mut PCA9539<B>>>,
}

#[cfg(feature = "cortex-m")]
impl<'a, B: Write + Read> CsMutexGuard<'a, B> {
impl<'a, B: I2c<SevenBitAddress>> CsMutexGuard<'a, B> {
pub fn new(expander: CsMutex<RefCell<&'a mut PCA9539<B>>>) -> Self {
CsMutexGuard { expander }
}
}

#[cfg(feature = "cortex-m")]
impl<'a, B> RefGuard<B> for CsMutexGuard<'a, B>
impl<B> RefGuard<B> for CsMutexGuard<'_, B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
fn access<F>(&self, mut f: F)
where
Expand All @@ -83,22 +83,22 @@ use spin::Mutex as SpinMutex;
#[cfg(feature = "spin")]
pub struct SpinGuard<'a, B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
expander: SpinMutex<RefCell<&'a mut PCA9539<B>>>,
}

#[cfg(feature = "spin")]
impl<'a, B: Write + Read> SpinGuard<'a, B> {
impl<'a, B: I2c<SevenBitAddress>> SpinGuard<'a, B> {
pub fn new(expander: SpinMutex<RefCell<&'a mut PCA9539<B>>>) -> Self {
SpinGuard { expander }
}
}

#[cfg(feature = "spin")]
impl<'a, B> RefGuard<B> for SpinGuard<'a, B>
impl<B> RefGuard<B> for SpinGuard<'_, B>
where
B: Write + Read<u8>,
B: I2c<SevenBitAddress>,
{
fn access<F>(&self, mut f: F)
where
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
//! use pca9539::expander::Bank::Bank0;
//! use pca9539::expander::PCA9539;
//! use pca9539::expander::PinID::Pin1;
//! use embedded_hal::digital::v2::InputPin;
//! use embedded_hal::digital::InputPin;
//!
//! let i2c_bus = DummyI2CBus::default();
//! let mut expander = PCA9539::new(i2c_bus, 0x74);
//! let pins = expander.pins();
//!
//! let pin01 = pins.get_pin(Bank0, Pin1);
//! let mut pin01 = pins.get_pin(Bank0, Pin1);
//! assert!(pin01.is_high().unwrap());
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "strict", deny(warnings))]
Expand Down
Loading
Loading