i have severe brain damage
This commit is contained in:
parent
05c6801628
commit
4f83151b96
11 changed files with 637 additions and 427 deletions
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,14 +1 @@
|
||||||
# Generated by Cargo
|
/target
|
||||||
# will have compiled files and executables
|
|
||||||
debug/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
|
||||||
**/*.rs.bk
|
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
|
||||||
*.pdb
|
|
||||||
|
|
251
Cargo.lock
generated
Normal file
251
Cargo.lock
generated
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-kit-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"mach2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.153"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libudev"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"libudev-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libudev-sys"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach2"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.81"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serialport"
|
||||||
|
version = "4.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"io-kit-sys",
|
||||||
|
"libudev",
|
||||||
|
"mach2",
|
||||||
|
"nix",
|
||||||
|
"regex",
|
||||||
|
"scopeguard",
|
||||||
|
"unescaper",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unescaper"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wabri"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serialport",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -4,4 +4,4 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serial2 = "0.2.20"
|
serialport = "4.3.0"
|
||||||
|
|
|
@ -10,11 +10,12 @@ For the address the following values are used:
|
||||||
- Sync Board -> Unit Boards: 0xE0 + Unit Board ID
|
- Sync Board -> Unit Boards: 0xE0 + Unit Board ID
|
||||||
#### Command ID
|
#### Command ID
|
||||||
The following Command ID's are known:
|
The following Command ID's are known:
|
||||||
- 0xA8: Get the Unit Board Version
|
- 0xA8: Get Unit Board Version
|
||||||
- 0xA0:
|
- 0xA0: Get Unit Board Version 2?
|
||||||
- 0x94:
|
- 0x94: Set Thresholds
|
||||||
- 0x90: "Initialize" Touch
|
- 0x90: "Initialize" unit board
|
||||||
- 0xA1: Poll board for touch data
|
- 0xA1: Poll touch state
|
||||||
|
- 0xA3: Poll touch state (Analogue) (Not tested yed)
|
||||||
#### Variable Data
|
#### Variable Data
|
||||||
This contains data, it has a variable length.
|
This contains data, it has a variable length.
|
||||||
#### Checksum
|
#### Checksum
|
||||||
|
@ -74,7 +75,14 @@ The sync board sends:
|
||||||
The unit boards respond with:
|
The unit boards respond with:
|
||||||
|
|
||||||
`0xD1 0xA1 0x80 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x75 0xF0`
|
`0xD1 0xA1 0x80 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x75 0xF0`
|
||||||
|
#### 0xA3 - Poll touch state (Analogue)
|
||||||
|
This command retrieves the touch state from the unit boards.
|
||||||
|
The sync board sends:
|
||||||
|
|
||||||
|
`0xE1 0xA3 0x42 0xF0`
|
||||||
|
|
||||||
|
The unit boards respond with:
|
||||||
|
|
||||||
|
`0xD1 0xA3 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x72 0xF0`
|
||||||
|
|
||||||
|
|
||||||
|
|
126
src/bridge.rs
Normal file
126
src/bridge.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
use std::{env, io::{self, BufReader, Read}, str, sync::{ mpsc::{self, Receiver, Sender}, Arc}, thread, time::{Duration, Instant}};
|
||||||
|
use serialport;
|
||||||
|
use crate::{game::{self, fix_touch}, utils::{self, calc_checksum}, unit};
|
||||||
|
|
||||||
|
pub fn start(side: bool, wedge_port: &str, game_port: &str) {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let mut left = unit::WedgePort {hardware_port: serialport::new(wedge_port, 921600).timeout(Duration::from_micros(1000)).open().expect("Unable to open serialport")};
|
||||||
|
let mut game = serialport::new(game_port, 115200).timeout(Duration::from_millis(1)).open().expect("Unable to open serialport");
|
||||||
|
// for i in 1..100 {
|
||||||
|
// let mut x: Vec<(u8, String)> = left.get_version();
|
||||||
|
// //println!("{:?}",x);
|
||||||
|
// }
|
||||||
|
left.set_thresholds(0x11, 0x0C);
|
||||||
|
left.init();
|
||||||
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
|
||||||
|
let (gametx, gamerx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel();
|
||||||
|
|
||||||
|
let mut c = game.try_clone().unwrap();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut serialbuffer: Vec<u8> = vec![0; 1000];
|
||||||
|
loop {
|
||||||
|
match c.read(serialbuffer.as_mut_slice()) {
|
||||||
|
Ok(t) => { println!("{:?}", serialbuffer[..t].to_vec()); let _ = &gametx.send(serialbuffer[..t].to_vec()); },
|
||||||
|
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
|
||||||
|
Err(e) => eprintln!("{:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut active: bool = false;
|
||||||
|
let mut touchbuffer: Vec<u8> = vec![0; 36];
|
||||||
|
let params = game::SyncBoardParams::get();
|
||||||
|
loop {
|
||||||
|
let x = Instant::now();
|
||||||
|
|
||||||
|
//game logic
|
||||||
|
match gamerx.try_recv() {
|
||||||
|
Ok(m) => {
|
||||||
|
println!(" a{:?}",m);
|
||||||
|
let res: Option<Vec<u8>> = match m[0] {
|
||||||
|
0xa0 => {
|
||||||
|
active = false;
|
||||||
|
Some([vec![m[0]], "190523".as_bytes().to_vec(), vec![44]].concat().to_vec())
|
||||||
|
},
|
||||||
|
0x77 => {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
0x20 => {
|
||||||
|
active = false;
|
||||||
|
None
|
||||||
|
},
|
||||||
|
0xa2 => {
|
||||||
|
active = false;
|
||||||
|
//Some(vec![ 162, 63, 29, 0, 0, 0, 0 ])
|
||||||
|
Some(vec![ 162, 63, 29 ])
|
||||||
|
},
|
||||||
|
0x94 => {
|
||||||
|
active = false;
|
||||||
|
//Some(vec![ 148, 0, 20, 0, 0, 0, 0 ])
|
||||||
|
Some(vec![ 148, 0, 20 ])
|
||||||
|
},
|
||||||
|
0xc9 => {
|
||||||
|
active = true;
|
||||||
|
//Some(vec![ 201, 0, 73, 0, 0, 0, 0 ])
|
||||||
|
Some(vec![ 201, 0, 73 ])
|
||||||
|
},
|
||||||
|
0xa8 => {
|
||||||
|
let mut versions = vec!["190523", "190523", "190523", "190523", "190523", "190523"];
|
||||||
|
Some(game::UnitBoardVersionPacket {
|
||||||
|
sync_board_version: "190523",
|
||||||
|
unit_board_version: versions,
|
||||||
|
side: side,
|
||||||
|
}.serialize())
|
||||||
|
},
|
||||||
|
0x72 => {
|
||||||
|
active = false;
|
||||||
|
let param: &str = match m[3] {
|
||||||
|
0x30 => {params.param0000}
|
||||||
|
0x31 => {params.param0016}
|
||||||
|
0x33 => {params.param0032}
|
||||||
|
_ => {""}
|
||||||
|
};
|
||||||
|
Some([param.as_bytes(), &vec![utils::calc_checksum(¶m.as_bytes().to_vec())]].concat())
|
||||||
|
},
|
||||||
|
0x9a => {
|
||||||
|
active = false;
|
||||||
|
None
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
match res {
|
||||||
|
Some(x) => { let _ = game.write(&x); },
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => ()
|
||||||
|
|
||||||
|
}
|
||||||
|
if active {
|
||||||
|
let e = left.get_touch();
|
||||||
|
utils::copy_into(&mut touchbuffer, 1, &[0; 24]);
|
||||||
|
for l in e {
|
||||||
|
let r = 7-l.0;
|
||||||
|
touchbuffer[r as usize] = touchbuffer[r as usize] | fix_touch(l.1[0], side);
|
||||||
|
touchbuffer[(r+6) as usize] = touchbuffer[(r+6) as usize] | fix_touch(l.1[1], side);
|
||||||
|
touchbuffer[(r+12) as usize] = touchbuffer[(r+12) as usize] | fix_touch(l.1[2], side);
|
||||||
|
touchbuffer[(r+18) as usize] = touchbuffer[(r+18) as usize] | fix_touch(l.1[3], side);
|
||||||
|
}
|
||||||
|
touchbuffer[0] = 129;
|
||||||
|
touchbuffer[34] = touchbuffer[34]+1;
|
||||||
|
touchbuffer[35] = 128;
|
||||||
|
touchbuffer[35] = calc_checksum(&touchbuffer);
|
||||||
|
if touchbuffer[34] == 127 {touchbuffer[34] = 0};
|
||||||
|
println!("write");
|
||||||
|
let _ = game.write(&touchbuffer);
|
||||||
|
} else {
|
||||||
|
thread::sleep(Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
//reader.read(serial_buf.as_mut_slice());
|
||||||
|
println!("{:?}",x.elapsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
src/game.rs
Normal file
46
src/game.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use crate::utils::calc_checksum;
|
||||||
|
|
||||||
|
pub struct SyncBoardParams<'a> {
|
||||||
|
pub param0000: &'a str,
|
||||||
|
pub param0016: &'a str,
|
||||||
|
pub param0032: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyncBoardParams<'static> {
|
||||||
|
pub fn get() -> SyncBoardParams<'static> {
|
||||||
|
SyncBoardParams {
|
||||||
|
param0000: " 0 0 1 2 3 4 5 15 15 15 15 15 15 11 11 11",
|
||||||
|
param0016: " 11 11 11 128 103 103 115 138 127 103 105 111 126 113 95 100",
|
||||||
|
param0032: " 101 115 98 86 76 67 68 48 117 0 82 154 0 6 35 4",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UnitBoardVersionPacket<'a> {
|
||||||
|
pub sync_board_version: &'a str,
|
||||||
|
pub unit_board_version: Vec<&'a str>,
|
||||||
|
pub side: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnitBoardVersionPacket<'_> {
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut s: Vec<u8> = vec![0xA8];
|
||||||
|
s.append(&mut self.sync_board_version.as_bytes().to_vec());
|
||||||
|
if self.side {s.push(0x4C)} else {s.push(0x52)};
|
||||||
|
for v in &self.unit_board_version {
|
||||||
|
s.append(&mut v.as_bytes().to_vec());
|
||||||
|
}
|
||||||
|
s.push(calc_checksum(&[s.as_slice(),vec![0x80].as_slice()].concat()));
|
||||||
|
//if self.side {s.push(104)} else {s.push(118)};
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fix_touch(byte: u8, side: bool) -> u8 {
|
||||||
|
let side = side.clone();
|
||||||
|
if side {
|
||||||
|
byte.reverse_bits() >> 3
|
||||||
|
} else {
|
||||||
|
byte & 0x7f
|
||||||
|
}
|
||||||
|
}
|
6
src/lib.rs
Normal file
6
src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#![feature(exclusive_range_pattern)]
|
||||||
|
|
||||||
|
mod unit;
|
||||||
|
mod utils;
|
||||||
|
mod game;
|
||||||
|
mod bridge;
|
199
src/main.rs
199
src/main.rs
|
@ -1,196 +1,19 @@
|
||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
use std::{io, sync::{atomic::{AtomicBool, Ordering}, mpsc::{self, Receiver, Sender}, Arc, Mutex}, thread, time::{Duration, Instant}};
|
|
||||||
|
|
||||||
use serial2::SerialPort;
|
use std::env;
|
||||||
use wacca::{calc_checksum, SyncBoardParams, TouchBinding, CommandPacket};
|
mod unit;
|
||||||
|
mod utils;
|
||||||
use crate::wacca::fix_touch;
|
mod game;
|
||||||
|
mod bridge;
|
||||||
mod wacca;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let game_left = Arc::new(SerialPort::open("/dev/tnt0", 115200).expect("Unable to open serialport"));
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() > 1 {
|
||||||
let game_right = Arc::new(SerialPort::open("/dev/tnt2", 115200).expect("Unable to open serialport"));
|
match args[1].as_ref() {
|
||||||
|
"selftest" => { println!("Selftest"); },
|
||||||
let wedge_left = Arc::new(Mutex::new(SerialPort::open("/dev/ttyUSB0", 921600).expect("Unable to open serialport")));
|
"bridge" | _ => { bridge::start(false, "COM20", "COM5"); }
|
||||||
|
|
||||||
let wedge_right = Arc::new(Mutex::new(SerialPort::open("/dev/ttyUSB1", 921600).expect("Unable to open serialport")));
|
|
||||||
|
|
||||||
let bindings = vec![
|
|
||||||
TouchBinding {
|
|
||||||
game_serial: game_left,
|
|
||||||
wedge_serial: wedge_left,
|
|
||||||
side: false,
|
|
||||||
},
|
|
||||||
TouchBinding {
|
|
||||||
game_serial: game_right,
|
|
||||||
wedge_serial: wedge_right,
|
|
||||||
side: true,
|
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
|
||||||
for binding in bindings.into_iter() {
|
|
||||||
println!("loading thread");
|
|
||||||
|
|
||||||
//let we need some params
|
|
||||||
let params = Arc::new(SyncBoardParams::get(&binding.side));
|
|
||||||
|
|
||||||
//Sync board -> Game writer thread logic
|
|
||||||
let (writer_tx, writer_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel();
|
|
||||||
let command_tx = writer_tx.clone();
|
|
||||||
|
|
||||||
let game_serial_1 = binding.game_serial.clone();
|
|
||||||
let wedge_serial_1 = binding.wedge_serial.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
match writer_rx.recv() {
|
|
||||||
Ok(data) => {
|
|
||||||
let _ = SerialPort::write(&game_serial_1,&data);
|
|
||||||
},
|
|
||||||
Err(e) => {println!("{:?}",e)}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//AtomicBool to check if touch should be active
|
|
||||||
let touch_active = Arc::new(AtomicBool::new(false));
|
|
||||||
|
|
||||||
//command handler for handshake between game and sync board
|
|
||||||
let touch_active_1 = touch_active.clone();
|
|
||||||
let touch_active_2 = touch_active.clone();
|
|
||||||
let game_serial_2 = binding.game_serial.clone();
|
|
||||||
let wedge_serial_1 = &binding.wedge_serial.clone();
|
|
||||||
let wedge_serial_2 = &binding.wedge_serial.clone();
|
|
||||||
let params_1 = params.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
let wedge = &binding.wedge_serial.clone();
|
|
||||||
let mut serialbuffer: Vec<u8> = vec![0; 1000];
|
|
||||||
loop {
|
|
||||||
let data = loop {
|
|
||||||
match SerialPort::read(&game_serial_2, serialbuffer.as_mut_slice()) {
|
|
||||||
Ok(t) => {break serialbuffer[..t].to_vec()},
|
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
|
|
||||||
Err(e) => eprintln!("{:?}", e),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut wedge = loop {
|
|
||||||
match wedge.lock() {
|
|
||||||
Ok(g) => {break g},
|
|
||||||
Err(e) => ()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match wacca::handle_data(&data, ¶ms, touch_active_2.clone(), wedge) {
|
|
||||||
Some(d) => command_tx.send(d).expect("Something has gone wrong!"),
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
//Send touch packet
|
|
||||||
let wedge: Arc<Mutex<SerialPort>> = wedge_serial_2.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
for i in 0..127 {
|
|
||||||
if touch_active_1.load(Ordering::Relaxed) {
|
|
||||||
let now = Instant::now();
|
|
||||||
let mut wedge = loop {
|
|
||||||
match wedge.lock() {
|
|
||||||
Ok(g) => {break g},
|
|
||||||
Err(e) => ()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut touchbuffer: Vec<u8> = vec![0; 36];
|
|
||||||
for x in 1..7 {
|
|
||||||
//bottleneck under here
|
|
||||||
let r: usize = 7-x;
|
|
||||||
let touch = match wacca::issue_command(&wedge, &CommandPacket { out: true, wedge_id: x as u8, command_id: 0xA1, data: Vec::new() }) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(_) => continue,
|
|
||||||
};
|
|
||||||
if touch.data.len() >= 4 {
|
|
||||||
touchbuffer[r as usize] = touchbuffer[r as usize] | fix_touch(touch.data[0], params_1.side);
|
|
||||||
touchbuffer[(r+6) as usize] = touchbuffer[(r+6) as usize] | fix_touch(touch.data[1], params_1.side);
|
|
||||||
touchbuffer[(r+12) as usize] = touchbuffer[(r+12) as usize] | fix_touch(touch.data[2], params_1.side);
|
|
||||||
touchbuffer[(r+18) as usize] = touchbuffer[(r+18) as usize] | fix_touch(touch.data[3], params_1.side);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
touchbuffer[0] = 129;
|
|
||||||
touchbuffer[34] = i;
|
|
||||||
touchbuffer[35] = 128;
|
|
||||||
touchbuffer[35] = calc_checksum(&touchbuffer);
|
|
||||||
if touchbuffer[34] == 127 {touchbuffer[34] = 0};
|
|
||||||
let _ = writer_tx.send(touchbuffer);
|
|
||||||
io::Write::flush(&mut io::stdout()).unwrap();
|
|
||||||
thread::sleep(Duration::from_millis(4));
|
|
||||||
} else {
|
} else {
|
||||||
thread::sleep(Duration::from_millis(4));
|
bridge::start(true, "COM18", "COM6");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//wedge stuff
|
|
||||||
//let (wedge_tx, wedge_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = mpsc::channel(); //channel pair for the wedge commands (unit board -> sync board)
|
|
||||||
//let (touch_tx, touch_rx): (Sender<wacca::CommandPacket>, Receiver<wacca::CommandPacket>) = mpsc::channel(); //channel pair for the touch commands (unit boards -> sync board)
|
|
||||||
|
|
||||||
/* //thread for submitting commands to the unit boards
|
|
||||||
let wedge_serial_1 = binding.wedge_serial.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
match wedge_cmd_rx.recv() {
|
|
||||||
Ok(data) => {
|
|
||||||
let _ = SerialPort::write(&wedge_serial_1,&data.serialize());
|
|
||||||
},
|
|
||||||
Err(e) => {println!("{:?}",e)}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//thread for receiving data from the unit boards
|
|
||||||
let wedge_serial_2 = binding.wedge_serial.clone();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let mut serialbuffer: Vec<u8> = vec![0; 1000];
|
|
||||||
loop {
|
|
||||||
let data = loop {
|
|
||||||
match SerialPort::read(&wedge_serial_2, serialbuffer.as_mut_slice()) {
|
|
||||||
Ok(t) => {break serialbuffer[..t].to_vec()},
|
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
|
|
||||||
Err(e) => eprintln!("{:?}", e),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let packet = match CommandPacket::new(data) {
|
|
||||||
Ok(d) => Some(d),
|
|
||||||
Err(e) => {println!("{:?}", e); None}
|
|
||||||
};
|
|
||||||
match packet {
|
|
||||||
Some(d) => {
|
|
||||||
match d.command_id {
|
|
||||||
0xA0 | 0xA2 | 0x94 | 0xC9 => {
|
|
||||||
println!("hfddfi");
|
|
||||||
let _ = &wedge_cmd_recv_tx.send(d);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {thread::sleep(Duration::from_millis(10))}
|
|
||||||
}
|
|
||||||
// match wacca::handle_data(&data, ¶ms, touch_active_2.clone()) {
|
|
||||||
// Some(d) => command_tx.send(d).expect("Something has gone wrong!"),
|
|
||||||
// None => (),
|
|
||||||
// };
|
|
||||||
};
|
|
||||||
}); */
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
println!("hi");
|
|
||||||
thread::sleep(Duration::from_millis(100));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
thread::sleep(Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
165
src/unit.rs
Normal file
165
src/unit.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
use serialport::SerialPort;
|
||||||
|
use std::{io::{self, Read, Write}, ops::Range, str, thread, time::{Duration, Instant}};
|
||||||
|
use crate::utils::calc_checksum;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CommandPacket {
|
||||||
|
out: bool,
|
||||||
|
wedge_id: u8,
|
||||||
|
command_id: u8,
|
||||||
|
data: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandPacket {
|
||||||
|
fn serialize(&self) -> Vec<u8> {
|
||||||
|
let dir: u8 = if self.out { 0xE0 } else { 0xD0 };
|
||||||
|
let mut packet: Vec<u8> = vec![self.wedge_id+dir, self.command_id];
|
||||||
|
packet.extend(&self.data);
|
||||||
|
let tail: Vec<u8> = vec![calc_checksum(&packet),240];
|
||||||
|
return [packet, tail].concat();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bulk(&self, r: Range<u8>) -> Vec<CommandPacket> {
|
||||||
|
let mut commands: Vec<CommandPacket> = Vec::new();
|
||||||
|
for i in r {
|
||||||
|
commands.push(CommandPacket { out: self.out, wedge_id: i, command_id: self.command_id, data: self.data.clone()})
|
||||||
|
}
|
||||||
|
commands
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dissect(data: Vec<u8>) -> Vec<CommandPacket> {
|
||||||
|
let mut commands: Vec<CommandPacket> = Vec::new();
|
||||||
|
|
||||||
|
let pieces: Vec<_> = data
|
||||||
|
.split(|&e| e == 0xf0)
|
||||||
|
.filter(|v| v.len() > 1 )
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for command in pieces.iter() {
|
||||||
|
match CommandPacket::new(command.to_vec()) {
|
||||||
|
Ok(c) => commands.push(c),
|
||||||
|
Err(e) => println!("ERR: {:?}", e)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
commands
|
||||||
|
}
|
||||||
|
fn new(mut data: Vec<u8>) -> Result<CommandPacket, String> {
|
||||||
|
if data.len() < 4 {
|
||||||
|
println!("LEN {:X?}",data);
|
||||||
|
return Err("Invalid Size".to_string())
|
||||||
|
}
|
||||||
|
match data[data.len()-1] {
|
||||||
|
0 => data = data[..data.len()-1].to_vec(),
|
||||||
|
0xF0 => (),
|
||||||
|
_ => data = [data, [0xF0].to_vec()].concat()
|
||||||
|
}
|
||||||
|
match data[0] {
|
||||||
|
209..215 => (),
|
||||||
|
225..231 => (),
|
||||||
|
_ => data = data[1..data.len()].to_vec(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let c = calc_checksum(&data[0..data.len()-2].to_vec());
|
||||||
|
let checksum: u8 = data[data.len()-2];
|
||||||
|
if c != checksum {
|
||||||
|
if calc_checksum(&[data[0..data.len()-2].to_vec(), vec![0x80]].concat()) != checksum {
|
||||||
|
println!("CHECK {:X?}",data);
|
||||||
|
return Err("Invalid Checksum".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let a: (bool, u8) = match data[0] {
|
||||||
|
209..215 => (false, data[0]-208),
|
||||||
|
225..231 => (true, data[0]-224),
|
||||||
|
_ => (false,0)
|
||||||
|
};
|
||||||
|
if a.1 == 0 {return Err("Wedge ID out of bounds".to_string())}
|
||||||
|
|
||||||
|
let datalen: usize = if data.len() > 4 {
|
||||||
|
data.len()-3
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
};
|
||||||
|
return Ok(CommandPacket {
|
||||||
|
out: a.0,
|
||||||
|
wedge_id: a.1,
|
||||||
|
command_id: data[1],
|
||||||
|
data: data[2..datalen].to_vec()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WedgePort {
|
||||||
|
pub hardware_port: Box<dyn SerialPort>,
|
||||||
|
}
|
||||||
|
impl WedgePort {
|
||||||
|
fn issue_command(&mut self, data: &CommandPacket) -> Result<CommandPacket, String> {
|
||||||
|
self.hardware_port.write(&data.serialize()).expect("Write failed!");
|
||||||
|
let _ = self.hardware_port.flush();
|
||||||
|
let mut serialbuffer: Vec<u8> = vec![0; 32];
|
||||||
|
let data = loop {
|
||||||
|
match self.hardware_port.read(serialbuffer.as_mut_slice()) {
|
||||||
|
Ok(t) => {break serialbuffer[..t].to_vec()},
|
||||||
|
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {},
|
||||||
|
Err(e) => eprintln!("{:?}", e),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//let x = self.hardware_port.read(serialbuffer.as_mut_slice()).expect("Found no data!");
|
||||||
|
//println!("{:?}",x);
|
||||||
|
CommandPacket::new(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_commandblk(&mut self, data: Vec<CommandPacket>) -> Vec<CommandPacket> {
|
||||||
|
for i in data {
|
||||||
|
let _ = self.hardware_port.write(&i.serialize());
|
||||||
|
let _ = self.hardware_port.flush();
|
||||||
|
thread::sleep(Duration::from_micros(1000));
|
||||||
|
}
|
||||||
|
//println!("poopy {:?}",start.elapsed());
|
||||||
|
let mut serialbuffer: Vec<u8> = vec![0; 256];
|
||||||
|
let data = loop {
|
||||||
|
match self.hardware_port.read(serialbuffer.as_mut_slice()) {
|
||||||
|
Ok(t) => {break serialbuffer[..t].to_vec()},
|
||||||
|
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {},
|
||||||
|
Err(e) => eprintln!("{:?}", e),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//let x = self.hardware_port.read(serialbuffer.as_mut_slice()).expect("Found no data!");
|
||||||
|
//println!("{:?}",x);
|
||||||
|
//let pieces: Vec<_> = it.split(|v| v == 0xf0 && it.peek() == 0x00).filter(|v| !v.is_empty()).collect();
|
||||||
|
CommandPacket::dissect(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_version(&mut self) -> Vec<(u8, String)> {
|
||||||
|
let mut versions: Vec<(u8, String)> = Vec::new();
|
||||||
|
// for i in 1..7 {
|
||||||
|
// match self.issue_command(&CommandPacket { out: true, wedge_id: i, command_id: 0xA8, data: Vec::new() }) {
|
||||||
|
// Ok(t) => {versions.push((i, str::from_utf8(&t.data).unwrap()[..6].to_string()))}
|
||||||
|
// Err(e) => println!("ERROR: {:?}", e),
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
let p = self.issue_commandblk(CommandPacket { out: true, wedge_id: 1, command_id: 0xA8, data: Vec::new() }.bulk(1..7));
|
||||||
|
for x in p {
|
||||||
|
versions.push((x.wedge_id, str::from_utf8(&x.data).unwrap()[..6].to_string()))
|
||||||
|
};
|
||||||
|
versions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_thresholds(&mut self, on: u8, off: u8) {
|
||||||
|
let p = self.issue_commandblk(CommandPacket { out: true, wedge_id: 1, command_id: 0x94, data: vec![on, off] }.bulk(1..7));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(&mut self) {
|
||||||
|
let p: Vec<CommandPacket> = self.issue_commandblk(CommandPacket { out: true, wedge_id: 1, command_id: 0x90, data: vec![0x14, 0x07, 0x7F, 0x3F, 0x44] }.bulk(1..7));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_touch(&mut self) -> Vec<(u8, Vec<u8>)> {
|
||||||
|
let mut s: Vec<(u8, Vec<u8>)> = Vec::new();
|
||||||
|
let p = self.issue_commandblk(CommandPacket { out: true, wedge_id: 1, command_id: 0xA1, data: Vec::new() }.bulk(1..7));
|
||||||
|
for i in p {
|
||||||
|
s.push((i.wedge_id, i.data[..4].to_vec()))
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
13
src/utils.rs
Normal file
13
src/utils.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
pub fn calc_checksum(data: &Vec<u8>) -> u8 {
|
||||||
|
let mut checksum: u8 = 0;
|
||||||
|
for byte in data.iter() {
|
||||||
|
checksum ^= byte;
|
||||||
|
}
|
||||||
|
checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_into(v: &mut Vec<u8>, position: usize, data: &[u8]) {
|
||||||
|
let buf = &mut v[position..];
|
||||||
|
let len = data.len().min(buf.len());
|
||||||
|
buf[..len].copy_from_slice(&data[..len]);
|
||||||
|
}
|
215
src/wacca.rs
215
src/wacca.rs
|
@ -1,215 +0,0 @@
|
||||||
use std::{io::{self, Read, Write}, str, sync::{atomic::{AtomicBool, Ordering}, mpsc::{Receiver, Sender}, Arc, Mutex}, thread, time::{Duration, Instant}};
|
|
||||||
|
|
||||||
use serial2::SerialPort;
|
|
||||||
|
|
||||||
pub struct SyncBoardParams<'a> {
|
|
||||||
pub param0000: &'a str,
|
|
||||||
pub param0016: &'a str,
|
|
||||||
pub param0032: &'a str,
|
|
||||||
pub sync_board_version: &'a str,
|
|
||||||
pub side: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SyncBoardParams<'static> {
|
|
||||||
pub fn get(side: &bool) -> SyncBoardParams<'static> {
|
|
||||||
SyncBoardParams {
|
|
||||||
param0000: " 0 0 1 2 3 4 5 15 15 15 15 15 15 11 11 11",
|
|
||||||
param0016: " 11 11 11 128 103 103 115 138 127 103 105 111 126 113 95 100",
|
|
||||||
param0032: " 101 115 98 86 76 67 68 48 117 0 82 154 0 6 35 4",
|
|
||||||
sync_board_version: "190523",
|
|
||||||
side: *side,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TouchBinding {
|
|
||||||
pub game_serial: Arc<SerialPort>,
|
|
||||||
pub wedge_serial: Arc<Mutex<SerialPort>>,
|
|
||||||
pub side: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CommandPacket {
|
|
||||||
pub out: bool,
|
|
||||||
pub wedge_id: u8,
|
|
||||||
pub command_id: u8,
|
|
||||||
pub data: Vec<u8>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct UnitBoardVersionPacket {
|
|
||||||
pub sync_board_version: String,
|
|
||||||
pub unit_board_version: Vec<String>,
|
|
||||||
pub side: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UnitBoardVersionPacket {
|
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
|
||||||
let mut s: Vec<u8> = vec![0xA8];
|
|
||||||
s.append(&mut self.sync_board_version.as_bytes().to_vec());
|
|
||||||
if self.side {s.push(0x4C)} else {s.push(0x52)};
|
|
||||||
for v in &self.unit_board_version {
|
|
||||||
s.append(&mut v.as_bytes().to_vec());
|
|
||||||
}
|
|
||||||
s.push(calc_checksum(&[s.as_slice(),vec![0x80].as_slice()].concat()));
|
|
||||||
//if self.side {s.push(104)} else {s.push(118)};
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CommandPacket {
|
|
||||||
pub fn serialize(&self) -> Vec<u8> {
|
|
||||||
let dir: u8 = if self.out { 0xE0 } else { 0xD0 };
|
|
||||||
let mut packet: Vec<u8> = vec![self.wedge_id+dir, self.command_id];
|
|
||||||
packet.extend(&self.data);
|
|
||||||
let tail: Vec<u8> = vec![calc_checksum(&packet),240];
|
|
||||||
return [packet, tail].concat();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(mut data: Vec<u8>) -> Result<CommandPacket, &'static str> { //TODO: Rewrite this parser to be more lenient with incoming data (trailing zero's etc)
|
|
||||||
if data.len() < 4 {
|
|
||||||
return Err("Invalid Size")
|
|
||||||
}
|
|
||||||
if data[data.len()-1] == 0 {
|
|
||||||
data = data[..data.len()-1].to_vec();
|
|
||||||
}
|
|
||||||
//let c: u8 = if data[1] == 0xA1 {
|
|
||||||
// calc_checksum(&[data[0..data.len()-2].to_vec(), vec![0x80]].concat())
|
|
||||||
//} else {
|
|
||||||
let c = calc_checksum(&data[0..data.len()-2].to_vec());
|
|
||||||
|
|
||||||
let checksum: u8 = data[data.len()-2];
|
|
||||||
if c != checksum {
|
|
||||||
if calc_checksum(&[data[0..data.len()-2].to_vec(), vec![0x80]].concat()) != checksum {
|
|
||||||
println!("check");
|
|
||||||
println!("{:X?}",data);
|
|
||||||
return Err("Invalid Checksum");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let a: (bool, u8) = match data[0] {
|
|
||||||
209..215 => (false, data[0]-208),
|
|
||||||
225..231 => (true, data[0]-224),
|
|
||||||
_ => (false,0)
|
|
||||||
};
|
|
||||||
if a.1 == 0 {return Err("Wedge ID out of bounds")}
|
|
||||||
|
|
||||||
let datalen: usize = if data.len() > 4 {
|
|
||||||
data.len()-3
|
|
||||||
} else {
|
|
||||||
2
|
|
||||||
};
|
|
||||||
return Ok(CommandPacket {
|
|
||||||
out: a.0,
|
|
||||||
wedge_id: a.1,
|
|
||||||
command_id: data[1],
|
|
||||||
data: data[2..datalen].to_vec()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn calc_checksum(data: &Vec<u8>) -> u8 {
|
|
||||||
let mut checksum: u8 = 0;
|
|
||||||
for byte in data.iter() {
|
|
||||||
checksum ^= byte;
|
|
||||||
}
|
|
||||||
checksum
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_data(buffer: &Vec<u8>, params: &SyncBoardParams, mut scan_active: Arc<AtomicBool>, mut wedge: std::sync::MutexGuard<'_, SerialPort>) -> Option<Vec<u8>> {
|
|
||||||
println!("aaaa {:?}",buffer[0]);
|
|
||||||
match buffer[0] {
|
|
||||||
0xa0 => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
return Some([vec![buffer[0]], params.sync_board_version.as_bytes().to_vec(), vec![44]].concat().to_vec());
|
|
||||||
},
|
|
||||||
0x77 => {
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
0x20 => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
0xa2 => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
for i in 1..7 {
|
|
||||||
let packet = issue_command(&wedge,&CommandPacket { out: true, wedge_id: i, command_id: 0xA0, data: Vec::new()});
|
|
||||||
}
|
|
||||||
return Some(vec![ 162, 63, 29, 0, 0, 0, 0 ]);
|
|
||||||
},
|
|
||||||
0x94 => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
for i in 1..7 {
|
|
||||||
let packet = issue_command(&wedge,&CommandPacket { out: true, wedge_id: i, command_id: 0x94, data: Vec::new() });
|
|
||||||
}
|
|
||||||
return Some(vec![ 148, 0, 20, 0, 0, 0, 0 ]);
|
|
||||||
},
|
|
||||||
0xc9 => {
|
|
||||||
scan_active.store(true, Ordering::Relaxed);
|
|
||||||
for i in 1..7 {
|
|
||||||
let packet = issue_command(&wedge,&CommandPacket { out: true, wedge_id: i, command_id: 0x90, data: vec![0x14, 0x07, 0x7F, 0x3F,]});
|
|
||||||
}
|
|
||||||
return Some(vec![ 201, 0, 73, 0, 0, 0, 0 ]);
|
|
||||||
},
|
|
||||||
0xa8 => {
|
|
||||||
let mut versions: Vec<String> = Vec::new();
|
|
||||||
for i in 1..7 {
|
|
||||||
let packet = issue_command(&wedge,&CommandPacket { out: true, wedge_id: i, command_id: 0xA0, data: Vec::new() });
|
|
||||||
//thread::sleep(Duration::from_secs(1));
|
|
||||||
let data = packet.expect("veri bad");
|
|
||||||
let version = str::from_utf8(&data.data).expect("Error").to_string();
|
|
||||||
versions.push(version[..6].to_string());
|
|
||||||
println!("{:?}", data)
|
|
||||||
|
|
||||||
}
|
|
||||||
//let mut versions = vec!["190523".to_string(), "190523".to_string(), "190523".to_string(), "190523".to_string(), "190523".to_string(), "190523".to_string()];
|
|
||||||
return Some(UnitBoardVersionPacket {
|
|
||||||
sync_board_version: params.sync_board_version.to_string(),
|
|
||||||
unit_board_version: versions,
|
|
||||||
side: params.side,
|
|
||||||
}.serialize());
|
|
||||||
},
|
|
||||||
0x72 => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
let param: &str = match buffer[3] {
|
|
||||||
0x30 => {params.param0000}
|
|
||||||
0x31 => {params.param0016}
|
|
||||||
0x33 => {params.param0032}
|
|
||||||
_ => {""}
|
|
||||||
};
|
|
||||||
return Some([param.as_bytes(), &vec![calc_checksum(¶m.as_bytes().to_vec())]].concat())
|
|
||||||
},
|
|
||||||
0x9a => {
|
|
||||||
scan_active.store(false, Ordering::Relaxed);
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
return None;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn issue_command(port: &SerialPort, data: &CommandPacket) -> Result<CommandPacket, &'static str> {
|
|
||||||
let now = Instant::now();
|
|
||||||
let _ = port.write(&data.serialize());
|
|
||||||
//thread::sleep(Duration::from_secs(1));
|
|
||||||
let mut serialbuffer: Vec<u8> = vec![0; 32];
|
|
||||||
println!("afw {:?}",now.elapsed());
|
|
||||||
let data = loop {
|
|
||||||
//println!("hi");
|
|
||||||
match port.read(serialbuffer.as_mut_slice()) { //slow poopy function
|
|
||||||
Ok(t) => {break serialbuffer[..t].to_vec()},
|
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
|
|
||||||
Err(e) => eprintln!("{:?}", e),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
println!("x {:?}",now.elapsed());
|
|
||||||
CommandPacket::new(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fix_touch(byte: u8, side: bool) -> u8 {
|
|
||||||
let side = side.clone();
|
|
||||||
if side {
|
|
||||||
byte.reverse_bits() >> 3
|
|
||||||
} else {
|
|
||||||
byte & 0x7f
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue