mirror of
https://github.com/4yn/slidershim.git
synced 2025-02-01 20:18:07 +01:00
wip serial
This commit is contained in:
parent
5865cd9d21
commit
2782d406dd
@ -4,7 +4,10 @@ use std::io;
|
||||
|
||||
use slider_io::{
|
||||
device::diva,
|
||||
shared::{utils::LoopTimer, worker::ThreadWorker},
|
||||
shared::{
|
||||
utils::LoopTimer,
|
||||
worker::{ThreadJob, ThreadWorker},
|
||||
},
|
||||
state::SliderState,
|
||||
};
|
||||
|
||||
@ -14,14 +17,23 @@ fn main() {
|
||||
.init();
|
||||
|
||||
let state = SliderState::new();
|
||||
let mut job = diva::DivaSliderJob::new(&state, &"COM4".to_string(), 0x3f);
|
||||
|
||||
let timer = LoopTimer::new();
|
||||
let _worker = ThreadWorker::new(
|
||||
"d",
|
||||
diva::DivaSliderJob::new(&state, &"COM5".to_string()),
|
||||
timer,
|
||||
);
|
||||
let ok = job.setup();
|
||||
while ok {
|
||||
job.tick();
|
||||
}
|
||||
|
||||
// let state = SliderState::new();
|
||||
|
||||
// let timer = LoopTimer::new();
|
||||
// let _worker = ThreadWorker::new(
|
||||
// "d",
|
||||
// diva::DivaSliderJob::new(&state, &"COM4".to_string(), 0x3f),
|
||||
// timer,
|
||||
// );
|
||||
|
||||
println!("Press enter to quit");
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input).unwrap();
|
||||
}
|
||||
|
47
src-slider_io/src/bin/test_diy_serial.rs
Normal file
47
src-slider_io/src/bin/test_diy_serial.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::{mem, ptr};
|
||||
use winapi::um::{commapi::*, fileapi::*, minwinbase::*, synchapi::*, winbase::*, winnt::*};
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut port: Vec<u16> = vec![];
|
||||
port.extend("COM4".encode_utf16());
|
||||
port.push(0);
|
||||
|
||||
let handle = CreateFileW(
|
||||
port.as_ptr(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
0 as HANDLE,
|
||||
);
|
||||
|
||||
let mut overlapped_read: OVERLAPPED = mem::zeroed();
|
||||
overlapped_read.hEvent = CreateEventW(ptr::null_mut(), 1, 0, ptr::null_mut());
|
||||
let mut overlapped_write: OVERLAPPED = mem::zeroed();
|
||||
overlapped_write.hEvent = CreateEventW(ptr::null_mut(), 0, 0, ptr::null_mut());
|
||||
|
||||
SetupComm(handle, 4096, 4096);
|
||||
|
||||
let mut timeouts: COMMTIMEOUTS = mem::zeroed();
|
||||
GetCommTimeouts(handle, &mut timeouts);
|
||||
|
||||
SetCommMask(handle, 0x80); // EV_ERR
|
||||
|
||||
let mut dcb: DCB = mem::zeroed();
|
||||
GetCommState(handle, &mut dcb);
|
||||
|
||||
dcb.BaudRate = 115200;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.set_fParity(0);
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.set_fBinary(1);
|
||||
|
||||
PurgeComm(
|
||||
handle,
|
||||
PURGE_TXCLEAR | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_RXABORT,
|
||||
);
|
||||
}
|
||||
}
|
102
src-slider_io/src/bin/test_raw_serial.rs
Normal file
102
src-slider_io/src/bin/test_raw_serial.rs
Normal file
@ -0,0 +1,102 @@
|
||||
extern crate slider_io;
|
||||
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
fn main() {
|
||||
let mut sp = serialport::new("COM4", 115200).open().unwrap();
|
||||
sp.write_request_to_send(true).unwrap();
|
||||
sp.write_data_terminal_ready(true).unwrap();
|
||||
|
||||
sleep(Duration::from_millis(100));
|
||||
println!("tx");
|
||||
let res = sp.write(&[0xff, 0x01, 0x00, 0xf1]).unwrap();
|
||||
println!("tx {}", res);
|
||||
|
||||
loop {
|
||||
sleep(Duration::from_millis(100));
|
||||
println!("rx");
|
||||
let mut buf = [0u8; 4];
|
||||
let res = sp.read(&mut buf).unwrap();
|
||||
println!("rx {} {:?}", res, buf);
|
||||
}
|
||||
}
|
||||
|
||||
// use serial2::SerialPort;
|
||||
|
||||
// fn main() {
|
||||
// let sp = SerialPort::open("COM4", 115200).unwrap();
|
||||
// println!("Tx");
|
||||
// let res = sp.write("data".as_bytes()).unwrap();
|
||||
// println!("Tx {}", res);
|
||||
// loop {
|
||||
// println!("Rx");
|
||||
// let mut buf = [0u8; 5];
|
||||
// let res = sp.read(&mut buf).unwrap();
|
||||
// // let res = sp.read(&mut buf).unwrap_or_else(|e| {
|
||||
// // println!("Err {}", e);
|
||||
// // 0
|
||||
// // });
|
||||
// println!("Rx {} {:?}", res, buf);
|
||||
// }
|
||||
|
||||
// let mut sp = serialport::new("COM4", 115200).open().unwrap();
|
||||
// println!("Tx");
|
||||
// let res = sp.write("data".as_bytes()).unwrap();
|
||||
// println!("Tx {}", res);
|
||||
// loop {
|
||||
// println!("Rx");
|
||||
// let mut buf = [0u8; 5];
|
||||
// let res = sp.read(&mut buf).unwrap();
|
||||
// println!("Rx {} {:?}", res, buf);
|
||||
// }
|
||||
// }
|
||||
|
||||
// use serialport::SerialPort;
|
||||
// use std::time::Duration;
|
||||
// use tokio::{
|
||||
// io::{self, AsyncReadExt, AsyncWriteExt},
|
||||
// time::sleep,
|
||||
// };
|
||||
// use tokio_serial::SerialPortBuilderExt;
|
||||
|
||||
// #[tokio::main]
|
||||
// async fn main() -> io::Result<()> {
|
||||
// let mut sp = tokio_serial::new("COM4", 115200)
|
||||
// .open_native_async()
|
||||
// .unwrap();
|
||||
|
||||
// sp.write_request_to_send(true).unwrap();
|
||||
// sp.write_data_terminal_ready(true).unwrap();
|
||||
// // sp.set_timeout(Duration::from_millis(1000))?;
|
||||
// let (mut rx_port, mut tx_port) = tokio::io::split(sp);
|
||||
|
||||
// // tx_port.write(&[41, 42, 43, 44]).await?;
|
||||
// // let mut buf = [0u8; 10];
|
||||
// // let res = rx_port.read(&mut buf).await?;
|
||||
// // println!("{}, {:?}", res, buf);
|
||||
|
||||
// loop {
|
||||
// let mut buf = [0u8; 10];
|
||||
// let res = rx_port.read(&mut buf).await?;
|
||||
// println!("{}, {:?}", res, buf);
|
||||
// }
|
||||
|
||||
// // let mut serial_reader =
|
||||
// // tokio_util::codec::FramedRead::new(rx_port,
|
||||
// // tokio_util::codec::BytesCodec::new()); let serial_sink =
|
||||
// // tokio_util::codec::FramedWrite::new(tx_port,
|
||||
// // tokio_util::codec::BytesCodec::new());
|
||||
|
||||
// // println!("Tx");
|
||||
// // let res = tx.write("data".as_bytes()).await?;
|
||||
// // println!("Sent {}", res);
|
||||
// // sleep(Duration::from_millis(1000)).await;
|
||||
// // loop {
|
||||
// // let mut buffer = [0u8; 1];
|
||||
// // println!("Rx");
|
||||
// // let res = rx.read(&mut buffer).await;
|
||||
// // println!("{:?} {:?}", res, buffer);
|
||||
// // }
|
||||
|
||||
// Ok(())
|
||||
// }
|
@ -63,13 +63,13 @@ impl Context {
|
||||
None,
|
||||
None,
|
||||
),
|
||||
DeviceMode::DivaSlider { port } => (
|
||||
DeviceMode::DivaSlider { port, brightness } => (
|
||||
{
|
||||
let timer = LoopTimer::new();
|
||||
timers.push(("d", timer.fork()));
|
||||
Some(ThreadWorker::new(
|
||||
"diva",
|
||||
DivaSliderJob::new(&state, port),
|
||||
DivaSliderJob::new(&state, port, *brightness),
|
||||
timer,
|
||||
))
|
||||
},
|
||||
|
@ -19,6 +19,7 @@ pub enum DeviceMode {
|
||||
},
|
||||
DivaSlider {
|
||||
port: String,
|
||||
brightness: u8,
|
||||
},
|
||||
}
|
||||
|
||||
@ -37,6 +38,7 @@ impl DeviceMode {
|
||||
},
|
||||
"diva" => DeviceMode::DivaSlider {
|
||||
port: v["divaSerialPort"].as_str()?.to_string(),
|
||||
brightness: u8::try_from(v["divaBrightness"].as_i64()?).ok()?,
|
||||
},
|
||||
"brokenithm" => DeviceMode::Brokenithm {
|
||||
ground_only: false,
|
||||
|
@ -1,9 +1,8 @@
|
||||
use log::{error, info};
|
||||
use log::{debug, error, info, warn};
|
||||
use serialport::{COMPort, SerialPort};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
io::{Read, Write},
|
||||
num::Wrapping,
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
@ -13,11 +12,23 @@ use crate::{
|
||||
state::SliderState,
|
||||
};
|
||||
|
||||
/*
|
||||
Init packet
|
||||
0xff 0x10 0x00 0xf1
|
||||
|
||||
Report of all touch sliders at 16 pressure
|
||||
0xff 0x01 0x20 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0x10 0xe0
|
||||
|
||||
Report of all touch sliders at 0-31 pressure
|
||||
0xff 0x01 0x20 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x0f
|
||||
*/
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DivaPacket {
|
||||
command: u8,
|
||||
len: u8,
|
||||
data: Vec<u8>,
|
||||
checksum: Wrapping<u8>,
|
||||
checksum: u8,
|
||||
raw: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
@ -27,17 +38,23 @@ impl DivaPacket {
|
||||
command: 0,
|
||||
len: 0,
|
||||
data: Vec::with_capacity(256),
|
||||
checksum: Wrapping(0),
|
||||
checksum: 0,
|
||||
raw: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_bytes(command: u8, data: &[u8]) -> Self {
|
||||
let checksum = 0xffu64
|
||||
+ (command as u64)
|
||||
+ (data.len() as u64)
|
||||
+ data.iter().map(|x| (*x) as u64).sum::<u64>();
|
||||
let checksum = ((0x100 - (checksum & 0xff)) & 0xff) as u8;
|
||||
|
||||
Self {
|
||||
command,
|
||||
len: data.len() as u8,
|
||||
data: data.iter().copied().collect(),
|
||||
checksum: Wrapping(0),
|
||||
checksum: checksum,
|
||||
raw: None,
|
||||
}
|
||||
}
|
||||
@ -60,23 +77,21 @@ impl DivaPacket {
|
||||
|
||||
fn serialize(&mut self) -> &[u8] {
|
||||
let mut raw: Vec<u8> = Vec::with_capacity(512);
|
||||
let mut checksum = Wrapping(0);
|
||||
|
||||
raw.push(0xff);
|
||||
checksum += Wrapping(0xffu8);
|
||||
Self::push_raw_escaped(self.command, &mut raw);
|
||||
checksum += Wrapping(self.command);
|
||||
Self::push_raw_escaped(self.len, &mut raw);
|
||||
checksum += Wrapping(self.len);
|
||||
for i in &self.data {
|
||||
Self::push_raw_escaped(*i, &mut raw);
|
||||
checksum += Wrapping(*i);
|
||||
}
|
||||
Self::push_raw_escaped(self.checksum, &mut raw);
|
||||
|
||||
checksum = -checksum;
|
||||
Self::push_raw_escaped(checksum.0, &mut raw);
|
||||
// null pad?
|
||||
// raw.push(0);
|
||||
|
||||
debug!("Diva serializing {}", raw.len());
|
||||
self.raw = Some(raw);
|
||||
// debug!("Diva serializing {:?}", &self.raw);
|
||||
return self.raw.as_ref().unwrap();
|
||||
}
|
||||
}
|
||||
@ -91,6 +106,7 @@ enum DivaDeserializerState {
|
||||
|
||||
struct DivaDeserializer {
|
||||
state: DivaDeserializerState,
|
||||
checksum: u64,
|
||||
escape: u8,
|
||||
len: u8,
|
||||
packet: DivaPacket,
|
||||
@ -100,7 +116,8 @@ impl DivaDeserializer {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
state: DivaDeserializerState::Done,
|
||||
escape: 1,
|
||||
checksum: 0,
|
||||
escape: 0,
|
||||
len: 0,
|
||||
packet: DivaPacket::new(),
|
||||
}
|
||||
@ -108,11 +125,13 @@ impl DivaDeserializer {
|
||||
|
||||
fn deserialize(&mut self, data: &[u8], out: &mut VecDeque<DivaPacket>) {
|
||||
// println!("Found data");
|
||||
// debug!("Diva deserializing {:?}", data);
|
||||
debug!("Diva deserializing {}", data.len());
|
||||
for c in data {
|
||||
match c {
|
||||
0xff => {
|
||||
self.packet = DivaPacket::new();
|
||||
self.packet.checksum = Wrapping(0xff);
|
||||
self.checksum = 0xff;
|
||||
self.state = DivaDeserializerState::ExpectCommand;
|
||||
self.escape = 0;
|
||||
|
||||
@ -126,7 +145,7 @@ impl DivaDeserializer {
|
||||
let c = c + self.escape;
|
||||
self.escape = 0;
|
||||
|
||||
self.packet.checksum += Wrapping(c);
|
||||
self.checksum += c as u64;
|
||||
match self.state {
|
||||
DivaDeserializerState::ExpectCommand => {
|
||||
self.packet.command = c;
|
||||
@ -154,9 +173,11 @@ impl DivaDeserializer {
|
||||
// println!("data {}", c);
|
||||
}
|
||||
DivaDeserializerState::ExpectChecksum => {
|
||||
// println!("checksum {} {:?}", c, self.packet.checksum);
|
||||
debug_assert!(self.packet.checksum == Wrapping(0));
|
||||
if self.packet.checksum == Wrapping(0) {
|
||||
self.packet.checksum = c;
|
||||
debug_assert!(self.checksum & 0xff == 0);
|
||||
// println!("Packet complete {} {}", self.checksum, c);
|
||||
if self.checksum & 0xff == 0 {
|
||||
// println!("Feeding packet");
|
||||
out.push_back(DivaPacket::new());
|
||||
std::mem::swap(&mut self.packet, out.back_mut().unwrap());
|
||||
}
|
||||
@ -174,25 +195,31 @@ enum DivaSliderBootstrap {
|
||||
Init,
|
||||
AwaitReset,
|
||||
AwaitInfo,
|
||||
AwaitStart,
|
||||
ReadLoop,
|
||||
Halt,
|
||||
}
|
||||
|
||||
pub struct DivaSliderJob {
|
||||
state: SliderState,
|
||||
port: String,
|
||||
packets: VecDeque<DivaPacket>,
|
||||
brightness: u8,
|
||||
// read_buf: Vec<u8>,
|
||||
in_packets: VecDeque<DivaPacket>,
|
||||
out_packets: VecDeque<DivaPacket>,
|
||||
deserializer: DivaDeserializer,
|
||||
serial_port: Option<COMPort>,
|
||||
bootstrap: DivaSliderBootstrap,
|
||||
}
|
||||
|
||||
impl DivaSliderJob {
|
||||
pub fn new(state: &SliderState, port: &String) -> Self {
|
||||
pub fn new(state: &SliderState, port: &String, brightness: u8) -> Self {
|
||||
Self {
|
||||
state: state.clone(),
|
||||
port: port.clone(),
|
||||
packets: VecDeque::with_capacity(100),
|
||||
brightness,
|
||||
// read_buf: vec![0u8; 1024],
|
||||
in_packets: VecDeque::with_capacity(100),
|
||||
out_packets: VecDeque::with_capacity(100),
|
||||
deserializer: DivaDeserializer::new(),
|
||||
serial_port: None,
|
||||
bootstrap: DivaSliderBootstrap::Init,
|
||||
@ -207,11 +234,24 @@ impl ThreadJob for DivaSliderJob {
|
||||
self.port.as_str(),
|
||||
115200
|
||||
);
|
||||
match serialport::new(&self.port, 152000).open_native() {
|
||||
match serialport::new(&self.port, 152000)
|
||||
.flow_control(serialport::FlowControl::Hardware)
|
||||
.open_native()
|
||||
{
|
||||
Ok(serial_port) => {
|
||||
info!("Serial port opened");
|
||||
// serial_port.write_request_to_send(true).unwrap_or_else(|e| {
|
||||
// error!("Serial request to send failed {}", e);
|
||||
// });
|
||||
// serial_port
|
||||
// .write_data_terminal_ready(true)
|
||||
// .unwrap_or_else(|e| {
|
||||
// error!("Serial data terminal ready failed {}", e);
|
||||
// });
|
||||
// serial_port.set_timeout(Duration::from_millis(10)).ok();
|
||||
serial_port.clear(serialport::ClearBuffer::All).ok();
|
||||
serial_port
|
||||
.set_read_write_timeout(Duration::from_millis(3))
|
||||
.set_read_write_timeout(Duration::from_millis(100))
|
||||
.ok();
|
||||
self.serial_port = Some(serial_port);
|
||||
true
|
||||
@ -228,93 +268,74 @@ impl ThreadJob for DivaSliderJob {
|
||||
|
||||
let serial_port = self.serial_port.as_mut().unwrap();
|
||||
|
||||
let bytes_avail = serial_port.bytes_to_read().unwrap_or(0);
|
||||
let bytes_avail = serial_port.bytes_to_read().unwrap_or_else(|e| {
|
||||
error!("Diva serial read error {}", e);
|
||||
0
|
||||
});
|
||||
// debug!("Serial read {} bytes", bytes_avail);
|
||||
if bytes_avail > 0 {
|
||||
let mut read_buf = vec![0 as u8; bytes_avail as usize];
|
||||
serial_port.read(&mut read_buf).ok();
|
||||
self.deserializer.deserialize(&read_buf, &mut self.packets);
|
||||
serial_port.read_exact(&mut read_buf).unwrap();
|
||||
self
|
||||
.deserializer
|
||||
.deserialize(&read_buf, &mut self.in_packets);
|
||||
work = true;
|
||||
}
|
||||
|
||||
// let read_amount = serial_port.read(&mut self.read_buf).unwrap_or_else(|e| {
|
||||
// error!("Read error {}", e);
|
||||
// 0
|
||||
// });
|
||||
// debug!("Serial read {} bytes", read_amount);
|
||||
// if read_amount > 0 {
|
||||
// self
|
||||
// .deserializer
|
||||
// .deserialize(&self.read_buf[0..read_amount], &mut self.packets);
|
||||
// }
|
||||
|
||||
match self.bootstrap {
|
||||
DivaSliderBootstrap::Init => {
|
||||
info!("Diva sending init");
|
||||
let mut reset_packet = DivaPacket::from_bytes(0x10, &[]);
|
||||
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));
|
||||
let reset_packet = DivaPacket::from_bytes(0x10, &[]);
|
||||
self.out_packets.push_back(reset_packet);
|
||||
self.bootstrap = DivaSliderBootstrap::AwaitReset;
|
||||
}
|
||||
DivaSliderBootstrap::AwaitReset => {
|
||||
while self.packets.len() > 1 {
|
||||
self.packets.pop_front();
|
||||
}
|
||||
if let Some(ack_packet) = self.packets.pop_front() {
|
||||
info!(
|
||||
"Diva ack reset {:?} {:?}",
|
||||
ack_packet.command, ack_packet.data
|
||||
);
|
||||
while let Some(ack_packet) = self.in_packets.pop_front() {
|
||||
if ack_packet.command == 0x10 && ack_packet.len == 0x00 && ack_packet.checksum == 0xf1 {
|
||||
info!(
|
||||
"Diva ack reset {:#4x} {:?}",
|
||||
ack_packet.command, ack_packet.data
|
||||
);
|
||||
|
||||
let mut info_packet = DivaPacket::from_bytes(0xf0, &[]);
|
||||
|
||||
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);
|
||||
}
|
||||
info!("Diva sending info");
|
||||
let info_packet = DivaPacket::from_bytes(0xf0, &[]);
|
||||
self.out_packets.push_back(info_packet);
|
||||
self.bootstrap = DivaSliderBootstrap::AwaitInfo;
|
||||
break;
|
||||
} else {
|
||||
warn!(
|
||||
"Unexpected packet {:#4x} {:?}",
|
||||
ack_packet.command, ack_packet.data
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
DivaSliderBootstrap::AwaitInfo => {
|
||||
if let Some(ack_packet) = self.packets.pop_front() {
|
||||
if let Some(ack_packet) = self.in_packets.pop_front() {
|
||||
info!(
|
||||
"Diva ack info {:?} {:?}",
|
||||
ack_packet.command, ack_packet.data
|
||||
);
|
||||
|
||||
let mut start_packet = DivaPacket::from_bytes(0x03, &[]);
|
||||
|
||||
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 ack start {:?} {:?}",
|
||||
"Diva ack info {:#4x} {:?}",
|
||||
ack_packet.command, ack_packet.data
|
||||
);
|
||||
|
||||
info!("Diva sending start");
|
||||
let start_packet = DivaPacket::from_bytes(0x03, &[]);
|
||||
self.out_packets.push_back(start_packet);
|
||||
self.bootstrap = DivaSliderBootstrap::ReadLoop;
|
||||
work = true;
|
||||
}
|
||||
}
|
||||
DivaSliderBootstrap::ReadLoop => {
|
||||
while let Some(data_packet) = self.packets.pop_front() {
|
||||
while let Some(data_packet) = self.in_packets.pop_front() {
|
||||
if data_packet.command == 0x01 && data_packet.len == 32 {
|
||||
let mut input_handle = self.state.input.lock();
|
||||
input_handle
|
||||
@ -325,24 +346,62 @@ impl ThreadJob for DivaSliderJob {
|
||||
}
|
||||
|
||||
let mut send_lights = false;
|
||||
let mut lights_buf = [0; 97];
|
||||
let mut lights_buf = [0; 94];
|
||||
{
|
||||
let mut lights_handle = self.state.lights.lock();
|
||||
if lights_handle.dirty {
|
||||
send_lights = true;
|
||||
lights_buf[0] = 0x3f;
|
||||
lights_buf[1..97].copy_from_slice(&lights_handle.ground[0..96]);
|
||||
lights_buf[0] = self.brightness;
|
||||
lights_buf[1..94].copy_from_slice(&lights_handle.ground[0..93]);
|
||||
lights_handle.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
if send_lights {
|
||||
let mut lights_packet = DivaPacket::from_bytes(0x02, &lights_buf);
|
||||
serial_port.write(lights_packet.serialize()).ok();
|
||||
let lights_packet = DivaPacket::from_bytes(0x02, &lights_buf);
|
||||
self.out_packets.push_back(lights_packet);
|
||||
}
|
||||
}
|
||||
DivaSliderBootstrap::Halt => {}
|
||||
};
|
||||
|
||||
let mut sent = false;
|
||||
while let Some(mut packet) = self.out_packets.pop_front() {
|
||||
println!("Sending packet {:?}", packet);
|
||||
sent = true;
|
||||
serial_port
|
||||
.write(packet.serialize())
|
||||
.map_err(|e| {
|
||||
error!("Send packet err {}", e);
|
||||
e
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
if sent {
|
||||
println!("Flushing");
|
||||
serial_port
|
||||
.flush()
|
||||
.map_err(|e| {
|
||||
error!("Flush err {}", e);
|
||||
e
|
||||
})
|
||||
.ok();
|
||||
serial_port
|
||||
.write(&[0])
|
||||
.map_err(|e| {
|
||||
error!("Send null packet err {}", e);
|
||||
e
|
||||
})
|
||||
.ok();
|
||||
serial_port
|
||||
.flush()
|
||||
.map_err(|e| {
|
||||
error!("Flush null packet err {}", e);
|
||||
e
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
// TODO: async worker?
|
||||
sleep(Duration::from_millis(10));
|
||||
|
||||
@ -353,7 +412,7 @@ impl ThreadJob for DivaSliderJob {
|
||||
impl Drop for DivaSliderJob {
|
||||
fn drop(&mut self) {
|
||||
match self.bootstrap {
|
||||
DivaSliderBootstrap::AwaitStart | DivaSliderBootstrap::ReadLoop => {
|
||||
DivaSliderBootstrap::ReadLoop => {
|
||||
let serial_port = self.serial_port.as_mut().unwrap();
|
||||
let mut stop_packet = DivaPacket::from_bytes(0x04, &[]);
|
||||
serial_port.write(stop_packet.serialize()).ok();
|
||||
@ -361,6 +420,5 @@ impl Drop for DivaSliderJob {
|
||||
_ => {}
|
||||
};
|
||||
info!("Diva serial port closed");
|
||||
// println!("Diva slider dropped");
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ impl LoopTimer {
|
||||
Self {
|
||||
cap: 100,
|
||||
cur: 0,
|
||||
buf: vec![Instant::now() - Duration::from_secs(10); 100],
|
||||
buf: vec![Instant::now() - Duration::from_secs(10_000); 100],
|
||||
freq: Arc::new(AtomicF64::new(0.0)),
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ fn main() {
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
let log_file_path = slider_io::Config::get_log_file_path().unwrap();
|
||||
let log_file_path = slider_io::system::get_log_file_path().unwrap();
|
||||
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "slidershim",
|
||||
"version": "0.1.4"
|
||||
"version": "0.2.0"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
|
@ -11,6 +11,7 @@
|
||||
let ledMode = "none";
|
||||
|
||||
let divaSerialPort = "COM1";
|
||||
let divaBrightness = 63;
|
||||
let keyboardSensitivity = 20;
|
||||
let outputPolling = "100";
|
||||
let outputWebsocketUrl = "http://localhost:3000";
|
||||
@ -58,6 +59,7 @@
|
||||
ledMode = payload.ledMode || "none";
|
||||
|
||||
divaSerialPort = payload.divaSerialPort || "COM1";
|
||||
divaBrightness = payload.divaBrightness || 63;
|
||||
keyboardSensitivity = payload.keyboardSensitivity || 20;
|
||||
outputPolling = payload.outputPolling || "100";
|
||||
outputWebsocketUrl =
|
||||
@ -106,6 +108,7 @@
|
||||
outputMode,
|
||||
ledMode,
|
||||
divaSerialPort,
|
||||
divaBrightness,
|
||||
keyboardSensitivity,
|
||||
outputPolling,
|
||||
outputWebsocketUrl,
|
||||
@ -137,7 +140,7 @@
|
||||
|
||||
<div class="titlebar">
|
||||
<div class="header-icon">
|
||||
<img src="/icon.png" />
|
||||
<img src="/icon.png" alt="logo" />
|
||||
</div>
|
||||
<div class="header">
|
||||
slidershim{versionString}
|
||||
@ -200,6 +203,32 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">Brightness</div>
|
||||
<div class="input">
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
max="255"
|
||||
step="1"
|
||||
bind:value={divaBrightness}
|
||||
on:change={markDirty}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label" />
|
||||
<div class="input">
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="255"
|
||||
step="1"
|
||||
bind:value={divaBrightness}
|
||||
on:change={markDirty}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="row">
|
||||
|
Loading…
x
Reference in New Issue
Block a user