Compare commits

...

5 Commits

Author SHA1 Message Date
alban 22d7d3c718 fix: i in point for etherdream is meh 2023-07-24 17:35:39 +02:00
alban 514f4cc7c9 fix: etherdream should work with device trait adjustments 2023-07-24 17:35:15 +02:00
alban 6f04925ea5 feat: add framerate with fixed value for now (20Hz) 2023-07-24 17:34:06 +02:00
alban 3ce346306f feat: add helios to etherdream transformer 2023-07-24 17:29:33 +02:00
alban ff96bdf6fa fix: etherdream example 2023-07-24 17:28:18 +02:00
12 changed files with 202 additions and 55 deletions

View File

@ -129,7 +129,7 @@ impl Iterator for SineWave {
_ => (std::u16::MAX, std::u16::MAX, std::u16::MAX),
};
let x_min = std::i16::MIN;
let x_max = std::i16::MAX;
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;

46
examples/test.rs Normal file
View File

@ -0,0 +1,46 @@
///
/// $ cargo run --example simple_client
///
use redis::{
//RedisResult,
Client,
Commands,
Connection,
};
use std::time::Instant;
fn do_something() -> redis::RedisResult<()> {
let client = Client::open("redis://127.0.0.1/")?;
let mut con: Connection = client.get_connection()?;
let start = Instant::now();
loop {
let elapsed = start.elapsed();
let time = 60.0 * elapsed.as_millis() as f32 / 1000.0;
let mut v: Vec<(f32, f32, u32)> = vec![];
for i in 0..128 {
let a = (time + i as f32) / 128.0 * std::f32::consts::PI * 2.0;
let r = 1200.0 + (a * 5.0).cos() * (500.0 * (time / 5.0).cos());
let x = a.cos() * r;
let y = a.sin() * r;
let col = if i % 8 < 4 {
0x000000ff
} else {
0x00ff0000
};
v.push((x, y, col));
}
// println!("{:?}", v);
let _ = con.set("/pl/0/0", format!("{:?}", v))?;
}
// Ok(())
}
fn main() {
_ = do_something();
}

View File

@ -48,7 +48,9 @@ pub enum TransformConf {
#[serde(rename = "grid")]
Grid(transformer::Grid),
#[serde(rename = "homography")]
Homography(transformer::Homography)
Homography(transformer::Homography),
#[serde(rename = "helios_to_etherdream")]
HeliosToEtherdream(transformer::HeliosToEtherdream),
}
@ -73,6 +75,7 @@ impl Conf {
TransformConf::FlipV(r) => Box::new(*r),
TransformConf::Grid(r) => Box::new(*r),
TransformConf::Homography(r) => Box::new(*r),
TransformConf::HeliosToEtherdream(r) => Box::new(*r),
};
v.push(t);
}

View File

@ -42,7 +42,7 @@ pub struct Status {
pub last_traced_at: String,
pub properties: Vec<String>,
pub playback_state: PlaybackState,
pub capacity: u16,
pub capacity: usize,
pub lack: String,
}

View File

@ -1,16 +1,20 @@
use std::time;
#[warn(unused_imports)]
use log::{ debug, info, warn};
use std::net::SocketAddr;
use std::thread::sleep;
use ether_dream::dac::stream::{CommunicationError, connect};
use ether_dream::dac::{Playback, Stream};
use chrono::{DateTime, Utc};
use std::time::SystemTime;
use std::time;
use std::time::{Duration, SystemTime};
use crate::conf::EtherDreamConf;
use crate::device::{Device, Status, PlaybackState};
use crate::errors::{LJError, LJResult};
use crate::point::{Color, Point};
use ether_dream::protocol::{DacBroadcast, DacResponse};
use log::{debug, info, warn};
#[warn(dead_code)]
pub struct EtherdreamDevice {
@ -114,14 +118,20 @@ impl EtherdreamDevice {
Ok(stream)
}
fn points_capacity(&self) -> u16 {
fn points_capacity(&self) -> usize {
/***
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 u16 - self.stream.dac().dac.status.buffer_fullness as u16 - 1;
let n_points = self.dac.buffer_capacity as usize - self.stream.dac().dac.status.buffer_fullness as usize - 1;
n_points
}
fn ping(&mut self) -> LJResult<()> {
Ok(self.stream.queue_commands().ping().submit()?)
}
}
impl Device for EtherdreamDevice {
@ -135,62 +145,72 @@ impl Device for EtherdreamDevice {
let now: DateTime<Utc> = now.into();
let now = now.to_rfc3339();
let status = Status {
Status {
last_traced_at: now,
properties: vec!["foo".to_string()],
playback_state,
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
// debug!("Stream dac{:?}", self.stream.dac());
// status
}
fn draw(&mut self,
line: Vec<Point>,
_speed: u32,
) -> LJResult<()> {
let n_points = self.points_capacity();
// let n_points = &line.len();
debug!("Etherdream::device draw Generating {:?} points", n_points);
match self.stream
.queue_commands()
.data(
line.into_iter()
.map(|point| point.into())
.take(n_points as usize)
)
// .data(sine_wave.by_ref().take(n_points as usize))
.submit() {
Err(err) => {
// We should account for
// 'Broken pipe (os error 32)'
// Connection reset by peer (os error 104)
self.dac_response = match err {
CommunicationError::Io(err) => {
warn!("IO ERROR while drawing: '{}'",err);
DacResponse::ACK
}
CommunicationError::Protocol(err) => {
warn!("Protocol ERROR while drawing: '{}'",err);
DacResponse::ACK
}
CommunicationError::Response(err) => {
warn!("Response ERROR while drawing: '{}'",err);
err.response.response
}
};
let chunk_size = 64;
let points_iter = line.into_iter();
for chunk in points_iter.as_slice().chunks(chunk_size){
debug!("New chunk length: {:?}", chunk.len());
loop {
let capacity = self.points_capacity();
if chunk.len() > capacity as usize {
debug!("Sleep, capacity : {:?}", capacity);
// Sleep for 1/100th of a sec
sleep(Duration::new( 0, 10000000));
self.ping();
} else {
break;
}
}
Ok(_) => {
self.dac_response = DacResponse::ACK;
debug!("Draw is ok");
}
};
debug!("drawing");
match self.stream
.queue_commands()
.data(
chunk.into_iter()
.map(|point| (*point).into())
.take(chunk_size as usize)
)
.submit() {
Err(err) => {
// We should account for
// 'Broken pipe (os error 32)'
// Connection reset by peer (os error 104)
self.dac_response = match err {
CommunicationError::Io(err) => {
warn!("IO ERROR while drawing: '{}'",err);
DacResponse::ACK
}
CommunicationError::Protocol(err) => {
warn!("Protocol ERROR while drawing: '{}'",err);
DacResponse::ACK
}
CommunicationError::Response(err) => {
warn!("Response ERROR while drawing: '{}'",err);
err.response.response
}
};
}
Ok(_) => {
self.dac_response = DacResponse::ACK;
// debug!("Draw is ok");
}
};
}
Ok(())
}
@ -274,7 +294,7 @@ impl Iterator for SineWave {
u1,
u2,
};
debug!("{:?}",p);
// debug!("{:?}",p);
self.point += 1;
Some(p)
}

View File

@ -57,7 +57,7 @@ impl Device for HeliosDevice {
last_traced_at: self.last_traced_at.clone(),
properties: vec!["foo".to_string()],
playback_state: self.state,
capacity: self.sent_points,
capacity: self.sent_points as usize,
lack,
}
}

39
src/framerate.rs Normal file
View File

@ -0,0 +1,39 @@
use log::{debug, warn};
use std::time::{Duration, Instant};
use crate::errors::LJResult;
use std::{thread};
/// Converts helios Geometry to Helios
#[derive(Debug, Clone, Copy)]
pub struct Framerate {
prev_trace_time: Instant,
fps: u8,
}
impl Framerate {
pub fn new() -> LJResult<Self> {
Ok(Framerate {
prev_trace_time: Instant::now(),
fps: 20,
})
}
pub fn handle_time(&mut self) -> LJResult<()> {
let frame_time = 1000000000 / self.fps as u128;
let now = Instant::now();
// How long since last loop ?
let nanotime_spent = self.prev_trace_time.elapsed().as_nanos();
// Diw it go too fast? If so : sleep a bit
if frame_time > nanotime_spent {
let nanotime_towait = frame_time - nanotime_spent;
let dur = Duration::new(0, (nanotime_towait as f32 * 0.9) as u32);
// debug!("{:?} - {:?} : {:?}", nanotime_towait, self.prev_trace_time, now );
thread::sleep(dur);
debug!("Framerate OK");
} else {
warn!("Frame longer than expected {:?} > {:?}", nanotime_spent, frame_time, );
}
self.prev_trace_time = now;
Ok(())
}
}

View File

@ -5,3 +5,4 @@ pub mod device;
pub mod point;
pub mod transformer;
pub mod worldstate;
pub mod framerate;

View File

@ -9,6 +9,7 @@ mod point;
mod transformer;
mod device;
mod worldstate;
mod framerate;
use device::device_factory;
use std::sync::atomic::{AtomicBool, Ordering};
@ -21,6 +22,7 @@ use transformer::Transformers;
use log::{LevelFilter, info, /* warn, */ error};
use env_logger::Builder;
use worldstate::WorldState;
use framerate::Framerate;
const DEFAULT_CONF_FILE: &str = "settings.toml";
@ -68,9 +70,13 @@ fn run_all() -> LJResult<()> {
// Setup geometry transformers on points lists
let transformers = config.get_transformers();
// Setup framerate limiter
let mut framerate_handler = Framerate::new()?;
// Dispatch based on redis requests
while running.load(Ordering::SeqCst) {
rs.set_status(tracer.status())?;
let _ = framerate_handler.handle_time()?;
let order = rs.get_order(config.laser_id)?;
match order {
Order::Draw | Order::Black | Order::Grid => {

View File

@ -1,5 +1,6 @@
use ether_dream::protocol::DacPoint;
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Point {
pub x: f32,
@ -48,10 +49,10 @@ impl From<Point> for DacPoint {
fn from(pt: Point) -> DacPoint {
let control = 0;
let (u1, u2) = (0, 0);
let i = 255;
let i = 0;
let x = pt.x.clamp(-32000.0, 32000.0);
let y = pt.y.clamp(-32000.0, 32000.0);
DacPoint {
let pt = DacPoint {
control,
x: x as i16,
y: y as i16,
@ -61,6 +62,8 @@ impl From<Point> for DacPoint {
b: (pt.color.b as u16) * 255,
u1,
u2,
}
};
// debug!("point {:?}", pt);
pt
}
}

View File

@ -6,6 +6,7 @@ mod flip_horizontal;
mod flip_vertical;
mod grid;
mod homography;
mod helios_to_etherdream;
use crate::point::Point;
use crate::worldstate::WorldState;
@ -18,6 +19,7 @@ pub use flip_horizontal::FlipHorizontal;
pub use flip_vertical::FlipVertical;
pub use grid::Grid;
pub use self::homography::Homography;
pub use helios_to_etherdream::HeliosToEtherdream;
pub trait Transformers {
fn apply(

View File

@ -0,0 +1,27 @@
use crate::transformer::Transformers;
use crate::point::Point;
use crate::worldstate::WorldState;
use serde::{Serialize, Deserialize};
/// Converts helios Geometry to Helios
#[allow(dead_code)]
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct HeliosToEtherdream {
}
impl Transformers for HeliosToEtherdream {
fn apply(&self, point_list: &[Point], _ws: &WorldState) -> Vec<Point> {
// 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),
..*pt
}
}).collect();
// debug!("list etherdream {:?}", out);
out
}
}