Merge pull request #2 from SWW13/v1-led5

V1: led5
This commit is contained in:
Siegfried Kienzle
2017-04-01 15:38:10 +02:00
committed by GitHub
8 changed files with 273 additions and 2 deletions

3
.gitignore vendored
View File

@@ -31,3 +31,6 @@
# Debug files # Debug files
*.dSYM/ *.dSYM/
*.su *.su
# Rust
target/

View File

@@ -1,8 +1,18 @@
# image: scorpil/rust:stable image: scorpil/rust:stable
stages: stages:
- test - test
cargo:test:
stage: test
script:
- ci/run-cargo-test.sh
rustfmt:
stage: test
script:
- ci/run-rustfmt.sh
shellcheck: shellcheck:
stage: test stage: test
image: ubuntu:yakkety image: ubuntu:yakkety
@@ -13,4 +23,4 @@ shellcheck:
- export LANGUAGE=en_US:en - export LANGUAGE=en_US:en
- export LC_ALL=en_US.UTF-8 - export LC_ALL=en_US.UTF-8
script: script:
- find . -type f -name '*.sh' -print0 | xargs -n 1 -0 shellcheck --color - ci/run-shellcheck.sh

66
V1/led5/Cargo.lock generated Normal file
View File

@@ -0,0 +1,66 @@
[root]
name = "led5"
version = "0.1.0"
dependencies = [
"chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"chan-signal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-set"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-vec"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chan"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "chan-signal"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
"checksum chan 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f93bfe971116428a9066c1c3c69a09ae3ef69432f8418be28ab50f96783e6a50"
"checksum chan-signal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3bb6c3bc387004ad914f0c5b7f33ace8bf7604bbec35f228b1a017f52cd3a0"
"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"

8
V1/led5/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "led5"
version = "0.1.0"
authors = ["Simon Wörner <git@simon-woerner.de>"]
[dependencies]
chan = ">=0.1.19"
chan-signal = ">=0.2.0"

152
V1/led5/src/main.rs Normal file
View File

@@ -0,0 +1,152 @@
#[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;
},
}
}
}

16
ci/run-cargo-test.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
ERROR=0
while IFS= read -r -d '' f; do
dir="$(dirname "${f}")"
echo "run 'cargo test' in ${dir}"
cd "${dir}" && cargo test
if [[ $? -ne 0 ]]; then
ERROR=1
fi
done < <(find . -type f -name 'Cargo.toml' -print0)
exit ${ERROR}

13
ci/run-rustfmt.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
ERROR=0
while IFS= read -r -d '' f; do
echo "${f}"
if [ "$(rustfmt --write-mode=diff "$f")" != $'' ] ; then
ERROR=1
fi
done < <(find . -type f -name '*.rs' -print0)
exit ${ERROR}

3
ci/run-shellcheck.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
find . -type f -name '*.sh' -print0 | xargs -n 1 -0 shellcheck --color