Start backend

This commit is contained in:
Kai Vogelgesang 2021-09-01 16:37:28 +02:00
parent 44c2604855
commit 2dedc08636
Signed by: kai
GPG Key ID: 0A95D3B6E62C0879
4 changed files with 1345 additions and 0 deletions

1
backend/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target

1203
backend/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

12
backend/Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "backend"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.43"
palette = "0.6.0"
rodio = "0.14.0"
serialport = "4.0.1"

129
backend/src/main.rs Normal file
View File

@ -0,0 +1,129 @@
use std::{
io, thread,
time::{Duration, Instant},
};
use anyhow::{anyhow, Result};
use palette::{FromColor, Hsl, Pixel, Srgb};
use serialport::SerialPort;
const TEST_VALUE: [u8; 9] = [0, 0, 134, 0, 0, 0, 0, 0, 0];
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 start_addr = 10;
dmx_buffer[(start_addr - 1)..(start_addr - 1 + TEST_VALUE.len())].copy_from_slice(&TEST_VALUE);
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();
// calculate color
let hsl_color = Hsl::new(360.0 * (t as f64 / FPS as f64), 1.0, 0.5);
let rgb_color = Srgb::from_color(hsl_color);
let rgb: [u8; 3] = rgb_color.into_format().into_raw();
let offset = start_addr + 2;
dmx_buffer[offset..offset + 3].copy_from_slice(&rgb);
// 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 = (t + 1) % FPS;
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()
);
}
}