This commit is contained in:
4yn 2022-02-01 10:37:53 +08:00
parent 3be06955ea
commit 2b20902179
9 changed files with 166 additions and 100 deletions

View File

@ -1,3 +1,3 @@
{
"editor.formatOnSave": true
}
"editor.formatOnSave": true
}

View File

@ -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();

View File

@ -1,3 +1,3 @@
fn main() {
tauri_build::build()
tauri_build::build();
}

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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();
}

View File

@ -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));
}

View File

@ -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>