From 650a3ed521dab9826f95c29e9c851ade1bf32ec7 Mon Sep 17 00:00:00 2001 From: alban Date: Sat, 5 Aug 2023 19:11:33 +0200 Subject: [PATCH] wip: dirty state for debugging etherdream --- copyme.settings.toml | 8 +- examples/etherdream.rs | 237 ++++++++++++------------ src/conf.rs | 2 +- src/device/etherdream.rs | 75 ++++---- src/main.rs | 2 +- src/point.rs | 1 + src/transformer/helios_to_etherdream.rs | 7 +- src/transformer/intensity.rs | 14 +- 8 files changed, 176 insertions(+), 170 deletions(-) diff --git a/copyme.settings.toml b/copyme.settings.toml index ea131ff..3ced243 100644 --- a/copyme.settings.toml +++ b/copyme.settings.toml @@ -22,10 +22,10 @@ redis_url = "redis://127.0.0.1:6379/" # [dac.etherdream] # ip = "192.168.1.68" -[[transformers]] -[transformers.translate] -x = 2000 -y = 2000 +#[[transformers]] +#[transformers.translate] +#x = 20 +#y = 20 [[transformers]] [transformers.replicate] diff --git a/examples/etherdream.rs b/examples/etherdream.rs index c521b0b..901dcff 100644 --- a/examples/etherdream.rs +++ b/examples/etherdream.rs @@ -3,149 +3,148 @@ extern crate ether_dream; use ether_dream::dac; fn main() { - println!("Listening for an Ether Dream DAC..."); + println!("Listening for an Ether Dream DAC..."); - let (dac_broadcast, source_addr) = ether_dream::recv_dac_broadcasts() - .expect("failed to bind to UDP socket") - .filter_map(Result::ok) - .next() - .unwrap(); - let mac_address = dac::MacAddress(dac_broadcast.mac_address); + let (dac_broadcast, source_addr) = ether_dream::recv_dac_broadcasts() + .expect("failed to bind to UDP socket") + .filter_map(Result::ok) + .next() + .unwrap(); + let mac_address = dac::MacAddress(dac_broadcast.mac_address); - println!( - "Discovered DAC \"{}\" at \"{}\"! Connecting...", - mac_address, source_addr - ); + println!( + "Discovered DAC \"{}\" at \"{}\"! Connecting...", + mac_address, source_addr + ); - // Establish the TCP connection. - let mut stream = dac::stream::connect(&dac_broadcast, source_addr.ip().clone()).unwrap(); + // Establish the TCP connection. + let mut stream = dac::stream::connect(&dac_broadcast, source_addr.ip().clone()).unwrap(); - // If we want to create an animation (in our case a moving sine wave) we need a frame rate. - let frames_per_second = 60.0; - // Lets use the DAC at an eighth the maximum scan rate. - let points_per_second = stream.dac().max_point_rate / 32; - // Determine the number of points per frame given our target frame and point rates. - let points_per_frame = (points_per_second as f32 / frames_per_second) as u16; + // If we want to create an animation (in our case a moving sine wave) we need a frame rate. + let frames_per_second = 60.0; + // Lets use the DAC at an eighth the maximum scan rate. + let points_per_second = 20_000; + // Determine the number of points per frame given our target frame and point rates. + let points_per_frame = (points_per_second as f32 / frames_per_second) as u16; - println!( - "Preparing for playback:\n\tframe_hz: {}\n\tpoint_hz: {}\n\tpoints_per_frame: {}\n", - frames_per_second, points_per_second, points_per_frame - ); + println!( + "Preparing for playback:\n\tframe_hz: {}\n\tpoint_hz: {}\n\tpoints_per_frame: {}\n", + frames_per_second, points_per_second, points_per_frame + ); - // Prepare the DAC's playback engine and await the repsonse. - stream - .queue_commands() - .prepare_stream() - .submit() - .err() - .map(|err| { - eprintln!( - "err occurred when submitting PREPARE_STREAM \ + // Prepare the DAC's playback engine and await the repsonse. + stream + .queue_commands() + .prepare_stream() + .submit() + .err() + .map(|err| { + eprintln!( + "err occurred when submitting PREPARE_STREAM \ command and listening for response: {}", - err - ); - }); + err + ); + }); - println!("Beginning playback!"); + println!("Beginning playback!"); - // The sine wave used to generate points. - let mut sine_wave = SineWave { - point: 0, - points_per_frame, - frames_per_second, - }; + // The sine wave used to generate points. + let mut sine_wave = SineWave { + point: 0, + points_per_frame, + frames_per_second, + }; - // Queue the initial frame and tell the DAC to begin producing output. - let n_points = points_to_generate(stream.dac()); - stream - .queue_commands() - .data(sine_wave.by_ref().take(n_points)) - .begin(0, points_per_second) - .submit() - .err() - .map(|err| { - eprintln!( - "err occurred when submitting initial DATA and BEGIN \ + // Queue the initial frame and tell the DAC to begin producing output. + let n_points = points_to_generate(stream.dac()); + stream + .queue_commands() + .data(sine_wave.by_ref().take(n_points)) + .begin(0, points_per_second) + .submit() + .err() + .map(|err| { + eprintln!( + "err occurred when submitting initial DATA and BEGIN \ commands and listening for response: {}", - err - ); - }); - eprintln!("Stream dac{:?}", stream.dac()); + err + ); + }); - // Loop and continue to send points forever. - loop { - // Determine how many points the DAC can currently receive. - let n_points = points_to_generate(stream.dac()); - if let Err(err) = stream - .queue_commands() - .data(sine_wave.by_ref().take(n_points)) - .submit() - { - eprintln!( - "err occurred when submitting DATA command and listening \ + // Loop and continue to send points forever. + loop { + // Determine how many points the DAC can currently receive. + let n_points = points_to_generate(stream.dac()); + if let Err(err) = stream + .queue_commands() + .data(sine_wave.by_ref().take(n_points)) + .submit() + { + eprintln!( + "err occurred when submitting DATA command and listening \ for response: {}", - err - ); - break; - } - } + err + ); + break; + } + } - // Tell the DAC to stop producing output and return to idle. Wait for the response. - // - // Note that the DAC is commanded to stop on `Drop` if this is not called and any errors - // produced are ignored. - stream - .queue_commands() - .stop() - .submit() - .expect("err occurred when submitting STOP command and listening for response"); + // Tell the DAC to stop producing output and return to idle. Wait for the response. + // + // Note that the DAC is commanded to stop on `Drop` if this is not called and any errors + // produced are ignored. + stream + .queue_commands() + .stop() + .submit() + .expect("err occurred when submitting STOP command and listening for response"); } // Determine the number of points needed to fill the DAC. fn points_to_generate(dac: ðer_dream::dac::Dac) -> usize { - dac.buffer_capacity as usize - 1 - dac.status.buffer_fullness as usize + dac.buffer_capacity as usize - 1 - dac.status.buffer_fullness as usize } // An iterator that endlessly generates a sine wave of DAC points. // // The sine wave oscillates at a rate of once per second. struct SineWave { - point: u32, - points_per_frame: u16, - frames_per_second: f32, + point: u32, + points_per_frame: u16, + frames_per_second: f32, } impl Iterator for SineWave { - type Item = ether_dream::protocol::DacPoint; - fn next(&mut self) -> Option { - let coloured_points_per_frame = self.points_per_frame - 1; - let i = (self.point % self.points_per_frame as u32) as u16; - let hz = 1.0; - let fract = i as f32 / coloured_points_per_frame as f32; - let phase = (self.point as f32 / coloured_points_per_frame as f32) / self.frames_per_second; - let amp = (hz * (fract + phase) * 2.0 * std::f32::consts::PI).sin(); - let (r, g, b) = match i { - i if i == coloured_points_per_frame || i < 13 => (0, 0, 0), - _ => (std::u16::MAX, std::u16::MAX, std::u16::MAX), - }; - let x_min = std::i16::MIN; - let x_max = std::i8::MAX as i16; - let x = (x_min as f32 + fract * (x_max as f32 - x_min as f32)) as i16; - let y = (amp * x_max as f32) as i16; - let control = 0; - let (u1, u2) = (0, 0); - let p = ether_dream::protocol::DacPoint { - control, - x, - y, - i, - r, - g, - b, - u1, - u2, - }; - self.point += 1; - Some(p) - } -} \ No newline at end of file + type Item = ether_dream::protocol::DacPoint; + fn next(&mut self) -> Option { + let coloured_points_per_frame = self.points_per_frame - 1; + let i = (self.point % self.points_per_frame as u32) as u16; + let hz = 1.0; + let fract = i as f32 / coloured_points_per_frame as f32; + let phase = (self.point as f32 / coloured_points_per_frame as f32) / self.frames_per_second; + let amp = (hz * (fract + phase) * 2.0 * std::f32::consts::PI).sin(); + let (r, g, b) = match i { + i if i == coloured_points_per_frame || i < 13 => (0, 0, 0), + _ => (std::u16::MAX, std::u16::MAX, std::u16::MAX), + }; + let x_min = std::i16::MIN; + let x_max = std::i16::MAX; + let x = (x_min as f32 + fract * (x_max as f32 - x_min as f32)) as i16; + let y = (amp * x_max as f32) as i16; + let control = 0; + let (u1, u2) = (0, 0); + let p = ether_dream::protocol::DacPoint { + control, + x, + y, + i, + r, + g, + b, + u1, + u2, + }; + self.point += 1; + Some(p) + } +} diff --git a/src/conf.rs b/src/conf.rs index 9cff95c..f1b4aa1 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -78,7 +78,7 @@ impl Conf { TransformConf::Intensity(r) => Box::new(*r), TransformConf::Replicate(r) => Box::new(*r), TransformConf::Rotate(r) => Box::new(*r), - TransformConf::Translate(t) => Box::new(*t), + TransformConf::Translate(r) => Box::new(*r), }; v.push(t); } diff --git a/src/device/etherdream.rs b/src/device/etherdream.rs index b9e3cab..bd1a898 100644 --- a/src/device/etherdream.rs +++ b/src/device/etherdream.rs @@ -1,5 +1,5 @@ #[warn(unused_imports)] -use log::{ debug, info, warn}; +use log::{debug, info, warn}; use std::net::SocketAddr; use std::thread::sleep; @@ -14,6 +14,7 @@ use crate::device::{Device, Status, PlaybackState}; use crate::errors::{LJError, LJResult}; use crate::point::{Color, Point}; use ether_dream::protocol::{DacBroadcast, DacResponse}; +use crate::device::PlaybackState::PLAYING; #[warn(dead_code)] @@ -21,18 +22,6 @@ pub struct EtherdreamDevice { pub conf: EtherDreamConf, dac: DacBroadcast, stream: Stream, - - // "a": ACK "F": Full "I": invalid. 64 or 35 for no connection. - // /// The previous command was accepted. - // pub const ACK: u8 = 0x61; - // /// The write command could not be performed because there was not enough buffer space when it - // /// was received. - // pub const NAK_FULL: u8 = 0x46; - // /// The command contained an invalid `command` byte or parameters. - // pub const NAK_INVALID: u8 = 0x49; - // /// An emergency-stop condition still exists. - // pub const NAK_STOP_CONDITION: u8 = 0x21; - // } dac_response: u8, } @@ -52,7 +41,7 @@ impl EtherdreamDevice { dac_broadcast.set_timeout(Some(time::Duration::new(10, 0)))?; info!("Attempting to get DAC broadcast..."); let broadcast = dac_broadcast - .take(3) + .take(5) .filter_map(|result| { match result { Err(err) => { @@ -85,17 +74,34 @@ impl EtherdreamDevice { fn get_tcp_stream(dac: &DacBroadcast, source_address: &SocketAddr) -> LJResult { let mut stream = connect(dac, source_address.ip())?; - match stream - .queue_commands() - .prepare_stream() - .submit() { - Err(err) => warn!("err occurred when submitting PREPARE_STREAM command and listening for response: {}",err), - Ok(_) => info!("Prepared Stream.") + debug!("Stream dac BEFORE PREPARE {:?}", stream.dac()); + debug!("Playback State BEFORE PREPARE {:?}, {:?}", stream.dac().dac.status.playback, Playback::Playing ); + if stream.dac().dac.status.playback == Playback::Playing { + warn!("DAC was in playback PLAYING, attempting to stop"); + match stream + .queue_commands() + .stop() + .submit() { + Err(err) => warn!("err occurred when submitting STOP command: {}",err), + Ok(_) => info!("Prepared Stream.") + } + } + if stream.dac().dac.status.playback != Playback::Prepared { + warn!("DAC was not in playback state PREPARED, attempting to prepare"); + match stream + .queue_commands() + .prepare_stream() + .submit() { + Err(err) => warn!("err occurred when submitting PREPARE_STREAM command and listening for response: {}",err), + Ok(_) => info!("Prepared Stream.") + } } // If we want to create an animation (in our case a moving sine wave) we need a frame rate. let frames_per_second = 60.0; // Lets use the DAC at an eighth the maximum scan rate. - let points_per_second = stream.dac().max_point_rate / 32; + let points_per_second = 20_000; + // let points_per_second = 30_000; + debug!("points per second {:?}", points_per_second); // Determine the number of points per frame given our target frame and point rates. let points_per_frame = (points_per_second as f32 / frames_per_second) as u16; @@ -104,6 +110,7 @@ impl EtherdreamDevice { points_per_frame, frames_per_second, }; + debug!("Stream dac BEFORE BEGIN {:?}", stream.dac()); match stream .queue_commands() @@ -122,15 +129,15 @@ impl EtherdreamDevice { /*** Determine the number of points needed to fill the DAC. ***/ - // Fixme thread 'main' panicked at 'attempt to subtract with overflow', src/device/etherdream.rs:144:24 - let n_points = self.dac.buffer_capacity as usize - self.stream.dac().dac.status.buffer_fullness as usize - 1; + let cap = self.dac.buffer_capacity as usize; + let fullness = self.stream.dac().dac.status.buffer_fullness as usize; + // Sometimes we had thread 'main' panicked at 'attempt to subtract with overflow', src/device/etherdream.rs:144:24 + let n_points = if cap > fullness { cap - fullness } else { 0 }; n_points } fn ping(&mut self) -> LJResult<()> { - Ok(self.stream.queue_commands().ping().submit()?) - } } @@ -144,6 +151,9 @@ impl Device for EtherdreamDevice { let now = SystemTime::now(); let now: DateTime = now.into(); let now = now.to_rfc3339(); + // debug!("Dac Status: {:?} ", status ); + // debug!("Etherdream Dac {:?} ", self.dac ); + debug!("Stream dac{:?}", self.stream.dac()); Status { last_traced_at: now, @@ -152,9 +162,6 @@ impl Device for EtherdreamDevice { capacity: self.points_capacity(), lack: self.dac_response.to_string(), } - // debug!("Dac Status: {:?} ", status ); - // debug!("Etherdream Dac {:?} ", self.dac ); - // debug!("Stream dac{:?}", self.stream.dac()); // status } @@ -162,22 +169,23 @@ impl Device for EtherdreamDevice { line: Vec, _speed: u32, ) -> LJResult<()> { - let chunk_size = 64; + let chunk_size = 111; let points_iter = line.into_iter(); - for chunk in points_iter.as_slice().chunks(chunk_size){ + for chunk in points_iter.as_slice().chunks(chunk_size) { debug!("New chunk length: {:?}", chunk.len()); loop { let capacity = self.points_capacity(); + debug!("capacity : {:?}", capacity); if chunk.len() > capacity as usize { - debug!("Sleep, capacity : {:?}", capacity); + debug!("Sleep"); // Sleep for 1/100th of a sec - sleep(Duration::new( 0, 10000000)); + sleep(Duration::new(0, 10_000_000)); self.ping(); } else { break; } } - debug!("drawing"); + debug!("Drawing"); match self.stream .queue_commands() .data( @@ -216,6 +224,7 @@ impl Device for EtherdreamDevice { fn stop(&mut self) -> LJResult<()> { info!("Stopping Etherdream device..."); + info!("Stream dac{:?}", self.stream.dac()); match self.stream .queue_commands() .stop() diff --git a/src/main.rs b/src/main.rs index c1ba308..fd51d53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,7 @@ fn run_all() -> LJResult<()> { // Dispatch based on redis requests while running.load(Ordering::SeqCst) { rs.set_status(tracer.status())?; - let _ = framerate_handler.handle_time()?; + // let _ = framerate_handler.handle_time()?; let order = rs.get_order(config.laser_id)?; match order { Order::Draw | Order::Black | Order::Grid => { diff --git a/src/point.rs b/src/point.rs index 21b5694..e7eb5f9 100644 --- a/src/point.rs +++ b/src/point.rs @@ -15,6 +15,7 @@ pub struct Color { pub g: u8, pub b: u8, } + impl Mul for Color { type Output = Self; diff --git a/src/transformer/helios_to_etherdream.rs b/src/transformer/helios_to_etherdream.rs index 1891d5d..86cf31a 100644 --- a/src/transformer/helios_to_etherdream.rs +++ b/src/transformer/helios_to_etherdream.rs @@ -7,16 +7,15 @@ use serde::{Serialize, Deserialize}; /// Converts helios Geometry to Helios #[allow(dead_code)] #[derive(Serialize, Deserialize, Debug, Clone, Copy)] -pub struct HeliosToEtherdream { -} +pub struct HeliosToEtherdream {} impl Transformers for HeliosToEtherdream { fn apply(&self, point_list: &[Point], _ws: &WorldState) -> Vec { // debug!("list helios {:?}", point_list); let out = point_list.iter().map(|pt| { Point { - x: 8.0 * (pt.x - 2047.0), - y: 8.0 * (pt.y - 2047.0), + x: 50.0 * (320.0 - pt.x), + y: 40.0 * (240.0 - pt.y), ..*pt } }).collect(); diff --git a/src/transformer/intensity.rs b/src/transformer/intensity.rs index 0aacc1c..6c70722 100644 --- a/src/transformer/intensity.rs +++ b/src/transformer/intensity.rs @@ -8,20 +8,18 @@ use serde::{Serialize, Deserialize}; /// Converts helios Geometry to Helios #[allow(dead_code)] #[derive(Serialize, Deserialize, Debug, Clone, Copy)] -pub struct Intensity { -} +pub struct Intensity {} impl Transformers for Intensity { fn apply(&self, point_list: &[Point], ws: &WorldState) -> Vec { // debug!("list helios {:?}", point_list); let out = point_list.iter().map(|pt| { Point { - x: pt.x, - y: pt.y, - color: pt.color * ws.intensity - } - }).collect(); - debug!("list intensity {:?}", out); + color: pt.color * ws.intensity, + ..*pt + } + }).collect(); + // debug!("list intensity {:?}", out); out } }