Files
resy/V1/led5/src/main.rs
2017-03-31 18:26:00 +02:00

153 lines
4.2 KiB
Rust

#[macro_use]
extern crate chan;
extern crate chan_signal;
use std::io::prelude::*;
use std::fs::File;
use std::thread;
use std::thread::JoinHandle;
use std::path::Path;
use std::time::Duration;
use chan_signal::Signal;
static GPIO_PORT_BTN: &'static str = "17";
static GPIO_PORT_LED: &'static str = "18";
static GPIO_DIRECTION_IN: &'static str = "in";
static GPIO_DIRECTION_OUT: &'static str = "out";
static GPIO_BTN_ON: &'static str = "0";
//static GPIO_BTN_OFF: &'static str = "1";
static GPIO_LED_ON: &'static str = "0";
static GPIO_LED_OFF: &'static str = "1";
fn write(path: &str, value: &str) {
let mut file = File::create(Path::new(path))
.expect(format!("Open file '{}' failed", path).as_str());
file.write_all(value.as_bytes())
.expect(format!("Write value '{}' to '{}' file failed", value, path).as_str());
#[cfg(debug_assertions)]
println!("Wrote value '{}' to '{}'.", value, path);
}
fn read(path: &str) -> String {
let mut file = File::open(Path::new(path))
.expect(format!("Open file '{}' failed", path).as_str());
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect(format!("Read from '{}' file failed", path).as_str());
#[cfg(debug_assertions)]
println!("Read value '{}' from '{}'.", contents, path);
contents
}
fn export(port: &str) {
write("/sys/class/gpio/export", port)
}
fn unexport(port: &str) {
write("/sys/class/gpio/unexport", port)
}
fn set_direction(port: &str, direction: &str) {
write(format!("/sys/class/gpio/gpio{}/direction", port).as_str(), direction);
}
fn set_value(port: &str, value: &str) {
write(format!("/sys/class/gpio/gpio{}/value", port).as_str(), value);
}
fn get_value(port: &str) -> String {
String::from(read(format!("/sys/class/gpio/gpio{}/value", port).as_str()).trim())
}
fn main() {
let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
let (sdone, rdone) = chan::sync(0);
let (spanic, rpanic) = chan::sync(0);
let worker = thread::Builder::new()
.name("worker".to_string())
.spawn(move || run(rdone))
.expect("Create worker thread failed");
let watchdog = thread::Builder::new()
.name("watchdog".to_string())
.spawn(move || watchdog(worker, spanic))
.expect("Create watchdog thread failed");
chan_select! {
rpanic.recv() => { },
signal.recv() -> signal => {
#[cfg(debug_assertions)]
println!("received signal: {:?}", signal);
sdone.send(());
}
}
watchdog.join().expect("Watchdog thread paniced");
}
fn watchdog(thread: JoinHandle<()>, _spanic: chan::Sender<()>) {
thread.join().expect("Thread paniced");
}
fn run(rdone: chan::Receiver<()>) {
// init
export(GPIO_PORT_BTN);
export(GPIO_PORT_LED);
set_direction(GPIO_PORT_BTN, GPIO_DIRECTION_IN);
set_direction(GPIO_PORT_LED, GPIO_DIRECTION_OUT);
let btn_tick = chan::tick(Duration::from_millis(50));
let led_tick = chan::tick(Duration::from_millis(1000 / 5));
let mut btn_last = false;
let mut led_on = false;
let mut enabled = true;
loop {
chan_select! {
btn_tick.recv() => {
//#[cfg(debug_assertions)]
//println!("btn_tick");
// switch enabled if button state changed
let btn = get_value(GPIO_PORT_BTN) == GPIO_BTN_ON;
if btn && btn != btn_last {
enabled = !enabled;
}
btn_last = btn;
},
led_tick.recv() => {
#[cfg(debug_assertions)]
println!("led_tick");
// blink led if enabled
if enabled {
led_on = !led_on;
} else {
led_on = false;
}
// set led state
if led_on {
set_value(GPIO_PORT_LED, GPIO_LED_ON);
}
else {
set_value(GPIO_PORT_LED, GPIO_LED_OFF);
}
},
rdone.recv() => {
// unexport
unexport(GPIO_PORT_BTN);
unexport(GPIO_PORT_LED);
return;
},
}
}
}