#!/usr/bin/env cargo run
use jetsongpio::{Direction, GPIO, Level, Mode};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
const LED_PIN: u32 = 12;
const BUTTON_PIN: u32 = 18;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let running = Arc::new(AtomicBool::new(true));
{
let r = Arc::clone(&running);
ctrlc::set_handler(move || {
println!("\nReceived CTRL+C, shutting down...");
r.store(false, Ordering::SeqCst);
})?;
}
let gpio = Arc::new(GPIO::new());
gpio.setmode(Mode::BOARD)?;
gpio.setup(vec![LED_PIN], Direction::OUT, Some(Level::LOW), None)?;
gpio.setup(vec![BUTTON_PIN], Direction::IN, None, None)?;
println!("Starting multi-threaded demo! Press CTRL+C to exit");
let gpio_led = Arc::clone(&gpio);
let led_running = Arc::clone(&running);
let led_handle = thread::spawn(move || {
let mut high = true;
while led_running.load(Ordering::SeqCst) {
let level = if high { Level::HIGH } else { Level::LOW };
if let Err(e) = gpio_led.output(vec![LED_PIN], vec![level]) {
eprintln!("LED thread error: {}", e);
break;
}
high = !high;
for _ in 0..50 {
if !led_running.load(Ordering::SeqCst) {
break;
}
thread::sleep(Duration::from_millis(10));
}
}
println!("LED thread exiting.");
});
let gpio_btn = Arc::clone(&gpio);
let btn_running = Arc::clone(&running);
let btn_handle = thread::spawn(move || {
let mut last: Option<Level> = None;
while btn_running.load(Ordering::SeqCst) {
match gpio_btn.input(BUTTON_PIN) {
Ok(level) => {
if last != Some(level) {
println!("Button: {:?}", level);
last = Some(level);
}
}
Err(e) => {
eprintln!("Button thread error: {}", e);
break;
}
}
thread::sleep(Duration::from_millis(50));
}
println!("Button thread exiting.");
});
led_handle.join().unwrap();
btn_handle.join().unwrap();
gpio.cleanup(None)?;
println!("Cleanup done. Goodbye!");
Ok(())
}