Skip to content

Commit 92960cc

Browse files
bors[bot]Morgan Roff
and
Morgan Roff
authored
Merge #60
60: Implementation of embedded_hal::digital::IoPin r=eldruin a=MorganR This is just a draft, and is pending the PR merge of an [IoPin implementation](rust-embedded/embedded-hal#269) into embedded_hal. I've verified it with a [no-std DHT11 driver based on the IoPin PR](https://github.com/MorganR/rust-simple-sensors/blob/main/src/dht11.rs). Co-authored-by: Morgan Roff <mroff@google.com>
2 parents ee0e6af + b78acf4 commit 92960cc

File tree

3 files changed

+119
-17
lines changed

3 files changed

+119
-17
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Implement `embedded_hal::digital::blocking::IoPin` for `CdevPin` and `SysfsPin`
13+
1014
## [v0.4.0-alpha.1] - 2021-09-27
1115

1216
### Changed

src/cdev_pin.rs

+95-17
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,132 @@
55
/// Newtype around [`gpio_cdev::LineHandle`] that implements the `embedded-hal` traits
66
///
77
/// [`gpio_cdev::LineHandle`]: https://docs.rs/gpio-cdev/0.5.0/gpio_cdev/struct.LineHandle.html
8-
pub struct CdevPin(pub gpio_cdev::LineHandle, bool);
8+
pub struct CdevPin(pub gpio_cdev::LineHandle, gpio_cdev::LineInfo);
99

1010
impl CdevPin {
1111
/// See [`gpio_cdev::Line::request`][0] for details.
1212
///
1313
/// [0]: https://docs.rs/gpio-cdev/0.5.0/gpio_cdev/struct.Line.html#method.request
1414
pub fn new(handle: gpio_cdev::LineHandle) -> Result<Self, gpio_cdev::errors::Error> {
1515
let info = handle.line().info()?;
16-
Ok(CdevPin(handle, info.is_active_low()))
16+
Ok(CdevPin(handle, info))
17+
}
18+
19+
fn get_input_flags(&self) -> gpio_cdev::LineRequestFlags {
20+
if self.1.is_active_low() {
21+
return gpio_cdev::LineRequestFlags::INPUT | gpio_cdev::LineRequestFlags::ACTIVE_LOW;
22+
}
23+
gpio_cdev::LineRequestFlags::INPUT
24+
}
25+
26+
fn get_output_flags(&self) -> gpio_cdev::LineRequestFlags {
27+
let mut flags = gpio_cdev::LineRequestFlags::OUTPUT;
28+
if self.1.is_active_low() {
29+
flags.insert(gpio_cdev::LineRequestFlags::ACTIVE_LOW);
30+
}
31+
if self.1.is_open_drain() {
32+
flags.insert(gpio_cdev::LineRequestFlags::OPEN_DRAIN);
33+
} else if self.1.is_open_source() {
34+
flags.insert(gpio_cdev::LineRequestFlags::OPEN_SOURCE);
35+
}
36+
return flags;
37+
}
38+
}
39+
40+
/// Converts a pin state to the gpio_cdev compatible numeric value, accounting
41+
/// for the active_low condition.
42+
fn state_to_value(state: embedded_hal::digital::PinState, is_active_low: bool) -> u8 {
43+
if is_active_low {
44+
match state {
45+
embedded_hal::digital::PinState::High => 0,
46+
embedded_hal::digital::PinState::Low => 1,
47+
}
48+
} else {
49+
match state {
50+
embedded_hal::digital::PinState::High => 1,
51+
embedded_hal::digital::PinState::Low => 0,
52+
}
1753
}
1854
}
1955

2056
impl embedded_hal::digital::blocking::OutputPin for CdevPin {
2157
type Error = gpio_cdev::errors::Error;
2258

2359
fn set_low(&mut self) -> Result<(), Self::Error> {
24-
if self.1 {
25-
self.0.set_value(1)
26-
} else {
27-
self.0.set_value(0)
28-
}
60+
self.0.set_value(state_to_value(
61+
embedded_hal::digital::PinState::Low,
62+
self.1.is_active_low(),
63+
))
2964
}
3065

3166
fn set_high(&mut self) -> Result<(), Self::Error> {
32-
if self.1 {
33-
self.0.set_value(0)
34-
} else {
35-
self.0.set_value(1)
36-
}
67+
self.0.set_value(state_to_value(
68+
embedded_hal::digital::PinState::High,
69+
self.1.is_active_low(),
70+
))
3771
}
3872
}
3973

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

4377
fn is_high(&self) -> Result<bool, Self::Error> {
44-
if !self.1 {
45-
self.0.get_value().map(|val| val != 0)
46-
} else {
47-
self.0.get_value().map(|val| val == 0)
48-
}
78+
self.0.get_value().map(|val| {
79+
val == state_to_value(
80+
embedded_hal::digital::PinState::High,
81+
self.1.is_active_low(),
82+
)
83+
})
4984
}
5085

5186
fn is_low(&self) -> Result<bool, Self::Error> {
5287
self.is_high().map(|val| !val)
5388
}
5489
}
5590

91+
impl embedded_hal::digital::blocking::IoPin<CdevPin, CdevPin> for CdevPin {
92+
type Error = gpio_cdev::errors::Error;
93+
94+
fn into_input_pin(self) -> Result<CdevPin, Self::Error> {
95+
if self.1.direction() == gpio_cdev::LineDirection::In {
96+
return Ok(self);
97+
}
98+
let line = self.0.line().clone();
99+
let input_flags = self.get_input_flags();
100+
let consumer = self.1.consumer().unwrap_or("").to_owned();
101+
102+
// Drop self to free the line before re-requesting it in a new mode.
103+
std::mem::drop(self);
104+
105+
CdevPin::new(line.request(input_flags, 0, &consumer)?)
106+
}
107+
108+
fn into_output_pin(
109+
self,
110+
state: embedded_hal::digital::PinState,
111+
) -> Result<CdevPin, Self::Error> {
112+
if self.1.direction() == gpio_cdev::LineDirection::Out {
113+
return Ok(self);
114+
}
115+
116+
let line = self.0.line().clone();
117+
let output_flags = self.get_output_flags();
118+
let consumer = self.1.consumer().unwrap_or("").to_owned();
119+
120+
// Drop self to free the line before re-requesting it in a new mode.
121+
std::mem::drop(self);
122+
123+
CdevPin::new(line.request(
124+
output_flags,
125+
state_to_value(
126+
state,
127+
output_flags.intersects(gpio_cdev::LineRequestFlags::ACTIVE_LOW),
128+
),
129+
&consumer,
130+
)?)
131+
}
132+
}
133+
56134
impl core::ops::Deref for CdevPin {
57135
type Target = gpio_cdev::LineHandle;
58136

src/sysfs_pin.rs

+20
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ impl embedded_hal::digital::blocking::InputPin for SysfsPin {
6464
}
6565
}
6666

67+
impl embedded_hal::digital::blocking::IoPin<SysfsPin, SysfsPin> for SysfsPin {
68+
type Error = sysfs_gpio::Error;
69+
70+
fn into_input_pin(self) -> Result<SysfsPin, Self::Error> {
71+
self.set_direction(sysfs_gpio::Direction::In)?;
72+
Ok(self)
73+
}
74+
75+
fn into_output_pin(
76+
self,
77+
state: embedded_hal::digital::PinState,
78+
) -> Result<SysfsPin, Self::Error> {
79+
self.set_direction(match state {
80+
embedded_hal::digital::PinState::High => sysfs_gpio::Direction::High,
81+
embedded_hal::digital::PinState::Low => sysfs_gpio::Direction::Low,
82+
})?;
83+
Ok(self)
84+
}
85+
}
86+
6787
impl core::ops::Deref for SysfsPin {
6888
type Target = sysfs_gpio::Pin;
6989

0 commit comments

Comments
 (0)