mirror of
https://github.com/4yn/slidershim.git
synced 2026-09-07 16:25:40 -05:00
air leds
This commit is contained in:
@@ -43,6 +43,8 @@ impl Config {
|
||||
"ledFaster": false,
|
||||
"ledColorActive": "#ff00ff",
|
||||
"ledColorInactive": "#ffff00",
|
||||
"ledColorAirActive": "#0086ed",
|
||||
"ledColorAirInactive": "#000000",
|
||||
"ledSensitivity": 20,
|
||||
"ledWebsocketUrl": "localhost:3001",
|
||||
"ledSerialPort": "COM5"
|
||||
|
||||
@@ -13,6 +13,8 @@ pub enum ReactiveLayout {
|
||||
pub struct ColorScheme {
|
||||
pub active: [u8; 3],
|
||||
pub inactive: [u8; 3],
|
||||
pub air_active: [u8; 3],
|
||||
pub air_inactive: [u8; 3],
|
||||
}
|
||||
|
||||
impl ColorScheme {
|
||||
@@ -28,6 +30,16 @@ impl ColorScheme {
|
||||
u8::from_str_radix(&v["ledColorInactive"].as_str()?[3..5], 16).ok()?,
|
||||
u8::from_str_radix(&v["ledColorInactive"].as_str()?[5..7], 16).ok()?,
|
||||
],
|
||||
air_active: [
|
||||
u8::from_str_radix(&v["ledColorAirActive"].as_str()?[1..3], 16).ok()?,
|
||||
u8::from_str_radix(&v["ledColorAirActive"].as_str()?[3..5], 16).ok()?,
|
||||
u8::from_str_radix(&v["ledColorAirActive"].as_str()?[5..7], 16).ok()?,
|
||||
],
|
||||
air_inactive: [
|
||||
u8::from_str_radix(&v["ledColorAirInactive"].as_str()?[1..3], 16).ok()?,
|
||||
u8::from_str_radix(&v["ledColorAirInactive"].as_str()?[3..5], 16).ok()?,
|
||||
u8::from_str_radix(&v["ledColorAirInactive"].as_str()?[5..7], 16).ok()?,
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,6 +47,8 @@ impl ColorScheme {
|
||||
Self {
|
||||
active: [255, 0, 255],
|
||||
inactive: [255, 255, 0],
|
||||
air_active: [0, 134, 237],
|
||||
air_inactive: [0, 0, 0],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +57,8 @@ impl ColorScheme {
|
||||
.or(Some(Self {
|
||||
active: [255, 0, 255],
|
||||
inactive: [255, 255, 0],
|
||||
air_active: [0, 134, 237],
|
||||
air_inactive: [0, 0, 0],
|
||||
}))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use async_trait::async_trait;
|
||||
use log::{error, info};
|
||||
use palette::{FromColor, Hsv, Srgb};
|
||||
use palette::{encoding::Srgb as SrgbEncoding, rgb::Rgb, FromColor, Hsv, Srgb};
|
||||
use serialport::{ClearBuffer, SerialPort};
|
||||
use std::{
|
||||
ops::DerefMut,
|
||||
@@ -15,6 +15,22 @@ use crate::{
|
||||
|
||||
use super::config::{LightsMode, ReactiveLayout};
|
||||
|
||||
fn get_rainbow(phase: f64, desaturate: bool) -> Rgb<SrgbEncoding, u8> {
|
||||
let phase = ((phase % 1.0) + 1.0) % 1.0;
|
||||
let color = Srgb::from_color(Hsv::new(
|
||||
phase * 360.0,
|
||||
match desaturate {
|
||||
false => 1.0,
|
||||
true => 0.2,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
1.0,
|
||||
))
|
||||
.into_format::<u8>();
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
pub struct LightsJob {
|
||||
state: SliderState,
|
||||
mode: LightsMode,
|
||||
@@ -75,6 +91,16 @@ impl LightsJob {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for idx in 0..3 {
|
||||
lights.paint_air(
|
||||
idx,
|
||||
match flat_input[32 + idx * 2] || flat_input[33 + idx * 2] {
|
||||
true => &color.air_active,
|
||||
false => &color.air_inactive,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
ReactiveLayout::Six => {
|
||||
let banks: Vec<bool> = [0..6, 6..10, 10..16, 16..22, 22..26, 26..32]
|
||||
@@ -106,6 +132,16 @@ impl LightsJob {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for idx in 0..3 {
|
||||
lights.paint_air(
|
||||
idx,
|
||||
match flat_input[32 + idx * 2] || flat_input[33 + idx * 2] {
|
||||
true => &color.air_active,
|
||||
false => &color.air_inactive,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
ReactiveLayout::Voltex => {
|
||||
lights.ground.fill(0);
|
||||
@@ -207,23 +243,32 @@ impl LightsJob {
|
||||
.elapsed()
|
||||
.div_duration_f64(Duration::from_secs(4))
|
||||
% 1.0;
|
||||
|
||||
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,
|
||||
match idx % 2 {
|
||||
0 => match banks[idx / 2] {
|
||||
true => 0.2,
|
||||
false => 1.0,
|
||||
},
|
||||
1 => 1.0,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
1.0,
|
||||
))
|
||||
.into_format::<u8>();
|
||||
let slice_theta = theta + (idx as f64) / 32.0;
|
||||
let color = get_rainbow(slice_theta, ((idx % 2) == 0) && banks[idx / 2]);
|
||||
lights.paint(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
|
||||
// left
|
||||
for idx in 0..3 {
|
||||
let slice_theta = theta - ((idx + 1) as f64) / 32.0;
|
||||
let color = get_rainbow(
|
||||
slice_theta,
|
||||
flat_input[32 + idx * 2] || flat_input[33 + idx * 2],
|
||||
);
|
||||
lights.paint_air_left(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
|
||||
// right
|
||||
for idx in 0..3 {
|
||||
let slice_theta = theta + (idx as f64) / 32.0;
|
||||
let color = get_rainbow(
|
||||
slice_theta,
|
||||
flat_input[32 + idx * 2] || flat_input[33 + idx * 2],
|
||||
);
|
||||
lights.paint_air_right(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,11 +278,26 @@ impl LightsJob {
|
||||
.elapsed()
|
||||
.div_duration_f64(Duration::from_secs(4))
|
||||
% 1.0;
|
||||
|
||||
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>();
|
||||
let slice_theta = theta + (idx as f64) / 32.0;
|
||||
let color = get_rainbow(slice_theta, false);
|
||||
lights.paint(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
|
||||
// left
|
||||
for idx in 0..3 {
|
||||
let slice_theta = theta - ((idx + 1) as f64) / 32.0;
|
||||
let color = get_rainbow(slice_theta, false);
|
||||
lights.paint_air_left(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
|
||||
// right
|
||||
for idx in 0..3 {
|
||||
let slice_theta = theta + (idx as f64) / 32.0;
|
||||
let color = get_rainbow(slice_theta, false);
|
||||
lights.paint_air_right(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
}
|
||||
LightsMode::Serial { .. } => {
|
||||
// https://github.com/jmontineri/OpeNITHM/blob/89e9a43f7484e8949cd31bbff79c32f21ea3ec1d/Firmware/OpeNITHM/SerialProcessor.h
|
||||
|
||||
@@ -108,6 +108,12 @@ async fn handle_umgr_leds(ws_stream: WebSocketStream<Upgraded>, state: SliderSta
|
||||
);
|
||||
}
|
||||
|
||||
for i in 0..3 {
|
||||
let pos = 94 + i * 3;
|
||||
lights_handle
|
||||
.paint_air(2 - i, &[payload[pos], payload[pos + 1], payload[pos + 2]]);
|
||||
}
|
||||
|
||||
if latest_lights.elapsed() > delay {
|
||||
lights_handle.dirty = true;
|
||||
latest_lights = Instant::now();
|
||||
|
||||
@@ -61,6 +61,10 @@ pub struct SliderLights {
|
||||
/// right. Alternates between 16 touch pad pixels and 15 divider pixels.
|
||||
pub ground: [u8; 3 * 31],
|
||||
|
||||
// RGB light values for left and right air sensors, bottom to top
|
||||
pub air_left: [u8; 3 * 3],
|
||||
pub air_right: [u8; 3 * 3],
|
||||
|
||||
/// Internal dirty flag used to indicate that new lighting data is available.
|
||||
pub dirty: bool,
|
||||
|
||||
@@ -73,6 +77,8 @@ impl SliderLights {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ground: [0; 3 * 31],
|
||||
air_left: [0; 3 * 3],
|
||||
air_right: [0; 3 * 3],
|
||||
dirty: false,
|
||||
start: Instant::now(),
|
||||
}
|
||||
@@ -83,8 +89,23 @@ impl SliderLights {
|
||||
self.ground[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
}
|
||||
|
||||
pub fn paint_air(&mut self, idx: usize, color: &[u8; 3]) {
|
||||
self.air_left[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
self.air_right[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
}
|
||||
|
||||
pub fn paint_air_left(&mut self, idx: usize, color: &[u8; 3]) {
|
||||
self.air_left[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
}
|
||||
|
||||
pub fn paint_air_right(&mut self, idx: usize, color: &[u8; 3]) {
|
||||
self.air_right[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.ground.fill(0);
|
||||
self.air_left.fill(0);
|
||||
self.air_right.fill(0);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
@@ -122,6 +143,8 @@ impl SliderState {
|
||||
{
|
||||
let lights_handle = self.lights.lock();
|
||||
buf.extend(lights_handle.ground);
|
||||
buf.extend(lights_handle.air_left);
|
||||
buf.extend(lights_handle.air_right);
|
||||
};
|
||||
|
||||
buf
|
||||
|
||||
Reference in New Issue
Block a user