From 2b2090217901545d604ebd99cc8c3c7a9b1374d0 Mon Sep 17 00:00:00 2001 From: 4yn Date: Tue, 1 Feb 2022 10:37:53 +0800 Subject: [PATCH] voltex --- .vscode/settings.json | 4 +- src-tauri/src/bin/test_usb.rs | 20 ++- src-tauri/src/build.rs | 2 +- src-tauri/src/slider_io/config.rs | 22 ++- src-tauri/src/slider_io/controller_state.rs | 4 + src-tauri/src/slider_io/device.rs | 5 +- src-tauri/src/slider_io/keyboard.rs | 43 ++++-- src-tauri/src/slider_io/led.rs | 162 +++++++++++--------- src/App.svelte | 4 +- 9 files changed, 166 insertions(+), 100 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 23fd35f..ad92582 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "editor.formatOnSave": true -} \ No newline at end of file + "editor.formatOnSave": true +} diff --git a/src-tauri/src/bin/test_usb.rs b/src-tauri/src/bin/test_usb.rs index f25db88..abc291f 100644 --- a/src-tauri/src/bin/test_usb.rs +++ b/src-tauri/src/bin/test_usb.rs @@ -13,23 +13,35 @@ fn main() { // r#"{ // "deviceMode": "yuancon", // "outputMode": "kb-32-tasoller", + // "keyboardSensitivity": 50,fdwdfp1 // "ledMode": "reactive-8", - // "keyboardSensitivity": 50 + // "ledSensitivity": 50 // }"#, // ) // .unwrap(); let config = Config::from_str( r#"{ - "deviceMode": "tasoller-two", - "outputMode": "kb-32-tasoller", + "deviceMode": "yuancon", + "outputMode": "kb-voltex", "keyboardSensitivity": 50, - "ledMode": "reactive-8", + "ledMode": "reactive-voltex", "ledSensitivity": 50 }"#, ) .unwrap(); + // let config = Config::from_str( + // r#"{ + // "deviceMode": "tasoller-two", + // "outputMode": "kb-32-tasoller", + // "keyboardSensitivity": 50, + // "ledMode": "reactive-8", + // "ledSensitivity": 50 + // }"#, + // ) + // .unwrap(); + let manager = Manager::new(config); let mut input = String::new(); diff --git a/src-tauri/src/build.rs b/src-tauri/src/build.rs index 795b9b7..311900d 100644 --- a/src-tauri/src/build.rs +++ b/src-tauri/src/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_build::build() + tauri_build::build(); } diff --git a/src-tauri/src/slider_io/config.rs b/src-tauri/src/slider_io/config.rs index e323480..9918e01 100644 --- a/src-tauri/src/slider_io/config.rs +++ b/src-tauri/src/slider_io/config.rs @@ -19,6 +19,7 @@ pub enum KeyboardLayout { Tasoller, Yuancon, Deemo, + Voltex, } #[derive(Debug, Clone)] @@ -35,9 +36,8 @@ pub enum OutputMode { #[derive(Debug, Clone, Copy)] pub enum ReactiveLayout { - Four, - Eight, - Sixteen, + Even { splits: usize }, + Voltex, } #[derive(Debug, Clone)] @@ -87,10 +87,14 @@ impl Config { layout: KeyboardLayout::Yuancon, sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?, }, - "kb-6-deemo" => OutputMode::Keyboard { + "kb-8-deemo" => OutputMode::Keyboard { layout: KeyboardLayout::Deemo, sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?, }, + "kb-voltex" => OutputMode::Keyboard { + layout: KeyboardLayout::Voltex, + sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?, + }, "websocket" => OutputMode::Websocket { url: v["outputWebsocketUrl"].to_string(), }, @@ -99,15 +103,19 @@ impl Config { led_mode: match v["ledMode"].as_str()? { "none" => LedMode::None, "reactive-4" => LedMode::Reactive { - layout: ReactiveLayout::Four, + layout: ReactiveLayout::Even { splits: 4 }, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, "reactive-8" => LedMode::Reactive { - layout: ReactiveLayout::Eight, + layout: ReactiveLayout::Even { splits: 8 }, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, "reactive-16" => LedMode::Reactive { - layout: ReactiveLayout::Sixteen, + layout: ReactiveLayout::Even { splits: 16 }, + sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, + }, + "reactive-voltex" => LedMode::Reactive { + layout: ReactiveLayout::Voltex, sensitivity: u8::try_from(v["ledSensitivity"].as_i64()?).ok()?, }, "attract" => LedMode::Attract, diff --git a/src-tauri/src/slider_io/controller_state.rs b/src-tauri/src/slider_io/controller_state.rs index 22a1b2c..f8c811c 100644 --- a/src-tauri/src/slider_io/controller_state.rs +++ b/src-tauri/src/slider_io/controller_state.rs @@ -48,6 +48,10 @@ impl LedState { start: Instant::now(), } } + + pub fn paint(&mut self, idx: usize, color: &[u8; 3]) { + self.led_state[3 * idx..3 * (idx + 1)].copy_from_slice(color); + } } pub struct FullState { diff --git a/src-tauri/src/slider_io/device.rs b/src-tauri/src/slider_io/device.rs index f6709bd..3d8a363 100644 --- a/src-tauri/src/slider_io/device.rs +++ b/src-tauri/src/slider_io/device.rs @@ -179,10 +179,11 @@ impl HidDeviceJob { .ground_state .copy_from_slice(&buf.data[2..34]); for i in 0..6 { - controller_state.air_state[i ^ 1] = if buf.data[0] & (1 << i) == 0 { 1 } else { 0 }; + controller_state.air_state[i ^ 1] = 0; + // controller_state.air_state[i ^ 1] = (buf.data[0] >> i) & 1; } for i in 0..3 { - controller_state.extra_state[i] = if buf.data[1] & (1 << i) == 0 { 1 } else { 0 }; + controller_state.extra_state[i] = (buf.data[1] >> i) & 1; } }, WriteType::Interrupt, diff --git a/src-tauri/src/slider_io/keyboard.rs b/src-tauri/src/slider_io/keyboard.rs index 06d2f84..d9eb7e4 100644 --- a/src-tauri/src/slider_io/keyboard.rs +++ b/src-tauri/src/slider_io/keyboard.rs @@ -31,16 +31,36 @@ const YUANCON_KB_MAP: [usize; 41] = [ #[rustfmt::skip] const DEEMO_KB_MAP: [usize; 41] = [ - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, // S + 0x41, 0x41, 0x41, 0x41, // A + 0x35, 0x35, 0x35, 0x35, // S 0x4f, 0x4f, 0x4f, 0x4f, // D - 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, // F - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, // J + 0x46, 0x46, 0x46, 0x46, // F + 0x4a, 0x4a, 0x4a, 0x4a, // J 0x4b, 0x4b, 0x4b, 0x4b, // K - 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, // L + 0x4c, 0x4c, 0x4c, 0x4c, // L + 0xba, 0xba, 0xba, 0xba, // VK_OEM_1 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // VK_SPACE 0x00, 0x00, 0x00, // Disabled ]; +#[rustfmt::skip] +const VOLTEX_KB_MAP: [usize; 41] = [ + 0x57, 0x57, 0x57, 0x57, // W + 0x45, 0x45, 0x45, 0x45, // E + 0x43, 0x44, + 0x43, 0x44, + 0x43, 0x46, // D + 0x43, 0x46, // C // F + 0x4d, 0x4a, // M // J + 0x4d, 0x4a, // K + 0x4d, 0x4b, + 0x4d, 0x4b, + 0x4f, 0x4f, 0x4f, 0x4f, // O + 0x50, 0x50, 0x50, 0x50, // P + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Disabled + 0x31, 0x1b, 0x0d, // 1, VK_ESCAPE, VK_RETURN +]; + pub struct KeyboardOutput { ground_to_idx: [usize; 41], idx_to_keycode: [u16; 41], @@ -59,6 +79,7 @@ impl KeyboardOutput { KeyboardLayout::Tasoller => &TASOLLER_KB_MAP, KeyboardLayout::Yuancon => &YUANCON_KB_MAP, KeyboardLayout::Deemo => &DEEMO_KB_MAP, + KeyboardLayout::Voltex => &VOLTEX_KB_MAP, }; let mut ground_to_idx = [0 as usize; 41]; @@ -101,14 +122,12 @@ impl KeyboardOutput { } pub fn tick(&mut self, flat_controller_state: &Vec) { - self - .next_keys - .iter_mut() - .zip(flat_controller_state) - .for_each(|(a, b)| { - *a = *b; - }); - // println!("{:?}", self.next_keys); + self.next_keys.fill(false); + for (idx, x) in flat_controller_state.iter().enumerate() { + if *x { + self.next_keys[self.ground_to_idx[idx]] = true; + } + } self.send(); } diff --git a/src-tauri/src/slider_io/led.rs b/src-tauri/src/slider_io/led.rs index b9613b1..63557b3 100644 --- a/src-tauri/src/slider_io/led.rs +++ b/src-tauri/src/slider_io/led.rs @@ -15,90 +15,108 @@ use crate::slider_io::{ pub struct LedJob { state: FullState, mode: LedMode, - sensitivity: u8, - - splits: usize, - buttons_per_split: usize, } impl LedJob { pub fn new(state: &FullState, mode: &LedMode) -> Self { - let mut splits = 16; - let mut sensitivity = 20; - - match mode { - LedMode::Reactive { - layout, - sensitivity: sensitivity_ref, - } => { - sensitivity = *sensitivity_ref; - splits = match layout { - ReactiveLayout::Four => 4, - ReactiveLayout::Eight => 8, - ReactiveLayout::Sixteen => 16, - } - } - _ => {} - }; - Self { state: state.clone(), mode: mode.clone(), - sensitivity, - - splits, - buttons_per_split: 32 / splits, } } - fn calc_lights(&self, flat_controller_state: &Vec, led_state: &mut LedState) { + fn calc_lights(&self, flat_controller_state: Option<&Vec>, led_state: &mut LedState) { match self.mode { - LedMode::Reactive { .. } => { - let banks: Vec = flat_controller_state - .chunks(self.buttons_per_split) - .take(self.splits) - .map(|x| x.iter().any(|x| *x)) - .collect(); + LedMode::Reactive { layout, .. } => { + let flat_controller_state = flat_controller_state.unwrap(); - led_state - .led_state - .chunks_mut(3) - .enumerate() - .for_each(|(idx, chunk)| match (idx + 1) % self.buttons_per_split { - 0 => { - chunk[0] = 255; - chunk[1] = 0; - chunk[2] = 255; + match layout { + ReactiveLayout::Even { splits } => { + let buttons_per_split = 32 / splits; + + let banks: Vec = flat_controller_state + .chunks(32 / splits) + .take(splits) + .map(|x| x.contains(&true)) + .collect(); + + for idx in 0..31 { + led_state.paint( + idx, + match (idx + 1) % buttons_per_split { + 0 => &[255, 0, 255], + _ => match banks[idx / buttons_per_split] { + true => &[255, 0, 255], + false => &[255, 255, 0], + }, + }, + ); } - _ => match banks[idx / self.buttons_per_split] { - true => { - chunk[0] = 255; - chunk[1] = 0; - chunk[2] = 255; + } + ReactiveLayout::Voltex => { + led_state.led_state.fill(0); + + // Fixed + led_state.paint(3, &[0, 0, 64]); + for idx in 0..5 { + led_state.paint(7 + idx * 4, &[64, 64, 64]); + } + led_state.paint(27, &[64, 0, 0]); + + // Left laser left + if flat_controller_state[0..4].contains(&true) { + for idx in 0..3 { + led_state.paint(idx, &[0, 0, 255]); } - false => { - chunk[0] = 255; - chunk[1] = 255; - chunk[2] = 0; + }; + + // Left laser right + if flat_controller_state[4..8].contains(&true) { + for idx in 4..7 { + led_state.paint(idx, &[0, 0, 255]); } - }, - }) + }; + + // Right laser left + if flat_controller_state[24..28].contains(&true) { + for idx in 24..27 { + led_state.paint(idx, &[255, 0, 0]); + } + }; + // Right laser right + if flat_controller_state[28..32].contains(&true) { + for idx in 28..31 { + led_state.paint(idx, &[255, 0, 0]); + } + }; + + // Buttons + for (btn_idx, btn_banks) in flat_controller_state[8..24].chunks(4).enumerate() { + if btn_banks.iter().skip(1).step_by(2).any(|x| *x) { + led_state.paint(8 + btn_idx * 4, &[255, 255, 255]); + led_state.paint(10 + btn_idx * 4, &[255, 255, 255]); + } + } + + // Fx + for (fx_idx, fx_banks) in flat_controller_state[8..24].chunks(8).enumerate() { + if fx_banks.iter().step_by(2).any(|x| *x) { + led_state.paint(9 + fx_idx * 8, &[255, 0, 0]); + led_state.paint(11 + fx_idx * 8, &[255, 0, 0]); + led_state.paint(13 + fx_idx * 8, &[255, 0, 0]); + } + } + } + } } LedMode::Attract => { let now = Instant::now(); let theta = (now - led_state.start).div_duration_f64(Duration::from_secs(4)) % 1.0; - led_state - .led_state - .chunks_mut(3) - .enumerate() - .for_each(|(idx, chunk)| { - let slice_theta = (&theta + (idx as f64) / 31.0) % 1.0; - let color = - Srgb::from_color(Hsv::new(slice_theta * 360.0, 1.0, 1.0)).into_format::(); - chunk[0] = color.red; - chunk[1] = color.green; - chunk[2] = color.blue; - }); + for idx in 0..31 { + let slice_theta = (&theta + (idx as f64) / 32.0) % 1.0; + let color = Srgb::from_color(Hsv::new(slice_theta * 360.0, 1.0, 1.0)).into_format::(); + led_state.paint(idx, &[color.red, color.green, color.blue]); + } } _ => panic!("Not implemented"), } @@ -111,15 +129,17 @@ impl Job for LedJob { fn setup(&mut self) {} fn tick(&mut self) { - let flat_controller_state: Vec; - { - let controller_state_handle = self.state.controller_state.lock().unwrap(); - flat_controller_state = controller_state_handle.flat(&self.sensitivity); - } + let flat_controller_state: Option> = match self.mode { + LedMode::Reactive { sensitivity, .. } => { + let controller_state_handle = self.state.controller_state.lock().unwrap(); + Some(controller_state_handle.flat(&sensitivity)) + } + _ => None, + }; { let mut led_state_handle = self.state.led_state.lock().unwrap(); - self.calc_lights(&flat_controller_state, led_state_handle.deref_mut()); + self.calc_lights(flat_controller_state.as_ref(), led_state_handle.deref_mut()); } thread::sleep(Duration::from_millis(33)); } diff --git a/src/App.svelte b/src/App.svelte index 144703d..485294f 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -92,7 +92,8 @@ - + + @@ -139,6 +140,7 @@ +