97 lines
2.8 KiB
Rust
97 lines
2.8 KiB
Rust
extern crate kawaii;
|
|
|
|
use std::time::Duration;
|
|
use std::thread;
|
|
use std::thread::JoinHandle;
|
|
use std::sync::Arc;
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
use self::kawaii::gpio::{AsyncPort, Edge, Value};
|
|
|
|
#[cfg(feature = "measure")]
|
|
use self::kawaii::Measure;
|
|
|
|
#[derive(Debug)]
|
|
pub struct EmergencyStop {
|
|
thread: Option<JoinHandle<()>>,
|
|
pub state: Arc<AtomicBool>,
|
|
}
|
|
|
|
impl EmergencyStop {
|
|
pub fn new(stop_port: u8) -> std::io::Result<Self> {
|
|
let name = format!("EmergencyStop(port = {})", stop_port);
|
|
let state = Arc::new(AtomicBool::new(false));
|
|
let mut port = AsyncPort::new(stop_port, Edge::Both)?;
|
|
|
|
let state_clone = state.clone();
|
|
let thread = thread::Builder::new()
|
|
.name(name)
|
|
.spawn(move || EmergencyStop::thread(&mut port, state_clone))?;
|
|
|
|
Ok(EmergencyStop {
|
|
thread: Some(thread),
|
|
state: state,
|
|
})
|
|
}
|
|
|
|
fn thread(port: &mut AsyncPort, state: Arc<AtomicBool>) {
|
|
#[cfg(feature = "measure")]
|
|
let mut measure = Measure::new(format!("EmergencyStop(port = {})", port.port.number));
|
|
|
|
// clear first value
|
|
port.poll(Some(Duration::new(0, 0))).is_ok();
|
|
|
|
while !state.load(Ordering::Relaxed) {
|
|
#[cfg(feature = "measure")]
|
|
measure.start();
|
|
|
|
let timeout = Some(Duration::new(1, 0));
|
|
|
|
#[cfg(not(feature = "measure"))]
|
|
let value = port.poll(timeout);
|
|
|
|
#[cfg(feature = "measure")]
|
|
let value = port.poll_measure(timeout, &mut measure);
|
|
|
|
// continue on timeout
|
|
match value {
|
|
Ok(value) => {
|
|
if let Some(value) = value {
|
|
match value {
|
|
Value::High => {
|
|
#[cfg(debug_assertions)]
|
|
println!("EmergencyStop! ({:?})", value);
|
|
|
|
state.store(true, Ordering::Relaxed);
|
|
}
|
|
_ => {
|
|
#[cfg(debug_assertions)]
|
|
println!("EmergencyStop ignored: ({:?})", value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
#[cfg(debug_assertions)]
|
|
println!("EmergencyStop! ({:?})", e);
|
|
|
|
state.store(true, Ordering::Relaxed);
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "measure")]
|
|
measure.stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for EmergencyStop {
|
|
fn drop(&mut self) {
|
|
self.state.store(true, Ordering::Relaxed);
|
|
|
|
if let Some(thread) = self.thread.take() {
|
|
thread.join().is_ok();
|
|
}
|
|
}
|
|
}
|