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

pub mod sysfs;
pub mod dummy;

/// A value read from or written to a GPIO port
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum GpioValue {
    /// A low value, usually 0 V
    Low,
    /// A high value, commonly 3.3V or 5V
    High,
}

impl From<bool> for GpioValue {
    #[inline]
    fn from(val: bool) -> GpioValue {
        if val {
            GpioValue::High
        } else {
            GpioValue::Low
        }
    }
}

impl From<u8> for GpioValue {
    #[inline]
    fn from(val: u8) -> GpioValue {
        if val != 0 {
            GpioValue::High
        } else {
            GpioValue::Low
        }
    }
}

impl From<GpioValue> for bool {
    #[inline]
    fn from(val: GpioValue) -> bool {
        match val {
            GpioValue::Low => false,
            GpioValue::High => true,
        }
    }
}

impl From<GpioValue> for u8 {
    #[inline]
    fn from(val: GpioValue) -> u8 {
        match val {
            GpioValue::Low => 0,
            GpioValue::High => 1,
        }
    }
}

/// Supports sending `GPIOValue`s
pub trait GpioOut {
    /// Errors that can occur during initialization of or writing to GPIO
    type Error;

    /// Sets the output value of the GPIO port
    #[inline(always)]
    fn set_value<T: Into<GpioValue> + Copy>(&mut self, value: T) -> Result<(), Self::Error> {
        match value.into() {
            GpioValue::High => self.set_high(),
            GpioValue::Low => self.set_low(),
        }
    }

    /// Set the GPIO port to a low output value directly
    #[inline(always)]
    fn set_low(&mut self) -> Result<(), Self::Error>;

    /// Set the GPIO port to a high output value directly
    #[inline(always)]
    fn set_high(&mut self) -> Result<(), Self::Error>;
}

/// Supports reading `GPIOValue`s
pub trait GpioIn {
    /// Errors that can occur during initialization of or reading from GPIO
    type Error;

    /// Perform a single reading of a GPIO port
    fn read_value(&mut self) -> Result<GpioValue, Self::Error>;
}