From f356624502479bf09df4934e94e6f05abf654e7c Mon Sep 17 00:00:00 2001 From: 4yn Date: Sun, 13 Feb 2022 23:22:31 +0800 Subject: [PATCH] refactor to 'lights', add diva protocol --- src-slider_io/src/config.rs | 6 +- src-slider_io/src/context.rs | 44 ++- .../{input => device}/brokenithm-www/app.js | 0 .../brokenithm-www/config.js | 0 .../brokenithm-www/favicon.ico | Bin .../{input => device}/brokenithm-www/icon.png | Bin .../brokenithm-www/index-go.html | 0 .../brokenithm-www/index.html | 0 .../{input => device}/brokenithm-www/src.js | 0 .../src/{input => device}/brokenithm.rs | 32 +- src-slider_io/src/{input => device}/config.rs | 16 +- src-slider_io/src/device/diva.rs | 313 ++++++++++++++++++ .../src/{input/device.rs => device/hid.rs} | 8 +- src-slider_io/src/{input => device}/mod.rs | 5 +- src-slider_io/src/input/acio.rs | 52 --- src-slider_io/src/lib.rs | 2 +- src-slider_io/src/lighting/config.rs | 22 +- src-slider_io/src/lighting/lighting.rs | 24 +- 18 files changed, 401 insertions(+), 123 deletions(-) rename src-slider_io/src/{input => device}/brokenithm-www/app.js (100%) rename src-slider_io/src/{input => device}/brokenithm-www/config.js (100%) rename src-slider_io/src/{input => device}/brokenithm-www/favicon.ico (100%) rename src-slider_io/src/{input => device}/brokenithm-www/icon.png (100%) rename src-slider_io/src/{input => device}/brokenithm-www/index-go.html (100%) rename src-slider_io/src/{input => device}/brokenithm-www/index.html (100%) rename src-slider_io/src/{input => device}/brokenithm-www/src.js (100%) rename src-slider_io/src/{input => device}/brokenithm.rs (91%) rename src-slider_io/src/{input => device}/config.rs (78%) create mode 100644 src-slider_io/src/device/diva.rs rename src-slider_io/src/{input/device.rs => device/hid.rs} (98%) rename src-slider_io/src/{input => device}/mod.rs (57%) delete mode 100644 src-slider_io/src/input/acio.rs diff --git a/src-slider_io/src/config.rs b/src-slider_io/src/config.rs index ab77f5b..c4fc5a1 100644 --- a/src-slider_io/src/config.rs +++ b/src-slider_io/src/config.rs @@ -3,7 +3,7 @@ use serde_json::Value; use std::fs; use crate::{ - input::config::DeviceMode, lighting::config::LedMode, output::config::OutputMode, system, + device::config::DeviceMode, lighting::config::LightsMode, output::config::OutputMode, system, }; #[derive(Debug, Clone)] @@ -11,7 +11,7 @@ pub struct Config { pub raw: String, pub device_mode: DeviceMode, pub output_mode: OutputMode, - pub led_mode: LedMode, + pub lights_mode: LightsMode, } impl Config { @@ -22,7 +22,7 @@ impl Config { raw: s.to_string(), device_mode: DeviceMode::from_serde_value(&v)?, output_mode: OutputMode::from_serde_value(&v)?, - led_mode: LedMode::from_serde_value(&v)?, + lights_mode: LightsMode::from_serde_value(&v)?, }) } diff --git a/src-slider_io/src/context.rs b/src-slider_io/src/context.rs index 2d6e6a4..6c66d0e 100644 --- a/src-slider_io/src/context.rs +++ b/src-slider_io/src/context.rs @@ -4,8 +4,8 @@ use std::sync::{atomic::Ordering, Arc}; use crate::{ config::Config, - input::{brokenithm::BrokenithmJob, config::DeviceMode, device::HidDeviceJob}, - lighting::{config::LedMode, lighting::LedJob}, + device::{brokenithm::BrokenithmJob, config::DeviceMode, diva::DivaSliderJob, hid::HidJob}, + lighting::{config::LightsMode, lighting::LightsJob}, output::{config::OutputMode, output::OutputJob}, shared::{ utils::LoopTimer, @@ -18,10 +18,10 @@ use crate::{ pub struct Context { state: SliderState, config: Config, - device_worker: Option, - brokenithm_worker: Option, + device_thread_worker: Option, + device_async_haltable_worker: Option, output_worker: Option, - led_worker: Option, + lights_worker: Option, timers: Vec<(&'static str, Arc)>, } @@ -30,7 +30,7 @@ impl Context { info!("Context creating"); info!("Device config {:?}", config.device_mode); info!("Output config {:?}", config.output_mode); - info!("LED config {:?}", config.led_mode); + info!("Lights config {:?}", config.lights_mode); let state = SliderState::new(); let mut timers = vec![]; @@ -39,12 +39,12 @@ impl Context { DeviceMode::None => (None, None), DeviceMode::Brokenithm { ground_only, - led_enabled, + lights_enabled, } => ( None, Some(AsyncHaltableWorker::new( "brokenithm", - BrokenithmJob::new(&state, ground_only, led_enabled), + BrokenithmJob::new(&state, ground_only, lights_enabled), )), ), DeviceMode::Hardware { spec } => ( @@ -53,7 +53,19 @@ impl Context { timers.push(("d", timer.fork())); Some(ThreadWorker::new( "device", - HidDeviceJob::from_config(&state, spec), + HidJob::from_config(&state, spec), + timer, + )) + }, + None, + ), + DeviceMode::DivaSlider { port } => ( + { + let timer = LoopTimer::new(); + timers.push(("d", timer.fork())); + Some(ThreadWorker::new( + "diva", + DivaSliderJob::new(&state, port), timer, )) }, @@ -72,14 +84,14 @@ impl Context { )) } }; - let led_worker = match &config.led_mode { - LedMode::None => None, + let lights_worker = match &config.lights_mode { + LightsMode::None => None, _ => { let timer = LoopTimer::new(); timers.push(("l", timer.fork())); Some(AsyncWorker::new( - "led", - LedJob::new(&state, &config.led_mode), + "lights", + LightsJob::new(&state, &config.lights_mode), timer, )) } @@ -88,10 +100,10 @@ impl Context { Self { state, config, - device_worker, - brokenithm_worker, + device_thread_worker: device_worker, + device_async_haltable_worker: brokenithm_worker, output_worker, - led_worker, + lights_worker, timers, } } diff --git a/src-slider_io/src/input/brokenithm-www/app.js b/src-slider_io/src/device/brokenithm-www/app.js similarity index 100% rename from src-slider_io/src/input/brokenithm-www/app.js rename to src-slider_io/src/device/brokenithm-www/app.js diff --git a/src-slider_io/src/input/brokenithm-www/config.js b/src-slider_io/src/device/brokenithm-www/config.js similarity index 100% rename from src-slider_io/src/input/brokenithm-www/config.js rename to src-slider_io/src/device/brokenithm-www/config.js diff --git a/src-slider_io/src/input/brokenithm-www/favicon.ico b/src-slider_io/src/device/brokenithm-www/favicon.ico similarity index 100% rename from src-slider_io/src/input/brokenithm-www/favicon.ico rename to src-slider_io/src/device/brokenithm-www/favicon.ico diff --git a/src-slider_io/src/input/brokenithm-www/icon.png b/src-slider_io/src/device/brokenithm-www/icon.png similarity index 100% rename from src-slider_io/src/input/brokenithm-www/icon.png rename to src-slider_io/src/device/brokenithm-www/icon.png diff --git a/src-slider_io/src/input/brokenithm-www/index-go.html b/src-slider_io/src/device/brokenithm-www/index-go.html similarity index 100% rename from src-slider_io/src/input/brokenithm-www/index-go.html rename to src-slider_io/src/device/brokenithm-www/index-go.html diff --git a/src-slider_io/src/input/brokenithm-www/index.html b/src-slider_io/src/device/brokenithm-www/index.html similarity index 100% rename from src-slider_io/src/input/brokenithm-www/index.html rename to src-slider_io/src/device/brokenithm-www/index.html diff --git a/src-slider_io/src/input/brokenithm-www/src.js b/src-slider_io/src/device/brokenithm-www/src.js similarity index 100% rename from src-slider_io/src/input/brokenithm-www/src.js rename to src-slider_io/src/device/brokenithm-www/src.js diff --git a/src-slider_io/src/input/brokenithm.rs b/src-slider_io/src/device/brokenithm.rs similarity index 91% rename from src-slider_io/src/input/brokenithm.rs rename to src-slider_io/src/device/brokenithm.rs index 56de67c..88c9d47 100644 --- a/src-slider_io/src/input/brokenithm.rs +++ b/src-slider_io/src/device/brokenithm.rs @@ -69,7 +69,7 @@ async fn serve_file(path: &str) -> Result, Infallible> { async fn handle_brokenithm( ws_stream: WebSocketStream, state: SliderState, - led_enabled: bool, + lights_enabled: bool, ) { let (mut ws_write, mut ws_read) = ws_stream.split(); @@ -153,7 +153,7 @@ async fn handle_brokenithm( // info!("Websocket read task done"); }; - match led_enabled { + match lights_enabled { false => { select! { _ = read_task => {} @@ -163,14 +163,14 @@ async fn handle_brokenithm( true => { let msg_write_handle = msg_write.clone(); let state_handle = state.clone(); - let led_task = async move { + let lights_task = async move { loop { - let mut led_data = vec![0; 93]; + let mut lights_data = vec![0; 93]; { let lights_handle = state_handle.lights.lock(); - (&mut led_data).copy_from_slice(&lights_handle.ground); + (&mut lights_data).copy_from_slice(&lights_handle.ground); } - msg_write_handle.send(Message::Binary(led_data)).ok(); + msg_write_handle.send(Message::Binary(lights_data)).ok(); sleep(Duration::from_millis(50)).await; } @@ -179,7 +179,7 @@ async fn handle_brokenithm( select! { _ = read_task => {} _ = write_task => {} - _ = led_task => {} + _ = lights_task => {} }; } } @@ -188,7 +188,7 @@ async fn handle_brokenithm( async fn handle_websocket( mut request: Request, state: SliderState, - led_enabled: bool, + lights_enabled: bool, ) -> Result, Infallible> { let res = match handshake::server::create_response_with_body(&request, || Body::empty()) { Ok(res) => { @@ -202,7 +202,7 @@ async fn handle_websocket( ) .await; - handle_brokenithm(ws_stream, state, led_enabled).await; + handle_brokenithm(ws_stream, state, lights_enabled).await; } Err(e) => { @@ -229,7 +229,7 @@ async fn handle_request( remote_addr: SocketAddr, state: SliderState, ground_only: bool, - led_enabled: bool, + lights_enabled: bool, ) -> Result, Infallible> { let method = request.method(); let path = request.uri().path(); @@ -251,7 +251,7 @@ async fn handle_request( true => serve_file("index-go.html").await, }, (filename, false) => serve_file(&filename[1..]).await, - ("/ws", true) => handle_websocket(request, state, led_enabled).await, + ("/ws", true) => handle_websocket(request, state, lights_enabled).await, _ => error_response().await, } } @@ -259,15 +259,15 @@ async fn handle_request( pub struct BrokenithmJob { state: SliderState, ground_only: bool, - led_enabled: bool, + lights_enabled: bool, } impl BrokenithmJob { - pub fn new(state: &SliderState, ground_only: &bool, led_enabled: &bool) -> Self { + pub fn new(state: &SliderState, ground_only: &bool, lights_enabled: &bool) -> Self { Self { state: state.clone(), ground_only: *ground_only, - led_enabled: *led_enabled, + lights_enabled: *lights_enabled, } } } @@ -277,14 +277,14 @@ impl AsyncHaltableJob for BrokenithmJob { async fn run + Send>(self, stop_signal: F) { let state = self.state.clone(); let ground_only = self.ground_only; - let led_enabled = self.led_enabled; + let lights_enabled = self.lights_enabled; let make_svc = make_service_fn(|conn: &AddrStream| { let remote_addr = conn.remote_addr(); let make_svc_state = state.clone(); async move { Ok::<_, Infallible>(service_fn(move |request: Request| { let svc_state = make_svc_state.clone(); - handle_request(request, remote_addr, svc_state, ground_only, led_enabled) + handle_request(request, remote_addr, svc_state, ground_only, lights_enabled) })) } }); diff --git a/src-slider_io/src/input/config.rs b/src-slider_io/src/device/config.rs similarity index 78% rename from src-slider_io/src/input/config.rs rename to src-slider_io/src/device/config.rs index c53beed..91974a2 100644 --- a/src-slider_io/src/input/config.rs +++ b/src-slider_io/src/device/config.rs @@ -15,7 +15,10 @@ pub enum DeviceMode { }, Brokenithm { ground_only: bool, - led_enabled: bool, + lights_enabled: bool, + }, + DivaSlider { + port: String, }, } @@ -32,21 +35,24 @@ impl DeviceMode { "yuancon" => DeviceMode::Hardware { spec: HardwareSpec::Yuancon, }, + "diva" => DeviceMode::DivaSlider { + port: v["divaSerialPort"].as_str()?.to_string(), + }, "brokenithm" => DeviceMode::Brokenithm { ground_only: false, - led_enabled: false, + lights_enabled: false, }, "brokenithm-led" => DeviceMode::Brokenithm { ground_only: false, - led_enabled: true, + lights_enabled: true, }, "brokenithm-ground" => DeviceMode::Brokenithm { ground_only: true, - led_enabled: false, + lights_enabled: false, }, "brokenithm-ground-led" => DeviceMode::Brokenithm { ground_only: true, - led_enabled: true, + lights_enabled: true, }, _ => return None, }) diff --git a/src-slider_io/src/device/diva.rs b/src-slider_io/src/device/diva.rs new file mode 100644 index 0000000..ec95cff --- /dev/null +++ b/src-slider_io/src/device/diva.rs @@ -0,0 +1,313 @@ +use log::{error, info}; +use serialport::SerialPort; +use std::{collections::VecDeque, num::Wrapping, thread::sleep, time::Duration}; + +use crate::{shared::worker::ThreadJob, state::SliderState}; + +struct DivaPacket { + command: u8, + len: u8, + data: Vec, + checksum: Wrapping, + raw: Option>, +} + +impl DivaPacket { + fn new() -> Self { + Self { + command: 0, + len: 0, + data: Vec::with_capacity(256), + checksum: Wrapping(0), + raw: None, + } + } + + fn from_bytes(command: u8, data: &[u8]) -> Self { + Self { + command, + len: data.len() as u8, + data: data.iter().copied().collect(), + checksum: Wrapping(0), + raw: None, + } + } + + fn push_raw_escaped(byte: u8, raw: &mut Vec) { + match byte { + 0xfd => { + raw.push(0xfd); + raw.push(0xfc); + } + 0xff => { + raw.push(0xfd); + raw.push(0xfe); + } + _ => { + raw.push(byte); + } + } + } + + fn serialize(&mut self) -> &[u8] { + let mut raw: Vec = Vec::with_capacity(512); + let mut checksum = Wrapping(0); + + raw.push(0xff); + checksum += Wrapping(0xffu8); + Self::push_raw_escaped(self.command, &mut raw); + checksum += Wrapping(self.command); + Self::push_raw_escaped(self.len, &mut raw); + checksum += Wrapping(self.len); + for i in &self.data { + Self::push_raw_escaped(*i, &mut raw); + checksum += Wrapping(*i); + } + + checksum = -checksum; + Self::push_raw_escaped(checksum.0, &mut raw); + + self.raw = Some(raw); + return self.raw.as_ref().unwrap(); + } +} + +enum DivaDeserializerState { + ExpectCommand, + ExpectLen, + ExpectData, + ExpectChecksum, + Done, +} + +struct DivaDeserializer { + state: DivaDeserializerState, + escape: u8, + len: u8, + packet: DivaPacket, +} + +impl DivaDeserializer { + fn new() -> Self { + Self { + state: DivaDeserializerState::Done, + escape: 1, + len: 0, + packet: DivaPacket::new(), + } + } + + fn deserialize(&mut self, data: &[u8], out: &mut VecDeque) { + for c in data { + match c { + 0xff => { + self.packet = DivaPacket::new(); + self.packet.checksum = Wrapping(0xff); + self.state = DivaDeserializerState::ExpectCommand; + } + 0xfd => { + self.escape = 1; + } + c => { + let c = c + self.escape; + self.escape = 0; + + self.packet.checksum += Wrapping(c); + match self.state { + DivaDeserializerState::ExpectCommand => { + self.packet.command = c; + self.state = DivaDeserializerState::ExpectLen; + } + DivaDeserializerState::ExpectLen => { + self.len = c; + self.packet.len = c; + self.state = match c { + 0 => DivaDeserializerState::ExpectChecksum, + _ => DivaDeserializerState::ExpectData, + }; + } + DivaDeserializerState::ExpectData => { + self.packet.data.push(c); + self.len -= 1; + + if self.len == 0 { + self.state = DivaDeserializerState::ExpectChecksum; + } + } + DivaDeserializerState::ExpectChecksum => { + debug_assert!(self.packet.checksum == Wrapping(0)); + if self.packet.checksum == Wrapping(0) { + out.push_back(DivaPacket::new()); + std::mem::swap(&mut self.packet, out.back_mut().unwrap()); + } + self.state = DivaDeserializerState::Done; + } + _ => {} + } + } + } + } + } +} + +enum DivaSliderBootstrap { + Init, + AwaitReset, + AwaitInfo, + AwaitStart, + ReadLoop, +} + +pub struct DivaSliderJob { + state: SliderState, + port: String, + packets: VecDeque, + deserializer: DivaDeserializer, + serial_port: Option>, + bootstrap: DivaSliderBootstrap, +} + +impl DivaSliderJob { + pub fn new(state: &SliderState, port: &String) -> Self { + Self { + state: state.clone(), + port: port.clone(), + packets: VecDeque::with_capacity(100), + deserializer: DivaDeserializer::new(), + serial_port: None, + bootstrap: DivaSliderBootstrap::Init, + } + } +} + +impl ThreadJob for DivaSliderJob { + fn setup(&mut self) -> bool { + info!( + "Serial port for diva slider opening at {} {:?}", + self.port.as_str(), + 115200 + ); + match serialport::new(&self.port, 152000).open() { + Ok(serial_port_buf) => { + info!("Serial port opened"); + self.serial_port = Some(serial_port_buf); + true + } + Err(e) => { + error!("Serial port could not open: {}", e); + false + } + } + } + + fn tick(&mut self) -> bool { + let mut work = false; + + let serial_port = self.serial_port.as_mut().unwrap(); + + let bytes_avail = serial_port.bytes_to_read().unwrap_or(0); + if bytes_avail > 0 { + let mut read_buf = vec![0 as u8; bytes_avail as usize]; + serial_port.read_exact(&mut read_buf).ok(); + self.deserializer.deserialize(&read_buf, &mut self.packets); + work = true; + } + + match self.bootstrap { + DivaSliderBootstrap::Init => { + let mut reset_packet = DivaPacket::from_bytes(0x10, &[]); + serial_port.write(reset_packet.serialize()).ok(); + + self.bootstrap = DivaSliderBootstrap::AwaitReset; + work = true; + } + DivaSliderBootstrap::AwaitReset => { + if let Some(ack_packet) = self.packets.pop_front() { + info!( + "Diva slider ack reset {:?} {:?}", + ack_packet.command, ack_packet.data + ); + + let mut info_packet = DivaPacket::from_bytes(0xf0, &[]); + serial_port.write(info_packet.serialize()).ok(); + + self.bootstrap = DivaSliderBootstrap::AwaitInfo; + work = true; + } + } + DivaSliderBootstrap::AwaitInfo => { + if let Some(ack_packet) = self.packets.pop_front() { + info!( + "Diva slider ack info {:?} {:?}", + ack_packet.command, ack_packet.data + ); + + let mut start_packet = DivaPacket::from_bytes(0x03, &[]); + serial_port.write(start_packet.serialize()).ok(); + + self.bootstrap = DivaSliderBootstrap::AwaitStart; + work = true; + } + } + DivaSliderBootstrap::AwaitStart => { + if let Some(ack_packet) = self.packets.pop_front() { + info!( + "Diva slider ack start {:?} {:?}", + ack_packet.command, ack_packet.data + ); + + self.bootstrap = DivaSliderBootstrap::ReadLoop; + work = true; + } + } + DivaSliderBootstrap::ReadLoop => { + while let Some(data_packet) = self.packets.pop_front() { + if data_packet.command == 0x01 && data_packet.len == 32 { + let mut input_handle = self.state.input.lock(); + input_handle + .ground + .copy_from_slice(&data_packet.data[0..32]); + work = true; + } + } + + let mut send_lights = false; + let mut lights_buf = [0; 97]; + { + let mut lights_handle = self.state.lights.lock(); + if lights_handle.dirty { + send_lights = true; + lights_buf[0] = 0x3f; + lights_buf[1..97].copy_from_slice(&lights_handle.ground[0..96]); + lights_handle.dirty = false; + } + } + + if send_lights { + let mut lights_packet = DivaPacket::from_bytes(0x02, &lights_buf); + serial_port.write(lights_packet.serialize()).ok(); + } + } + }; + + // TODO: async worker? + sleep(Duration::from_millis(10)); + + work + } +} + +impl Drop for DivaSliderJob { + fn drop(&mut self) { + match self.bootstrap { + DivaSliderBootstrap::AwaitStart | DivaSliderBootstrap::ReadLoop => { + info!("Diva slider sending stop"); + + let serial_port = self.serial_port.as_mut().unwrap(); + let mut stop_packet = DivaPacket::from_bytes(0x04, &[]); + serial_port.write(stop_packet.serialize()).ok(); + } + _ => {} + }; + } +} diff --git a/src-slider_io/src/input/device.rs b/src-slider_io/src/device/hid.rs similarity index 98% rename from src-slider_io/src/input/device.rs rename to src-slider_io/src/device/hid.rs index 48aa284..78f35c0 100644 --- a/src-slider_io/src/input/device.rs +++ b/src-slider_io/src/device/hid.rs @@ -25,7 +25,7 @@ enum WriteType { Interrupt, } -pub struct HidDeviceJob { +pub struct HidJob { state: SliderState, vid: u16, @@ -44,7 +44,7 @@ pub struct HidDeviceJob { handle: Option>, } -impl HidDeviceJob { +impl HidJob { fn new( state: SliderState, vid: u16, @@ -212,7 +212,7 @@ impl HidDeviceJob { const TIMEOUT: Duration = Duration::from_millis(20); -impl ThreadJob for HidDeviceJob { +impl ThreadJob for HidJob { fn setup(&mut self) -> bool { match self.get_handle() { Ok(_) => { @@ -283,7 +283,7 @@ impl ThreadJob for HidDeviceJob { } } -impl Drop for HidDeviceJob { +impl Drop for HidJob { fn drop(&mut self) { if let Some(handle) = self.handle.as_mut() { handle.release_interface(0).ok(); diff --git a/src-slider_io/src/input/mod.rs b/src-slider_io/src/device/mod.rs similarity index 57% rename from src-slider_io/src/input/mod.rs rename to src-slider_io/src/device/mod.rs index 600edf5..b8daf75 100644 --- a/src-slider_io/src/input/mod.rs +++ b/src-slider_io/src/device/mod.rs @@ -1,6 +1,5 @@ pub mod config; -mod acio; - +pub mod diva; pub mod brokenithm; -pub mod device; +pub mod hid; diff --git a/src-slider_io/src/input/acio.rs b/src-slider_io/src/input/acio.rs deleted file mode 100644 index cf6c6a3..0000000 --- a/src-slider_io/src/input/acio.rs +++ /dev/null @@ -1,52 +0,0 @@ -// use serialport::SerialPort; -// use std::io::{BufRead, BufReader}; - -// struct ArcadeSlider { -// serial_port: BufReader>, -// } - -// impl ArcadeSlider { -// fn new() -> Self { -// let serial_port = serialport::new("COM1", 152000).open().unwrap(); -// let serial_port_buf = BufReader::new(serial_port); -// Self { -// serial_port: serial_port_buf, -// } -// } - -// fn recv(&mut self) { -// let mut consumed = 0; -// { -// let d = self.serial_port.fill_buf().unwrap(); - -// let mut packets = vec![]; -// let mut packet = vec![]; - -// let mut bytes_taken = 0; -// let mut in_escape = 0; -// let mut checksum = 0; -// for b in d.iter() { -// bytes_taken += 1; - -// match b { -// 0xff => { -// consumed += bytes_taken; -// bytes_taken = 0; -// in_escape = 0; -// } -// 0xfd => { -// in_escape = 1; -// } -// _ => { -// let b = b + in_escape; -// in_escape = 0; -// packet.push(b); -// } -// } -// } -// } -// self.serial_port.consume(consumed); -// } - -// fn send(&mut self) {} -// } diff --git a/src-slider_io/src/lib.rs b/src-slider_io/src/lib.rs index 32915f2..8632020 100644 --- a/src-slider_io/src/lib.rs +++ b/src-slider_io/src/lib.rs @@ -9,7 +9,7 @@ mod config; mod shared; mod state; -mod input; +mod device; mod lighting; mod output; diff --git a/src-slider_io/src/lighting/config.rs b/src-slider_io/src/lighting/config.rs index 47dec93..ffeb005 100644 --- a/src-slider_io/src/lighting/config.rs +++ b/src-slider_io/src/lighting/config.rs @@ -7,7 +7,7 @@ pub enum ReactiveLayout { } #[derive(Debug, Clone)] -pub enum LedMode { +pub enum LightsMode { None, Reactive { layout: ReactiveLayout, @@ -23,32 +23,32 @@ pub enum LedMode { }, } -impl LedMode { +impl LightsMode { pub fn from_serde_value(v: &Value) -> Option { Some(match v["ledMode"].as_str()? { - "none" => LedMode::None, - "reactive-4" => LedMode::Reactive { + "none" => LightsMode::None, + "reactive-4" => LightsMode::Reactive { layout: ReactiveLayout::Even { splits: 4 }, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, - "reactive-8" => LedMode::Reactive { + "reactive-8" => LightsMode::Reactive { layout: ReactiveLayout::Even { splits: 8 }, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, - "reactive-16" => LedMode::Reactive { + "reactive-16" => LightsMode::Reactive { layout: ReactiveLayout::Even { splits: 16 }, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, - "reactive-voltex" => LedMode::Reactive { + "reactive-voltex" => LightsMode::Reactive { layout: ReactiveLayout::Voltex, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, - "attract" => LedMode::Attract, - "test" => LedMode::Test, - "websocket" => LedMode::Websocket { + "attract" => LightsMode::Attract, + "test" => LightsMode::Test, + "websocket" => LightsMode::Websocket { url: v["ledWebsocketUrl"].as_str()?.to_string(), }, - "serial" => LedMode::Serial { + "serial" => LightsMode::Serial { port: v["ledSerialPort"].as_str()?.to_string(), }, _ => return None, diff --git a/src-slider_io/src/lighting/lighting.rs b/src-slider_io/src/lighting/lighting.rs index a9e9ba0..0cb1de3 100644 --- a/src-slider_io/src/lighting/lighting.rs +++ b/src-slider_io/src/lighting/lighting.rs @@ -13,18 +13,18 @@ use crate::{ state::{SliderLights, SliderState}, }; -use super::config::{LedMode, ReactiveLayout}; +use super::config::{LightsMode, ReactiveLayout}; -pub struct LedJob { +pub struct LightsJob { state: SliderState, - mode: LedMode, + mode: LightsMode, serial_port: Option>, started: Instant, timer: Interval, } -impl LedJob { - pub fn new(state: &SliderState, mode: &LedMode) -> Self { +impl LightsJob { + pub fn new(state: &SliderState, mode: &LightsMode) -> Self { Self { state: state.clone(), mode: mode.clone(), @@ -41,7 +41,7 @@ impl LedJob { lights: &mut SliderLights, ) { match self.mode { - LedMode::Reactive { layout, .. } => { + LightsMode::Reactive { layout, .. } => { let flat_input = flat_input.unwrap(); match layout { @@ -116,7 +116,7 @@ impl LedJob { } } } - LedMode::Attract => { + LightsMode::Attract => { let theta = self .started .elapsed() @@ -128,7 +128,7 @@ impl LedJob { lights.paint(idx, &[color.red, color.green, color.blue]); } } - LedMode::Serial { .. } => { + LightsMode::Serial { .. } => { // https://github.com/jmontineri/OpeNITHM/blob/89e9a43f7484e8949cd31bbff79c32f21ea3ec1d/Firmware/OpeNITHM/SerialProcessor.h // https://github.com/jmontineri/OpeNITHM/blob/89e9a43f7484e8949cd31bbff79c32f21ea3ec1d/Firmware/OpeNITHM/SerialProcessor.cpp // https://github.com/jmontineri/OpeNITHM/blob/89e9a43f7484e8949cd31bbff79c32f21ea3ec1d/Firmware/OpeNITHM/SerialLeds.h @@ -155,10 +155,10 @@ impl LedJob { } #[async_trait] -impl AsyncJob for LedJob { +impl AsyncJob for LightsJob { async fn setup(&mut self) -> bool { match &self.mode { - LedMode::Serial { port } => { + LightsMode::Serial { port } => { info!( "Serial port for led opening at {} {:?}", port.as_str(), @@ -187,11 +187,11 @@ impl AsyncJob for LedJob { // Do the IO here match self.mode { - LedMode::Reactive { sensitivity, .. } => { + LightsMode::Reactive { sensitivity, .. } => { let input_handle = self.state.input.lock(); flat_input = Some(input_handle.to_flat(&sensitivity)); } - LedMode::Serial { .. } => { + LightsMode::Serial { .. } => { if let Some(serial_port) = self.serial_port.as_mut() { let mut serial_data_avail = serial_port.bytes_to_read().unwrap_or(0); if serial_data_avail >= 100 {