diff --git a/src/framerate.rs b/src/framerate.rs new file mode 100644 index 0000000..dbab25b --- /dev/null +++ b/src/framerate.rs @@ -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 { + 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(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 9048f40..ac3d833 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,3 +5,4 @@ pub mod device; pub mod point; pub mod transformer; pub mod worldstate; +pub mod framerate; diff --git a/src/main.rs b/src/main.rs index 62067a8..c1ba308 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 => {