mirror of
https://github.com/4yn/slidershim.git
synced 2026-04-24 23:46:57 -05:00
voltex
This commit is contained in:
parent
3be06955ea
commit
2b20902179
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
fn main() {
|
||||
tauri_build::build()
|
||||
tauri_build::build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<bool>) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<bool>, led_state: &mut LedState) {
|
||||
fn calc_lights(&self, flat_controller_state: Option<&Vec<bool>>, led_state: &mut LedState) {
|
||||
match self.mode {
|
||||
LedMode::Reactive { .. } => {
|
||||
let banks: Vec<bool> = 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<bool> = 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::<u8>();
|
||||
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::<u8>();
|
||||
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<bool>;
|
||||
{
|
||||
let controller_state_handle = self.state.controller_state.lock().unwrap();
|
||||
flat_controller_state = controller_state_handle.flat(&self.sensitivity);
|
||||
}
|
||||
let flat_controller_state: Option<Vec<bool>> = 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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@
|
|||
<option value="kb-32-tasoller">Keyboard 32-zone, Tasoller Layout</option
|
||||
>
|
||||
<option value="kb-32-yuancon">Keyboard 32-zone, Yuancon Layout</option>
|
||||
<option value="kb-6-deemo">Keyboard 6-zone, Deemo Layout</option>
|
||||
<option value="kb-8-deemo">Keyboard 8-zone, Deemo Layout</option>
|
||||
<option value="kb-voltex">Keyboard 10-zone, Voltex Layout</option>
|
||||
<option value="websocket">Websocket</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -139,6 +140,7 @@
|
|||
<option value="reactive-4">Reactive, 4-Zone</option>
|
||||
<option value="reactive-8">Reactive, 8-Zone</option>
|
||||
<option value="reactive-16">Reactive, 16-Zone</option>
|
||||
<option value="reactive-voltex">Reactive, Voltex Layout</option>
|
||||
<option value="attract">Rainbow Attract Mode</option>
|
||||
<option value="test">LED Test</option>
|
||||
<option value="websocket">Websocket</option>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user