1
0
mirror of https://github.com/4yn/slidershim.git synced 2025-02-08 15:18:17 +01:00

diva draft

This commit is contained in:
4yn 2022-02-14 02:04:06 +08:00
parent 6bc462210f
commit 5865cd9d21
12 changed files with 334 additions and 198 deletions

View File

@ -5,41 +5,42 @@ use std::{future::Future, io, time::Duration};
use tokio::{select, time::sleep};
// use slidershim::slider_io::worker::{AsyncJob, AsyncWorker};
use slider_io::shared::worker::{AsyncHaltableJob, AsyncHaltableWorker};
// struct CounterJob;
struct CounterJob;
// #[async_trait]
// impl AsyncJob for CounterJob {
// async fn run<F: Future<Output = ()> + Send>(self, stop_signal: F) {
// let job_a = async {
// println!("Start job A");
// let mut x = 0;
// loop {
// x += 1;
// println!("{}", x);
// sleep(Duration::from_millis(100)).await;
// }
// };
// let job_b = async move {
// println!("Start job B");
// stop_signal.await;
// println!("Stop signal hit at job B");
// };
#[async_trait]
impl AsyncHaltableJob for CounterJob {
async fn run<F: Future<Output = ()> + Send>(self, stop_signal: F) {
let job_a = async {
println!("Start job A");
let mut x = 0;
loop {
x += 1;
println!("{}", x);
sleep(Duration::from_millis(500)).await;
}
};
let job_b = async move {
println!("Start job B");
stop_signal.await;
println!("Stop signal hit at job B");
};
// select! {
// _ = job_a => {},
// _ = job_b => {},
// }
// }
// }
select! {
_ = job_a => {},
_ = job_b => {},
}
}
}
fn main() {
#[tokio::main]
async fn main() {
env_logger::Builder::new()
.filter_level(log::LevelFilter::Debug)
.init();
// let worker = AsyncWorker::new("counter", CounterJob);
let _worker = AsyncHaltableWorker::new("counter", CounterJob);
let mut input = String::new();
let string = io::stdin().read_line(&mut input).unwrap();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -1,19 +1,20 @@
extern crate slider_io;
use std::{io, time::Duration};
use std::io;
use tokio::time::sleep;
use slider_io::{
device::brokenithm::BrokenithmJob, shared::worker::AsyncHaltableWorker, state::SliderState,
};
// use slidershim::slider_io::{
// brokenithm::BrokenithmJob, controller_state::FullState, worker::AsyncWorker,
// };
fn main() {
#[tokio::main]
async fn main() {
env_logger::Builder::new()
.filter_level(log::LevelFilter::Debug)
.init();
// let worker = AsyncWorker::new("brokenithm", BrokenithmJob::new(FullState::new()));
let state = SliderState::new();
let _worker = AsyncHaltableWorker::new("brokenithm", BrokenithmJob::new(&state, &false, &false));
let mut input = String::new();
let string = io::stdin().read_line(&mut input).unwrap();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -0,0 +1,27 @@
extern crate slider_io;
use std::io;
use slider_io::{
device::diva,
shared::{utils::LoopTimer, worker::ThreadWorker},
state::SliderState,
};
fn main() {
env_logger::Builder::new()
.filter_level(log::LevelFilter::Debug)
.init();
let state = SliderState::new();
let timer = LoopTimer::new();
let _worker = ThreadWorker::new(
"d",
diva::DivaSliderJob::new(&state, &"COM5".to_string()),
timer,
);
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -7,5 +7,5 @@ fn main() {
let res = available_ports();
println!("{:?}", res);
let mut input = String::new();
let string = io::stdin().read_line(&mut input).unwrap();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -2,7 +2,7 @@ extern crate slider_io;
use std::io;
// use slidershim::slider_io::{Config, Context};
use slider_io::config::Config;
fn main() {
env_logger::Builder::new()
@ -10,55 +10,64 @@ fn main() {
.init();
// voltex?
// let config = Config::from_str(
// r#"{
// "deviceMode": "yuancon",
// "outputMode": "gamepad-voltex",
// "keyboardSensitivity": 50,
// "ledMode": "reactive-voltex",
// "ledSensitivity": 50
// }"#,
// )
// .unwrap();
let config = Config::from_str(
r#"{
"deviceMode": "yuancon",
"outputMode": "gamepad-voltex",
"outputPolling": "60",
"keyboardSensitivity": 50,
"ledMode": "reactive-voltex",
"ledSensitivity": 50
}"#,
)
.unwrap();
println!("{:?}", config);
// serial?
// let config = Config::from_str(
// r#"{
// "deviceMode": "yuancon",
// "outputMode": "kb-32-tasoller",
// "keyboardSensitivity": 50,
// "ledMode": "serial",
// "ledSerialPort": "COM5"
// }"#,
// )
// .unwrap();
let config = Config::from_str(
r#"{
"deviceMode": "yuancon",
"outputMode": "kb-32-tasoller",
"outputPolling": "60",
"keyboardSensitivity": 50,
"ledMode": "serial",
"ledSerialPort": "COM5"
}"#,
)
.unwrap();
println!("{:?}", config);
// basic
// let config = Config::from_str(
// r#"{
// "deviceMode": "yuancon",
// "outputMode": "kb-32-tasoller",
// "keyboardSensitivity": 50,fdwdfp1
// "ledMode": "reactive-8",
// "ledSensitivity": 50
// }"#,
// )
// .unwrap();
let config = Config::from_str(
r#"{
"deviceMode": "yuancon",
"outputMode": "kb-32-tasoller",
"keyboardSensitivity": 50,
"outputPolling": "60",
"ledMode": "reactive-8",
"ledSensitivity": 50
}"#,
)
.unwrap();
println!("{:?}", config);
// tasoller/
// let config = Config::from_str(
// r#"{
// "deviceMode": "tasoller-two",
// "outputMode": "kb-32-tasoller",
// "keyboardSensitivity": 50,
// "ledMode": "reactive-8",
// "ledSensitivity": 50
// }"#,
// )
// .unwrap();
let config = Config::from_str(
r#"{
"deviceMode": "tasoller-two",
"outputMode": "kb-32-tasoller",
"outputPolling": "60",
"keyboardSensitivity": 50,
"ledMode": "reactive-8",
"ledSensitivity": 50
}"#,
)
.unwrap();
println!("{:?}", config);
// let manager = Context::new(config);
let mut input = String::new();
let string = io::stdin().read_line(&mut input).unwrap();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -1,31 +1,41 @@
extern crate slider_io;
use std::io;
use std::{io, thread::sleep, time::Duration};
// use slidershim::slider_io::worker::{Job, Worker};
use slider_io::shared::{
utils::LoopTimer,
worker::{ThreadJob, ThreadWorker},
};
// struct TestJob {
// data: i64,
// }
struct TestJob {
data: i64,
}
// impl Job for TestJob {
// fn setup(&mut self) {
// self.data = 10;
// println!("setup {}", self.data);
// }
// fn tick(&mut self) {
// self.data -= 1;
// println!("tick {}", self.data);
// }
// fn teardown(&mut self) {
// self.data = 11;
// println!("teardown {}", self.data);
// }
// }
impl ThreadJob for TestJob {
fn setup(&mut self) -> bool {
self.data = 0;
println!("setup {}", self.data);
true
}
fn tick(&mut self) -> bool {
self.data += 1;
println!("tick {}", self.data);
sleep(Duration::from_millis(500));
true
}
}
impl Drop for TestJob {
fn drop(&mut self) {
self.data = -1;
println!("teardown {}", self.data);
}
}
fn main() {
// let worker = Worker::new(TestJob { data: 1 });
let timer = LoopTimer::new();
let _worker = ThreadWorker::new("j", TestJob { data: 1 }, timer);
let mut input = String::new();
let string = io::stdin().read_line(&mut input).unwrap();
io::stdin().read_line(&mut input).unwrap();
}

View File

@ -19,6 +19,7 @@ pub struct Context {
state: SliderState,
config: Config,
device_thread_worker: Option<ThreadWorker>,
device_async_worker: Option<AsyncWorker>,
device_async_haltable_worker: Option<AsyncHaltableWorker>,
output_worker: Option<AsyncWorker>,
lights_worker: Option<AsyncWorker>,
@ -35,12 +36,14 @@ impl Context {
let state = SliderState::new();
let mut timers = vec![];
let (device_worker, brokenithm_worker) = match &config.device_mode {
DeviceMode::None => (None, None),
let (device_thread_worker, device_async_worker, device_async_haltable_worker) =
match &config.device_mode {
DeviceMode::None => (None, None, None),
DeviceMode::Brokenithm {
ground_only,
lights_enabled,
} => (
None,
None,
Some(AsyncHaltableWorker::new(
"brokenithm",
@ -58,6 +61,7 @@ impl Context {
))
},
None,
None,
),
DeviceMode::DivaSlider { port } => (
{
@ -70,6 +74,7 @@ impl Context {
))
},
None,
None,
),
};
let output_worker = match &config.output_mode {
@ -100,8 +105,9 @@ impl Context {
Self {
state,
config,
device_thread_worker: device_worker,
device_async_haltable_worker: brokenithm_worker,
device_thread_worker,
device_async_worker,
device_async_haltable_worker,
output_worker,
lights_worker,
timers,

View File

@ -1,8 +1,17 @@
use log::{error, info};
use serialport::SerialPort;
use std::{collections::VecDeque, num::Wrapping, thread::sleep, time::Duration};
use serialport::{COMPort, SerialPort};
use std::{
collections::VecDeque,
io::{Read, Write},
num::Wrapping,
thread::sleep,
time::Duration,
};
use crate::{shared::worker::ThreadJob, state::SliderState};
use crate::{
shared::{serial::ReadWriteTimeout, worker::ThreadJob},
state::SliderState,
};
struct DivaPacket {
command: u8,
@ -98,15 +107,20 @@ impl DivaDeserializer {
}
fn deserialize(&mut self, data: &[u8], out: &mut VecDeque<DivaPacket>) {
// println!("Found data");
for c in data {
match c {
0xff => {
self.packet = DivaPacket::new();
self.packet.checksum = Wrapping(0xff);
self.state = DivaDeserializerState::ExpectCommand;
self.escape = 0;
// println!("{} open", c);
}
0xfd => {
self.escape = 1;
// println!("esc {}", c);
}
c => {
let c = c + self.escape;
@ -117,6 +131,8 @@ impl DivaDeserializer {
DivaDeserializerState::ExpectCommand => {
self.packet.command = c;
self.state = DivaDeserializerState::ExpectLen;
// println!("cmd {}", c);
}
DivaDeserializerState::ExpectLen => {
self.len = c;
@ -125,6 +141,7 @@ impl DivaDeserializer {
0 => DivaDeserializerState::ExpectChecksum,
_ => DivaDeserializerState::ExpectData,
};
// println!("len {}", c);
}
DivaDeserializerState::ExpectData => {
self.packet.data.push(c);
@ -133,8 +150,11 @@ impl DivaDeserializer {
if self.len == 0 {
self.state = DivaDeserializerState::ExpectChecksum;
}
// println!("data {}", c);
}
DivaDeserializerState::ExpectChecksum => {
// println!("checksum {} {:?}", c, self.packet.checksum);
debug_assert!(self.packet.checksum == Wrapping(0));
if self.packet.checksum == Wrapping(0) {
out.push_back(DivaPacket::new());
@ -163,7 +183,7 @@ pub struct DivaSliderJob {
port: String,
packets: VecDeque<DivaPacket>,
deserializer: DivaDeserializer,
serial_port: Option<Box<dyn SerialPort>>,
serial_port: Option<COMPort>,
bootstrap: DivaSliderBootstrap,
}
@ -187,10 +207,13 @@ impl ThreadJob for DivaSliderJob {
self.port.as_str(),
115200
);
match serialport::new(&self.port, 152000).open() {
Ok(serial_port_buf) => {
match serialport::new(&self.port, 152000).open_native() {
Ok(serial_port) => {
info!("Serial port opened");
self.serial_port = Some(serial_port_buf);
serial_port
.set_read_write_timeout(Duration::from_millis(3))
.ok();
self.serial_port = Some(serial_port);
true
}
Err(e) => {
@ -208,53 +231,81 @@ impl ThreadJob for DivaSliderJob {
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();
serial_port.read(&mut read_buf).ok();
self.deserializer.deserialize(&read_buf, &mut self.packets);
work = true;
}
match self.bootstrap {
DivaSliderBootstrap::Init => {
println!("Diva sending init");
info!("Diva sending init");
let mut reset_packet = DivaPacket::from_bytes(0x10, &[]);
serial_port.write(reset_packet.serialize()).ok();
println!("Diva sent init");
match serial_port.write(reset_packet.serialize()) {
Ok(_) => {
info!("Diva sent init");
self.bootstrap = DivaSliderBootstrap::AwaitReset;
work = true;
}
Err(e) => {
error!("Diva send init error {}", e);
}
}
// Wait for flush
sleep(Duration::from_millis(100));
}
DivaSliderBootstrap::AwaitReset => {
while self.packets.len() > 1 {
self.packets.pop_front();
}
if let Some(ack_packet) = self.packets.pop_front() {
info!(
"Diva slider ack reset {:?} {:?}",
"Diva ack reset {:?} {:?}",
ack_packet.command, ack_packet.data
);
let mut info_packet = DivaPacket::from_bytes(0xf0, &[]);
serial_port.write(info_packet.serialize()).ok();
match serial_port.write(info_packet.serialize()) {
Ok(_) => {
info!("Diva sent info");
self.bootstrap = DivaSliderBootstrap::AwaitInfo;
work = true;
}
Err(e) => {
error!("Diva send info error {}", e);
}
}
}
}
DivaSliderBootstrap::AwaitInfo => {
if let Some(ack_packet) = self.packets.pop_front() {
info!(
"Diva slider ack info {:?} {:?}",
"Diva ack info {:?} {:?}",
ack_packet.command, ack_packet.data
);
let mut start_packet = DivaPacket::from_bytes(0x03, &[]);
serial_port.write(start_packet.serialize()).ok();
match serial_port.write(start_packet.serialize()) {
Ok(_) => {
info!("Diva sent start");
self.bootstrap = DivaSliderBootstrap::AwaitStart;
work = true;
}
Err(e) => {
error!("Diva send start error {}", e);
}
}
}
}
DivaSliderBootstrap::AwaitStart => {
if let Some(ack_packet) = self.packets.pop_front() {
info!(
"Diva slider ack start {:?} {:?}",
"Diva ack start {:?} {:?}",
ack_packet.command, ack_packet.data
);
@ -301,16 +352,15 @@ impl ThreadJob for DivaSliderJob {
impl Drop for DivaSliderJob {
fn drop(&mut self) {
println!("Dropping diva");
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();
}
_ => {}
};
info!("Diva serial port closed");
// println!("Diva slider dropped");
}
}

View File

@ -5,18 +5,18 @@
#![feature(div_duration)]
#![feature(more_qualified_paths)]
mod config;
mod shared;
mod state;
pub mod config;
pub mod shared;
pub mod state;
mod device;
mod lighting;
mod output;
pub mod device;
pub mod lighting;
pub mod output;
mod system;
pub mod system;
mod context;
mod manager;
pub mod context;
pub mod manager;
pub use config::Config;
pub use manager::Manager;

View File

@ -1,3 +1,4 @@
pub mod serial;
pub mod utils;
pub mod voltex;
pub mod worker;

View File

@ -0,0 +1,31 @@
use serialport::COMPort;
use std::{os::windows::prelude::AsRawHandle, time::Duration};
use winapi::{
shared::minwindef::DWORD,
um::{commapi::SetCommTimeouts, winbase::COMMTIMEOUTS},
};
pub trait ReadWriteTimeout {
fn set_read_write_timeout(&self, timeout: Duration) -> Result<(), ()>;
}
impl ReadWriteTimeout for COMPort {
fn set_read_write_timeout(&self, timeout: Duration) -> Result<(), ()> {
let milliseconds = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000;
let mut timeouts = COMMTIMEOUTS {
ReadIntervalTimeout: 0,
ReadTotalTimeoutMultiplier: 0,
ReadTotalTimeoutConstant: milliseconds as DWORD,
WriteTotalTimeoutMultiplier: 0,
WriteTotalTimeoutConstant: milliseconds as DWORD,
};
if unsafe { SetCommTimeouts(self.as_raw_handle(), &mut timeouts) } == 0 {
return Err(());
}
Ok(())
}
}

4
src-tauri/Cargo.lock generated
View File

@ -1628,9 +1628,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.114"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50"
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
[[package]]
name = "libudev"