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}