#![doc(html_root_url = "http://ogeon.github.io/docs/rust-wiringpi/master/")]
#![cfg_attr(feature = "strict", deny(warnings))]
extern crate libc;
use std::marker::PhantomData;
use pin::{Pin, Pwm, GpioClock, RequiresRoot};
macro_rules! impl_pins {
($($name:ident),+) => (
$(
#[derive(Clone, Copy)]
pub struct $name;
impl Pin for $name {}
)+
)
}
macro_rules! impl_pwm {
($($name:ident: $pwm:expr),+) => (
$(
impl Pwm for $name {
#[inline]
fn pwm_pin() -> PwmPin<$name> {
PwmPin::new($pwm)
}
}
)+
)
}
macro_rules! impl_clock {
($($name:ident: $pwm:expr),+) => (
$(
impl GpioClock for $name {
#[inline]
fn clock_pin() -> ClockPin<$name> {
ClockPin::new($pwm)
}
}
)+
)
}
macro_rules! require_root {
($($name:ident),+) => (
$(
impl RequiresRoot for $name {}
)+
)
}
mod bindings;
pub mod thread {
use bindings;
use libc;
pub fn priority(priority: u8) -> bool {
unsafe {
bindings::piHiPri(priority as libc::c_int) >= 0
}
}
}
pub mod pin {
use bindings;
use libc;
use self::Value::{Low, High};
use std::marker::PhantomData;
const INPUT: libc::c_int = 0;
const OUTPUT: libc::c_int = 1;
const PWM_OUTPUT: libc::c_int = 2;
const GPIO_CLOCK: libc::c_int = 3;
pub fn wpi_to_gpio_number(wpi_number: u16) -> u16 {
unsafe {
bindings::wpiPinToGpio(wpi_number as libc::c_int) as u16
}
}
pub fn phys_to_gpio_number(phys_number: u16) -> u16 {
unsafe {
bindings::physPinToGpio(phys_number as libc::c_int) as u16
}
}
impl_pins!(WiringPi, Gpio, Phys, Sys);
impl_pwm!(WiringPi: 1, Gpio: 18, Phys: 12);
impl_clock!(WiringPi: 7, Gpio: 4, Phys: 7);
require_root!(WiringPi, Gpio, Phys);
pub trait Pin {}
pub trait Pwm: RequiresRoot + Sized {
fn pwm_pin() -> PwmPin<Self>;
}
pub trait GpioClock: RequiresRoot + Sized {
fn clock_pin() -> ClockPin<Self>;
}
pub trait RequiresRoot: Pin {}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Value {
Low = 0,
High
}
#[derive(Clone, Copy)]
pub enum Pull {
Off = 0,
Down,
Up
}
#[derive(Clone, Copy)]
pub enum PwmMode {
MarkSpace = 0,
Balanced
}
pub struct InputPin<Pin>(libc::c_int, PhantomData<Pin>);
impl<P: Pin> InputPin<P> {
pub fn new(pin: libc::c_int) -> InputPin<P> {
unsafe {
bindings::pinMode(pin, INPUT);
}
InputPin(pin, PhantomData)
}
#[inline]
pub fn number(&self) -> libc::c_int {
let &InputPin(number, _) = self;
number
}
pub fn digital_read(&self) -> Value {
let value = unsafe {
bindings::digitalRead(self.number())
};
if value == 0 {
Low
} else {
High
}
}
pub fn analog_read(&self) -> u16 {
unsafe {
bindings::analogRead(self.number()) as u16
}
}
}
impl<P: Pin + RequiresRoot> InputPin<P> {
pub fn pull_up_dn_control(&self, pud: Pull) {
unsafe {
bindings::pullUpDnControl(self.number(), pud as libc::c_int);
}
}
pub fn into_output(self) -> OutputPin<P> {
let InputPin(number, _) = self;
OutputPin::new(number)
}
pub fn into_soft_pwm(self) -> SoftPwmPin<P> {
let InputPin(number, _) = self;
SoftPwmPin::new(number)
}
}
impl<P: Pin + Pwm> InputPin<P> {
pub fn into_pwm(self) -> PwmPin<P> {
let InputPin(number, _) = self;
PwmPin::new(number)
}
}
impl<P: Pin + GpioClock> InputPin<P> {
pub fn into_clock(self) -> ClockPin<P> {
let InputPin(number, _) = self;
ClockPin::new(number)
}
}
pub struct SoftPwmPin<Pin>(libc::c_int, PhantomData<Pin>);
impl<P: Pin + RequiresRoot> SoftPwmPin<P> {
pub fn new(pin: libc::c_int) -> SoftPwmPin<P> {
unsafe {
bindings::softPwmCreate(pin, 0, 100);
}
SoftPwmPin(pin, PhantomData)
}
#[inline]
pub fn number(&self) -> libc::c_int {
let &SoftPwmPin(number, _) = self;
number
}
pub fn pwm_write(&self, value: libc::c_int) {
unsafe {
bindings::softPwmWrite(self.number(), value);
}
}
pub fn pwm_stop(self) {
unsafe {
bindings::softPwmStop(self.number());
}
}
pub fn into_input(self) -> InputPin<P> {
let SoftPwmPin(number, _) = self;
self.pwm_stop();
InputPin::new(number)
}
pub fn into_output(self) -> OutputPin<P> {
let SoftPwmPin(number, _) = self;
self.pwm_stop();
OutputPin::new(number)
}
}
impl<P: Pin + Pwm> SoftPwmPin<P> {
pub fn into_pwm(self) -> PwmPin<P> {
let SoftPwmPin(number, _) = self;
self.pwm_stop();
PwmPin::new(number)
}
}
impl<P: Pin + GpioClock> SoftPwmPin<P> {
pub fn into_clock(self) -> ClockPin<P> {
let SoftPwmPin(number, _) = self;
self.pwm_stop();
ClockPin::new(number)
}
}
pub struct OutputPin<Pin>(libc::c_int, PhantomData<Pin>);
impl<P: Pin> OutputPin<P> {
pub fn new(pin: libc::c_int) -> OutputPin<P> {
unsafe {
bindings::pinMode(pin, OUTPUT);
}
OutputPin(pin, PhantomData)
}
#[inline]
pub fn number(&self) -> libc::c_int {
let &OutputPin(number, _) = self;
number
}
pub fn digital_write(&self, value: Value) {
unsafe {
bindings::digitalWrite(self.number(), value as libc::c_int);
}
}
pub fn analog_write(&self, value: u16) {
unsafe {
bindings::analogWrite(self.number(), value as libc::c_int);
}
}
}
impl<P: Pin + RequiresRoot> OutputPin<P> {
pub fn into_soft_pwm(self) -> SoftPwmPin<P> {
let OutputPin(number, _) = self;
SoftPwmPin::new(number)
}
}
impl<P: Pin + RequiresRoot> OutputPin<P> {
pub fn into_input(self) -> InputPin<P> {
let OutputPin(number, _) = self;
InputPin::new(number)
}
}
impl<P: Pin + Pwm> OutputPin<P> {
pub fn into_pwm(self) -> PwmPin<P> {
let OutputPin(number, _) = self;
PwmPin::new(number)
}
}
impl<P: Pin + GpioClock> OutputPin<P> {
pub fn into_clock(self) -> ClockPin<P> {
let OutputPin(number, _) = self;
ClockPin::new(number)
}
}
pub struct PwmPin<Pin>(libc::c_int, PhantomData<Pin>);
impl<P: Pin + Pwm> PwmPin<P> {
pub fn new(pin: libc::c_int) -> PwmPin<P> {
unsafe {
bindings::pinMode(pin, PWM_OUTPUT);
}
PwmPin(pin, PhantomData)
}
#[inline]
pub fn number(&self) -> libc::c_int {
let &PwmPin(number, _) = self;
number
}
pub fn into_input(self) -> InputPin<P> {
let PwmPin(number, _) = self;
InputPin::new(number)
}
pub fn into_output(self) -> OutputPin<P> {
let PwmPin(number, _) = self;
OutputPin::new(number)
}
pub fn into_soft_pwm(self) -> SoftPwmPin<P> {
let PwmPin(number, _) = self;
SoftPwmPin::new(number)
}
pub fn write(&self, value: u16) {
unsafe {
bindings::pwmWrite(self.number(), value as libc::c_int);
}
}
pub fn set_mode(&self, mode: PwmMode) {
unsafe {
bindings::pwmSetMode(mode as libc::c_int);
}
}
pub fn set_range(&self, value: u16) {
unsafe {
bindings::pwmSetRange(value as libc::c_uint);
}
}
pub fn set_clock(&self, value: u16) {
unsafe {
bindings::pwmSetClock(value as libc::c_int);
}
}
}
pub struct ClockPin<Pin>(libc::c_int, PhantomData<Pin>);
impl<P: Pin + GpioClock> ClockPin<P> {
pub fn new(pin: libc::c_int) -> ClockPin<P> {
unsafe {
bindings::pinMode(pin, GPIO_CLOCK);
}
ClockPin(pin, PhantomData)
}
#[inline]
pub fn number(&self) -> libc::c_int {
let &ClockPin(number, _) = self;
number
}
pub fn into_input(self) -> InputPin<P> {
let ClockPin(number, _) = self;
InputPin::new(number)
}
pub fn into_output(self) -> OutputPin<P> {
let ClockPin(number, _) = self;
OutputPin::new(number)
}
pub fn into_soft_pwm(self) -> SoftPwmPin<P> {
let ClockPin(number, _) = self;
SoftPwmPin::new(number)
}
pub fn frequency(&self, freq: u16) {
unsafe {
bindings::gpioClockSet(self.number(), freq as libc::c_int);
}
}
}
}
pub fn setup() -> WiringPi<pin::WiringPi> {
unsafe { bindings::wiringPiSetup(); }
WiringPi(PhantomData)
}
pub fn setup_gpio() -> WiringPi<pin::Gpio> {
unsafe { bindings::wiringPiSetupGpio(); }
WiringPi(PhantomData)
}
pub fn setup_phys() -> WiringPi<pin::Phys> {
unsafe { bindings::wiringPiSetupPhys(); }
WiringPi(PhantomData)
}
pub fn setup_sys() -> WiringPi<pin::Sys> {
unsafe { bindings::wiringPiSetupSys(); }
WiringPi(PhantomData)
}
pub fn board_revision() -> i32 {
unsafe {
bindings::piBoardRev()
}
}
pub struct WiringPi<Pin>(PhantomData<Pin>);
impl<P: Pin> WiringPi<P> {
pub fn input_pin(&self, pin: u16) -> pin::InputPin<P> {
let pin = pin as libc::c_int;
pin::InputPin::new(pin)
}
pub fn output_pin(&self, pin: u16) -> pin::OutputPin<P> {
let pin = pin as libc::c_int;
pin::OutputPin::new(pin)
}
pub fn millis(&self) -> u32 {
unsafe {
bindings::millis()
}
}
pub fn micros(&self) -> u32 {
unsafe {
bindings::micros()
}
}
pub fn digital_write_byte(&self, byte: u8) {
unsafe {
bindings::digitalWriteByte(byte as libc::c_int);
}
}
}
impl<P: Pwm + Pin> WiringPi<P> {
pub fn pwm_pin(&self) -> pin::PwmPin<P> {
Pwm::pwm_pin()
}
}
impl<P: GpioClock + Pin> WiringPi<P> {
pub fn clock_pin(&self) -> pin::ClockPin<P> {
GpioClock::clock_pin()
}
}
impl<P: Pin + RequiresRoot> WiringPi<P> {
pub fn soft_pwm_pin(&self, pin: u16) -> pin::SoftPwmPin<P> {
let pin = pin as libc::c_int;
pin::SoftPwmPin::new(pin)
}
}