Files
light_maymays/beat_detection/src/dmx_controller.rs
2021-10-28 03:07:03 +02:00

114 lines
2.7 KiB
Rust

use std::{
io,
sync::{Arc, Mutex},
thread,
time::{Duration, Instant},
};
use anyhow::{anyhow, Result};
use serialport::SerialPort;
use crate::fixtures::{DMXFixture, MovingHead};
const FPS: u32 = 50;
enum MCUResponse {
Sync,
Ack,
#[allow(dead_code)]
Info {
num_pkts: u32,
},
}
fn poll_response(ser: &mut dyn SerialPort) -> Result<MCUResponse> {
let mut read_buffer = vec![0u8; 32];
let bytes_read;
loop {
match ser.read(read_buffer.as_mut_slice()) {
Ok(t) => {
bytes_read = t;
break;
}
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => continue,
Err(e) => Err(e),
}?
}
let response = std::str::from_utf8(&read_buffer[..bytes_read])?;
match response.trim() {
"Sync." => Ok(MCUResponse::Sync),
"Ack." => Ok(MCUResponse::Ack),
s if s.starts_with("Info") => Ok(MCUResponse::Info { num_pkts: 69 }),
s => Err(anyhow!("Unknown response: \"{}\"", s)),
}
}
pub fn controller_thread(
running: Arc<Mutex<bool>>,
movingheads: Arc<Mutex<[MovingHead; 4]>>,
) -> Result<()> {
let frame_time = Duration::from_secs_f64(1.0 / FPS as f64);
let mut dmx_buffer = [0u8; 512];
let mut ser = serialport::new("/dev/ttyUSB0", 500_000)
.timeout(Duration::from_millis(10))
.open()?;
// wait for initial sync
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Sync) => break,
_ => continue,
}
}
'main: loop {
{
let running = running.lock().unwrap();
if !*running {
break Ok(());
}
}
let loop_start = Instant::now();
{
let movingheads = movingheads.lock().unwrap();
for head in movingheads.iter() {
head.render(&mut dmx_buffer);
}
}
let write_result = ser.write(&dmx_buffer);
if write_result.is_err() {
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Sync) => continue 'main,
_ => continue,
}
}
}
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Ack) => break,
Ok(MCUResponse::Info { .. }) | Err(_) => continue,
Ok(MCUResponse::Sync) => continue 'main,
}
}
let loop_time = loop_start.elapsed();
if loop_time < frame_time {
thread::sleep(frame_time - loop_time);
} else {
println!("loop took too long!");
}
}
}