mirror of
https://github.com/4yn/slidershim.git
synced 2026-09-11 18:25:10 -05:00
timer
This commit is contained in:
@@ -140,9 +140,12 @@ fn main() {
|
||||
let manager_clone = Arc::clone(&manager);
|
||||
app.listen_global("queryState", move |_| {
|
||||
// app_handle.emit_all("showState", "@@@");
|
||||
let snapshot = {
|
||||
let (snapshot, timer) = {
|
||||
let manager_handle = manager_clone.lock().unwrap();
|
||||
manager_handle.try_get_state().map(|x| x.snapshot())
|
||||
(
|
||||
manager_handle.try_get_state().map(|x| x.snapshot()),
|
||||
manager_handle.get_timer_state(),
|
||||
)
|
||||
};
|
||||
match snapshot {
|
||||
Some(snapshot) => {
|
||||
@@ -150,6 +153,8 @@ fn main() {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
app_handle.emit_all("showTimerState", timer).ok();
|
||||
});
|
||||
|
||||
// Config set event
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use atomic_float::AtomicF64;
|
||||
use log::info;
|
||||
use std::sync::{atomic::Ordering, Arc};
|
||||
|
||||
use crate::slider_io::{
|
||||
brokenithm::BrokenithmJob,
|
||||
@@ -7,6 +9,7 @@ use crate::slider_io::{
|
||||
device::HidDeviceJob,
|
||||
led::LedJob,
|
||||
output::OutputJob,
|
||||
utils::LoopTimer,
|
||||
worker::{AsyncWorker, ThreadWorker},
|
||||
};
|
||||
|
||||
@@ -18,6 +21,7 @@ pub struct Context {
|
||||
brokenithm_worker: Option<AsyncWorker>,
|
||||
output_worker: Option<ThreadWorker>,
|
||||
led_worker: Option<ThreadWorker>,
|
||||
timers: Vec<(&'static str, Arc<AtomicF64>)>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@@ -28,6 +32,7 @@ impl Context {
|
||||
info!("LED config {:?}", config.led_mode);
|
||||
|
||||
let state = FullState::new();
|
||||
let mut timers = vec![];
|
||||
|
||||
let (device_worker, brokenithm_worker) = match &config.device_mode {
|
||||
DeviceMode::None => (None, None),
|
||||
@@ -42,26 +47,41 @@ impl Context {
|
||||
)),
|
||||
),
|
||||
_ => (
|
||||
Some(ThreadWorker::new(
|
||||
"device",
|
||||
HidDeviceJob::from_config(&state, &config.device_mode),
|
||||
)),
|
||||
{
|
||||
let timer = LoopTimer::new();
|
||||
timers.push(("d", timer.fork()));
|
||||
Some(ThreadWorker::new(
|
||||
"device",
|
||||
HidDeviceJob::from_config(&state, &config.device_mode),
|
||||
timer,
|
||||
))
|
||||
},
|
||||
None,
|
||||
),
|
||||
};
|
||||
let output_worker = match &config.output_mode {
|
||||
OutputMode::None => None,
|
||||
_ => Some(ThreadWorker::new(
|
||||
"output",
|
||||
OutputJob::new(&state, &config.output_mode),
|
||||
)),
|
||||
_ => {
|
||||
let timer = LoopTimer::new();
|
||||
timers.push(("o", timer.fork()));
|
||||
Some(ThreadWorker::new(
|
||||
"output",
|
||||
OutputJob::new(&state, &config.output_mode),
|
||||
timer,
|
||||
))
|
||||
}
|
||||
};
|
||||
let led_worker = match &config.led_mode {
|
||||
LedMode::None => None,
|
||||
_ => Some(ThreadWorker::new(
|
||||
"led",
|
||||
LedJob::new(&state, &config.led_mode),
|
||||
)),
|
||||
_ => {
|
||||
let timer = LoopTimer::new();
|
||||
timers.push(("l", timer.fork()));
|
||||
Some(ThreadWorker::new(
|
||||
"led",
|
||||
LedJob::new(&state, &config.led_mode),
|
||||
timer,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
@@ -71,10 +91,20 @@ impl Context {
|
||||
brokenithm_worker,
|
||||
output_worker,
|
||||
led_worker,
|
||||
timers,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_state(&self) -> FullState {
|
||||
self.state.clone()
|
||||
}
|
||||
|
||||
pub fn timer_state(&self) -> String {
|
||||
self
|
||||
.timers
|
||||
.iter()
|
||||
.map(|(s, f)| format!("{}:{:.1}/s", s, f.load(Ordering::SeqCst)))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,9 +101,9 @@ impl HidDeviceJob {
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
{
|
||||
buf_chunk[0] = state_chunk[2];
|
||||
buf_chunk[0] = state_chunk[1];
|
||||
buf_chunk[1] = state_chunk[0];
|
||||
buf_chunk[2] = state_chunk[1];
|
||||
buf_chunk[2] = state_chunk[2];
|
||||
}
|
||||
buf.data[96..240].fill(0);
|
||||
},
|
||||
@@ -139,9 +139,9 @@ impl HidDeviceJob {
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
{
|
||||
buf_chunk[0] = state_chunk[2];
|
||||
buf_chunk[0] = state_chunk[1];
|
||||
buf_chunk[1] = state_chunk[0];
|
||||
buf_chunk[2] = state_chunk[1];
|
||||
buf_chunk[2] = state_chunk[2];
|
||||
}
|
||||
buf.data[96..240].fill(0);
|
||||
},
|
||||
@@ -224,9 +224,10 @@ impl ThreadJob for HidDeviceJob {
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
fn tick(&mut self) -> bool {
|
||||
// Input loop
|
||||
let handle = self.handle.as_mut().unwrap();
|
||||
let mut work = false;
|
||||
|
||||
{
|
||||
let res = handle
|
||||
@@ -239,6 +240,7 @@ impl ThreadJob for HidDeviceJob {
|
||||
self.read_buf.len = res;
|
||||
// debug!("{:?}", self.read_buf.slice());
|
||||
if self.read_buf.len != 0 {
|
||||
work = true;
|
||||
let mut controller_state_handle = self.state.controller_state.lock().unwrap();
|
||||
(self.read_callback)(&self.read_buf, controller_state_handle.deref_mut());
|
||||
}
|
||||
@@ -267,12 +269,13 @@ impl ThreadJob for HidDeviceJob {
|
||||
})
|
||||
.unwrap_or(0);
|
||||
if res == self.led_buf.len + 1 {
|
||||
work = true;
|
||||
self.led_buf.len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// thread::sleep(Duration::from_millis(10));
|
||||
work
|
||||
}
|
||||
|
||||
fn teardown(&mut self) {
|
||||
|
||||
@@ -174,7 +174,7 @@ impl ThreadJob for LedJob {
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
fn tick(&mut self) -> bool {
|
||||
let mut flat_controller_state: Option<Vec<bool>> = None;
|
||||
let mut serial_buffer: Option<Buffer> = None;
|
||||
|
||||
@@ -217,7 +217,10 @@ impl ThreadJob for LedJob {
|
||||
led_state_handle.deref_mut(),
|
||||
);
|
||||
}
|
||||
thread::sleep(Duration::from_millis(30));
|
||||
// thread::sleep(Duration::from_millis(30));
|
||||
spin_sleep::sleep(Duration::from_millis(30));
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn teardown(&mut self) {}
|
||||
|
||||
@@ -14,6 +14,7 @@ use super::controller_state::FullState;
|
||||
|
||||
pub struct Manager {
|
||||
state: Arc<Mutex<Option<FullState>>>,
|
||||
context: Arc<Mutex<Option<Context>>>,
|
||||
join_handle: Option<JoinHandle<()>>,
|
||||
tx_config: mpsc::UnboundedSender<Config>,
|
||||
tx_stop: Option<oneshot::Sender<()>>,
|
||||
@@ -70,6 +71,7 @@ impl Manager {
|
||||
|
||||
Self {
|
||||
state,
|
||||
context,
|
||||
join_handle: Some(join_handle),
|
||||
tx_config,
|
||||
tx_stop: Some(tx_stop),
|
||||
@@ -84,6 +86,14 @@ impl Manager {
|
||||
let state_handle = self.state.lock().unwrap();
|
||||
state_handle.as_ref().map(|x| x.clone())
|
||||
}
|
||||
|
||||
pub fn get_timer_state(&self) -> String {
|
||||
let context_handle = self.context.lock().unwrap();
|
||||
context_handle
|
||||
.as_ref()
|
||||
.map(|context| context.timer_state())
|
||||
.unwrap_or("".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Manager {
|
||||
|
||||
@@ -50,7 +50,7 @@ impl ThreadJob for OutputJob {
|
||||
true
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
fn tick(&mut self) -> bool {
|
||||
let flat_controller_state: Vec<bool>;
|
||||
{
|
||||
let controller_state_handle = self.state.controller_state.lock().unwrap();
|
||||
@@ -58,7 +58,10 @@ impl ThreadJob for OutputJob {
|
||||
}
|
||||
|
||||
self.handler.tick(&flat_controller_state);
|
||||
thread::sleep(Duration::from_millis(self.t));
|
||||
// thread::sleep(Duration::from_millis(self.t));
|
||||
spin_sleep::sleep(Duration::from_millis(self.t));
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn teardown(&mut self) {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
use std::{error::Error, fmt};
|
||||
use atomic_float::AtomicF64;
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct Buffer {
|
||||
pub data: [u8; 256],
|
||||
@@ -44,3 +50,45 @@ pub fn list_ips() -> Result<Vec<String>, Box<dyn Error>> {
|
||||
|
||||
Ok(ips)
|
||||
}
|
||||
|
||||
pub struct LoopTimer {
|
||||
cap: usize,
|
||||
cur: usize,
|
||||
buf: Vec<Instant>,
|
||||
freq: Arc<AtomicF64>,
|
||||
}
|
||||
|
||||
impl LoopTimer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cap: 100,
|
||||
cur: 0,
|
||||
buf: vec![Instant::now() - Duration::from_secs(10); 100],
|
||||
freq: Arc::new(AtomicF64::new(0.0)),
|
||||
}
|
||||
}
|
||||
pub fn tick(&mut self) {
|
||||
let last = self.buf[self.cur];
|
||||
let now = Instant::now();
|
||||
self.buf[self.cur] = now;
|
||||
|
||||
let delta = (now - last) / 100 + Duration::from_micros(1);
|
||||
let freq = Duration::from_millis(1000)
|
||||
.div_duration_f64(delta)
|
||||
.clamp(0.0, 9999.0);
|
||||
self.freq.store(freq, Ordering::SeqCst);
|
||||
|
||||
self.cur = match self.cur + 1 {
|
||||
cur if cur == self.cap => 0,
|
||||
cur => cur,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn reset(&mut self) {
|
||||
// self.buf = vec![Instant::now(); 100];
|
||||
// }
|
||||
|
||||
pub fn fork(&self) -> Arc<AtomicF64> {
|
||||
Arc::clone(&self.freq)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,11 @@ use std::{
|
||||
|
||||
use tokio::{sync::oneshot, task};
|
||||
|
||||
use crate::slider_io::utils::LoopTimer;
|
||||
|
||||
pub trait ThreadJob: Send {
|
||||
fn setup(&mut self) -> bool;
|
||||
fn tick(&mut self);
|
||||
fn tick(&mut self) -> bool;
|
||||
fn teardown(&mut self);
|
||||
}
|
||||
|
||||
@@ -24,7 +26,7 @@ pub struct ThreadWorker {
|
||||
}
|
||||
|
||||
impl ThreadWorker {
|
||||
pub fn new<T: 'static + ThreadJob>(name: &'static str, mut job: T) -> Self {
|
||||
pub fn new<T: 'static + ThreadJob>(name: &'static str, mut job: T, mut timer: LoopTimer) -> Self {
|
||||
info!("Thread worker starting {}", name);
|
||||
|
||||
let stop_signal = Arc::new(AtomicBool::new(false));
|
||||
@@ -40,7 +42,9 @@ impl ThreadWorker {
|
||||
if stop_signal_clone.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
job.tick();
|
||||
if job.tick() {
|
||||
timer.tick();
|
||||
}
|
||||
}
|
||||
info!("Thread worker stopping internal {}", name);
|
||||
job.teardown();
|
||||
|
||||
Reference in New Issue
Block a user