light_maymays/backend/src/main.rs

142 lines
3.5 KiB
Rust

use std::{
io, thread,
time::{Duration, Instant},
};
use anyhow::{anyhow, Result};
use palette::{Hsl, IntoColor, Srgb};
use serialport::SerialPort;
mod fixtures;
const FPS: u32 = 50;
enum MCUResponse {
Sync,
Ack,
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)),
}
}
fn main() -> Result<()> {
let frame_time = Duration::from_secs_f64(1.0 / FPS as f64);
let mut dmx_buffer = [0u8; 512];
let mut movingheads = [
fixtures::MovingHead14CH::new(1),
fixtures::MovingHead14CH::new(15),
fixtures::MovingHead14CH::new(29),
fixtures::MovingHead14CH::new(43),
];
for movinghead in movingheads.iter_mut() {
movinghead.dimmer = 134;
}
let mut ser = serialport::new("/dev/ttyUSB0", 500_000)
.timeout(Duration::from_millis(10))
.open()?;
println!("open");
// wait for initial sync
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Sync) => break,
_ => continue,
}
}
println!("sync");
let mut t = 0;
'main: loop {
let loop_start = Instant::now();
let dist = FPS as f32 / movingheads.len() as f32;
for (i, movinghead) in movingheads.iter_mut().enumerate() {
let hsl_color = Hsl::new(
360.0 * ((t % FPS) as f32 / FPS as f32) + i as f32 * dist,
1.0,
0.5,
);
movinghead.rgb = hsl_color.into_color();
movinghead.render(&mut dmx_buffer);
}
// write DMX data
let write_result = ser.write(&dmx_buffer);
if write_result.is_err() {
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Sync) => {
continue 'main;
}
_ => continue,
}
}
}
// get response
loop {
match poll_response(&mut *ser) {
Ok(MCUResponse::Ack) => break,
Ok(MCUResponse::Info { num_pkts }) => {
println!("Info: {}", num_pkts);
continue;
}
Err(e) => {
println!("Error! {:?}", e);
continue;
}
Ok(MCUResponse::Sync) => {
continue 'main;
}
}
}
t += 1;
let loop_time = loop_start.elapsed();
if loop_time < frame_time {
thread::sleep(frame_time - loop_time);
} else {
println!("loop took too long!");
}
println!(
"loop time: {}ms busy, {}ms total",
loop_time.as_millis(),
loop_start.elapsed().as_millis()
);
}
}