gpio/lib.rs
1//! GPIO interface
2//!
3//! The GPIO crate allows easy and fast access to GPIO pins. It aims to provide
4//! an ergonomic interface while being lower overhead, enabling high-frequency
5//! output without complicating simple tasks.
6//!
7//! The core interface is defined using `GpioValue` and the `GpioOut`/`GpioIn`
8//! traits. All backends implement at least some of these traits, making them
9//! interchangeable, e.g. for testing.
10//!
11//! The most commonly used implementation is based on the
12//! [Linux GPIO Sysfs](https://www.kernel.org/doc/Documentation/gpio/sysfs.txt)
13//! interface, found inside the `sysfs` crate.
14//!
15//! ## Example
16//!
17//! ```rust,no_run
18//! use gpio::{GpioIn, GpioOut};
19//! use std::{thread, time};
20//!
21//! // Let's open GPIO23 and -24, e.g. on a Raspberry Pi 2.
22//! let mut gpio23 = gpio::sysfs::SysFsGpioInput::open(23).unwrap();
23//! let mut gpio24 = gpio::sysfs::SysFsGpioOutput::open(24).unwrap();
24//!
25//! // GPIO24 will be toggled every second in the background by a different thread
26//! let mut value = false;
27//! thread::spawn(move || loop {
28//! gpio24.set_value(value).expect("could not set gpio24");
29//! thread::sleep(time::Duration::from_millis(1000));
30//! value = !value;
31//! });
32//!
33//! // The main thread will simply display the current value of GPIO23 every 100ms.
34//! loop {
35//! println!("GPIO23: {:?}", gpio23.read_value().unwrap());
36//! thread::sleep(time::Duration::from_millis(100));
37//! }
38//! ```
39//!
40//! ## TODO
41//!
42//! * `/dev/mem` interface: Higher frequency port usage
43//!
44
45pub mod sysfs;
46pub mod dummy;
47
48/// A value read from or written to a GPIO port
49#[derive(Debug, Copy, Clone, Eq, PartialEq)]
50pub enum GpioValue {
51 /// A low value, usually 0 V
52 Low,
53 /// A high value, commonly 3.3V or 5V
54 High,
55}
56
57impl From<bool> for GpioValue {
58 #[inline]
59 fn from(val: bool) -> GpioValue {
60 if val {
61 GpioValue::High
62 } else {
63 GpioValue::Low
64 }
65 }
66}
67
68impl From<u8> for GpioValue {
69 #[inline]
70 fn from(val: u8) -> GpioValue {
71 if val != 0 {
72 GpioValue::High
73 } else {
74 GpioValue::Low
75 }
76 }
77}
78
79impl From<GpioValue> for bool {
80 #[inline]
81 fn from(val: GpioValue) -> bool {
82 match val {
83 GpioValue::Low => false,
84 GpioValue::High => true,
85 }
86 }
87}
88
89impl From<GpioValue> for u8 {
90 #[inline]
91 fn from(val: GpioValue) -> u8 {
92 match val {
93 GpioValue::Low => 0,
94 GpioValue::High => 1,
95 }
96 }
97}
98
99/// Supports sending `GPIOValue`s
100pub trait GpioOut {
101 /// Errors that can occur during initialization of or writing to GPIO
102 type Error;
103
104 /// Sets the output value of the GPIO port
105 #[inline(always)]
106 fn set_value<T: Into<GpioValue> + Copy>(&mut self, value: T) -> Result<(), Self::Error> {
107 match value.into() {
108 GpioValue::High => self.set_high(),
109 GpioValue::Low => self.set_low(),
110 }
111 }
112
113 /// Set the GPIO port to a low output value directly
114 #[inline(always)]
115 fn set_low(&mut self) -> Result<(), Self::Error>;
116
117 /// Set the GPIO port to a high output value directly
118 #[inline(always)]
119 fn set_high(&mut self) -> Result<(), Self::Error>;
120}
121
122/// Supports reading `GPIOValue`s
123pub trait GpioIn {
124 /// Errors that can occur during initialization of or reading from GPIO
125 type Error;
126
127 /// Perform a single reading of a GPIO port
128 fn read_value(&mut self) -> Result<GpioValue, Self::Error>;
129}