mirror of
https://github.com/4yn/slidershim.git
synced 2024-11-27 23:10:49 +01:00
refactor state structs
This commit is contained in:
parent
2a0d466cf3
commit
ac4933449b
@ -4,7 +4,6 @@ use std::sync::{atomic::Ordering, Arc};
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
controller_state::FullState,
|
||||
device::{brokenithm::BrokenithmJob, config::DeviceMode, device::HidDeviceJob},
|
||||
lighting::{config::LedMode, led::LedJob},
|
||||
output::{config::OutputMode, output::OutputJob},
|
||||
@ -12,11 +11,12 @@ use crate::{
|
||||
utils::LoopTimer,
|
||||
worker::{AsyncHaltableWorker, AsyncWorker, ThreadWorker},
|
||||
},
|
||||
state::SliderState,
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Context {
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
config: Config,
|
||||
device_worker: Option<ThreadWorker>,
|
||||
brokenithm_worker: Option<AsyncHaltableWorker>,
|
||||
@ -32,7 +32,7 @@ impl Context {
|
||||
info!("Output config {:?}", config.output_mode);
|
||||
info!("LED config {:?}", config.led_mode);
|
||||
|
||||
let state = FullState::new();
|
||||
let state = SliderState::new();
|
||||
let mut timers = vec![];
|
||||
|
||||
let (device_worker, brokenithm_worker) = match &config.device_mode {
|
||||
@ -96,7 +96,7 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_state(&self) -> FullState {
|
||||
pub fn clone_state(&self) -> SliderState {
|
||||
self.state.clone()
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ use tokio::{
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tungstenite::{handshake, Message};
|
||||
|
||||
use crate::{controller_state::FullState, shared::worker::AsyncHaltableJob};
|
||||
use crate::{shared::worker::AsyncHaltableJob, state::SliderState};
|
||||
|
||||
// https://levelup.gitconnected.com/handling-websocket-and-http-on-the-same-port-with-rust-f65b770722c9
|
||||
|
||||
@ -68,7 +68,7 @@ async fn serve_file(path: &str) -> Result<Response<Body>, Infallible> {
|
||||
|
||||
async fn handle_brokenithm(
|
||||
ws_stream: WebSocketStream<Upgraded>,
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
led_enabled: bool,
|
||||
) {
|
||||
let (mut ws_write, mut ws_read) = ws_stream.split();
|
||||
@ -114,15 +114,15 @@ async fn handle_brokenithm(
|
||||
}
|
||||
39 => {
|
||||
if chars[0] == 'b' {
|
||||
let mut controller_state_handle = state_handle.controller_state.lock();
|
||||
let mut input_handle = state_handle.input.lock();
|
||||
for (idx, c) in chars[0..32].iter().enumerate() {
|
||||
controller_state_handle.ground_state[idx] = match *c == '1' {
|
||||
input_handle.ground[idx] = match *c == '1' {
|
||||
false => 0,
|
||||
true => 255,
|
||||
}
|
||||
}
|
||||
for (idx, c) in chars[32..38].iter().enumerate() {
|
||||
controller_state_handle.air_state[idx] = match *c == '1' {
|
||||
input_handle.air[idx] = match *c == '1' {
|
||||
false => 0,
|
||||
true => 1,
|
||||
}
|
||||
@ -167,8 +167,8 @@ async fn handle_brokenithm(
|
||||
loop {
|
||||
let mut led_data = vec![0; 93];
|
||||
{
|
||||
let led_state_handle = state_handle.led_state.lock();
|
||||
(&mut led_data).copy_from_slice(&led_state_handle.led_state);
|
||||
let lights_handle = state_handle.lights.lock();
|
||||
(&mut led_data).copy_from_slice(&lights_handle.ground);
|
||||
}
|
||||
msg_write_handle.send(Message::Binary(led_data)).ok();
|
||||
|
||||
@ -187,7 +187,7 @@ async fn handle_brokenithm(
|
||||
|
||||
async fn handle_websocket(
|
||||
mut request: Request<Body>,
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
led_enabled: bool,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
let res = match handshake::server::create_response_with_body(&request, || Body::empty()) {
|
||||
@ -227,7 +227,7 @@ async fn handle_websocket(
|
||||
async fn handle_request(
|
||||
request: Request<Body>,
|
||||
remote_addr: SocketAddr,
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
ground_only: bool,
|
||||
led_enabled: bool,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
@ -257,13 +257,13 @@ async fn handle_request(
|
||||
}
|
||||
|
||||
pub struct BrokenithmJob {
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
ground_only: bool,
|
||||
led_enabled: bool,
|
||||
}
|
||||
|
||||
impl BrokenithmJob {
|
||||
pub fn new(state: &FullState, ground_only: &bool, led_enabled: &bool) -> Self {
|
||||
pub fn new(state: &SliderState, ground_only: &bool, led_enabled: &bool) -> Self {
|
||||
Self {
|
||||
state: state.clone(),
|
||||
ground_only: *ground_only,
|
||||
|
@ -8,17 +8,17 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
controller_state::{ControllerState, FullState, LedState},
|
||||
shared::{
|
||||
utils::{Buffer, ShimError},
|
||||
worker::ThreadJob,
|
||||
},
|
||||
state::{SliderInput, SliderLights, SliderState},
|
||||
};
|
||||
|
||||
use super::config::HardwareSpec;
|
||||
|
||||
type HidReadCallback = fn(&Buffer, &mut ControllerState) -> ();
|
||||
type HidLedCallback = fn(&mut Buffer, &LedState) -> ();
|
||||
type HidReadCallback = fn(&Buffer, &mut SliderInput) -> ();
|
||||
type HidLedCallback = fn(&mut Buffer, &SliderLights) -> ();
|
||||
|
||||
enum WriteType {
|
||||
Bulk,
|
||||
@ -26,7 +26,7 @@ enum WriteType {
|
||||
}
|
||||
|
||||
pub struct HidDeviceJob {
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
|
||||
vid: u16,
|
||||
pid: u16,
|
||||
@ -46,7 +46,7 @@ pub struct HidDeviceJob {
|
||||
|
||||
impl HidDeviceJob {
|
||||
fn new(
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
vid: u16,
|
||||
pid: u16,
|
||||
read_endpoint: u8,
|
||||
@ -71,7 +71,7 @@ impl HidDeviceJob {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_config(state: &FullState, spec: &HardwareSpec) -> Self {
|
||||
pub fn from_config(state: &SliderState, spec: &HardwareSpec) -> Self {
|
||||
match spec {
|
||||
HardwareSpec::TasollerOne => Self::new(
|
||||
state.clone(),
|
||||
@ -79,7 +79,7 @@ impl HidDeviceJob {
|
||||
0x2333,
|
||||
0x84,
|
||||
0x03,
|
||||
|buf, controller_state| {
|
||||
|buf, input| {
|
||||
if buf.len != 11 {
|
||||
return;
|
||||
}
|
||||
@ -90,15 +90,15 @@ impl HidDeviceJob {
|
||||
.flat_map(|x| (0..8).map(move |i| ((x) >> i) & 1))
|
||||
.collect();
|
||||
for i in 0..32 {
|
||||
controller_state.ground_state[i] = bits[34 + i] * 255;
|
||||
input.ground[i] = bits[34 + i] * 255;
|
||||
}
|
||||
controller_state.flip_vert();
|
||||
input.flip_vert();
|
||||
|
||||
controller_state.air_state.copy_from_slice(&bits[28..34]);
|
||||
controller_state.extra_state[0..2].copy_from_slice(&bits[26..28]);
|
||||
input.air.copy_from_slice(&bits[28..34]);
|
||||
input.extra[0..2].copy_from_slice(&bits[26..28]);
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
|buf, lights| {
|
||||
buf.len = 240;
|
||||
buf.data[0] = 'B' as u8;
|
||||
buf.data[1] = 'L' as u8;
|
||||
@ -106,7 +106,7 @@ impl HidDeviceJob {
|
||||
for (buf_chunk, state_chunk) in buf.data[3..96]
|
||||
.chunks_mut(3)
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
.zip(lights.ground.chunks(3).rev())
|
||||
{
|
||||
buf_chunk[0] = state_chunk[1];
|
||||
buf_chunk[1] = state_chunk[0];
|
||||
@ -121,22 +121,20 @@ impl HidDeviceJob {
|
||||
0x2333,
|
||||
0x84,
|
||||
0x03,
|
||||
|buf, controller_state| {
|
||||
|buf, input| {
|
||||
if buf.len != 36 {
|
||||
return;
|
||||
}
|
||||
|
||||
controller_state
|
||||
.ground_state
|
||||
.copy_from_slice(&buf.data[4..36]);
|
||||
controller_state.flip_vert();
|
||||
input.ground.copy_from_slice(&buf.data[4..36]);
|
||||
input.flip_vert();
|
||||
|
||||
let bits: Vec<u8> = (0..8).map(|x| (buf.data[3] >> x) & 1).collect();
|
||||
controller_state.air_state.copy_from_slice(&bits[0..6]);
|
||||
controller_state.extra_state[0..2].copy_from_slice(&bits[6..8]);
|
||||
input.air.copy_from_slice(&bits[0..6]);
|
||||
input.extra[0..2].copy_from_slice(&bits[6..8]);
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
|buf, lights| {
|
||||
buf.len = 240;
|
||||
buf.data[0] = 'B' as u8;
|
||||
buf.data[1] = 'L' as u8;
|
||||
@ -144,7 +142,7 @@ impl HidDeviceJob {
|
||||
for (buf_chunk, state_chunk) in buf.data[3..96]
|
||||
.chunks_mut(3)
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
.zip(lights.ground.chunks(3).rev())
|
||||
{
|
||||
buf_chunk[0] = state_chunk[1];
|
||||
buf_chunk[1] = state_chunk[0];
|
||||
@ -159,29 +157,27 @@ impl HidDeviceJob {
|
||||
0x2001,
|
||||
0x81,
|
||||
0x02,
|
||||
|buf, controller_state| {
|
||||
|buf, input| {
|
||||
if buf.len != 34 {
|
||||
return;
|
||||
}
|
||||
|
||||
controller_state
|
||||
.ground_state
|
||||
.copy_from_slice(&buf.data[2..34]);
|
||||
input.ground.copy_from_slice(&buf.data[2..34]);
|
||||
for i in 0..6 {
|
||||
controller_state.air_state[i ^ 1] = (buf.data[0] >> i) & 1;
|
||||
input.air[i ^ 1] = (buf.data[0] >> i) & 1;
|
||||
}
|
||||
for i in 0..3 {
|
||||
controller_state.extra_state[2 - i] = (buf.data[1] >> i) & 1;
|
||||
input.extra[2 - i] = (buf.data[1] >> i) & 1;
|
||||
}
|
||||
},
|
||||
WriteType::Interrupt,
|
||||
|buf, led_state| {
|
||||
|buf, lights| {
|
||||
buf.len = 31 * 2;
|
||||
for (buf_chunk, state_chunk) in buf
|
||||
.data
|
||||
.chunks_mut(2)
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
.zip(lights.ground.chunks(3).rev())
|
||||
{
|
||||
buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3);
|
||||
buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5);
|
||||
@ -248,8 +244,8 @@ impl ThreadJob for HidDeviceJob {
|
||||
// if self.read_buf.len != 0 {
|
||||
if (self.read_buf.len != 0) && (self.read_buf.slice() != self.last_read_buf.slice()) {
|
||||
work = true;
|
||||
let mut controller_state_handle = self.state.controller_state.lock();
|
||||
(self.read_callback)(&self.read_buf, controller_state_handle.deref_mut());
|
||||
let mut input_handle = self.state.input.lock();
|
||||
(self.read_callback)(&self.read_buf, input_handle.deref_mut());
|
||||
swap(&mut self.read_buf, &mut self.last_read_buf);
|
||||
}
|
||||
}
|
||||
@ -257,10 +253,10 @@ impl ThreadJob for HidDeviceJob {
|
||||
// Led loop
|
||||
{
|
||||
{
|
||||
let mut led_state_handle = self.state.led_state.lock();
|
||||
if led_state_handle.dirty {
|
||||
(self.led_callback)(&mut self.led_buf, led_state_handle.deref());
|
||||
led_state_handle.dirty = false;
|
||||
let mut lights_handle = self.state.lights.lock();
|
||||
if lights_handle.dirty {
|
||||
(self.led_callback)(&mut self.led_buf, lights_handle.deref());
|
||||
lights_handle.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
#![feature(more_qualified_paths)]
|
||||
|
||||
mod config;
|
||||
mod controller_state;
|
||||
mod shared;
|
||||
mod state;
|
||||
|
||||
mod device;
|
||||
mod lighting;
|
||||
|
@ -9,14 +9,14 @@ use std::{
|
||||
use tokio::time::{interval, Interval};
|
||||
|
||||
use crate::{
|
||||
controller_state::{FullState, LedState},
|
||||
shared::{utils::Buffer, voltex::VoltexState, worker::AsyncJob},
|
||||
state::{SliderLights, SliderState},
|
||||
};
|
||||
|
||||
use super::config::{LedMode, ReactiveLayout};
|
||||
|
||||
pub struct LedJob {
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
mode: LedMode,
|
||||
serial_port: Option<Box<dyn SerialPort>>,
|
||||
started: Instant,
|
||||
@ -24,7 +24,7 @@ pub struct LedJob {
|
||||
}
|
||||
|
||||
impl LedJob {
|
||||
pub fn new(state: &FullState, mode: &LedMode) -> Self {
|
||||
pub fn new(state: &SliderState, mode: &LedMode) -> Self {
|
||||
Self {
|
||||
state: state.clone(),
|
||||
mode: mode.clone(),
|
||||
@ -36,26 +36,26 @@ impl LedJob {
|
||||
|
||||
fn calc_lights(
|
||||
&self,
|
||||
flat_controller_state: Option<&Vec<bool>>,
|
||||
flat_input: Option<&Vec<bool>>,
|
||||
serial_buffer: Option<&Buffer>,
|
||||
led_state: &mut LedState,
|
||||
lights: &mut SliderLights,
|
||||
) {
|
||||
match self.mode {
|
||||
LedMode::Reactive { layout, .. } => {
|
||||
let flat_controller_state = flat_controller_state.unwrap();
|
||||
let flat_input = flat_input.unwrap();
|
||||
|
||||
match layout {
|
||||
ReactiveLayout::Even { splits } => {
|
||||
let buttons_per_split = 32 / splits;
|
||||
|
||||
let banks: Vec<bool> = flat_controller_state
|
||||
let banks: Vec<bool> = flat_input
|
||||
.chunks(32 / splits)
|
||||
.take(splits)
|
||||
.map(|x| x.contains(&true))
|
||||
.collect();
|
||||
|
||||
for idx in 0..31 {
|
||||
led_state.paint(
|
||||
lights.paint(
|
||||
idx,
|
||||
match (idx + 1) % buttons_per_split {
|
||||
0 => &[255, 0, 255],
|
||||
@ -68,49 +68,49 @@ impl LedJob {
|
||||
}
|
||||
}
|
||||
ReactiveLayout::Voltex => {
|
||||
led_state.led_state.fill(0);
|
||||
lights.ground.fill(0);
|
||||
|
||||
// Fixed
|
||||
led_state.paint(3, &[10, 100, 180]);
|
||||
lights.paint(3, &[10, 100, 180]);
|
||||
for idx in 0..5 {
|
||||
led_state.paint(7 + idx * 4, &[64, 64, 64]);
|
||||
lights.paint(7 + idx * 4, &[64, 64, 64]);
|
||||
}
|
||||
led_state.paint(27, &[180, 10, 110]);
|
||||
lights.paint(27, &[180, 10, 110]);
|
||||
|
||||
let voltex_state = VoltexState::from_flat(flat_controller_state);
|
||||
let voltex_input = VoltexState::from_flat(flat_input);
|
||||
|
||||
// Left laser
|
||||
for (idx, state) in voltex_state.laser[0..2].iter().enumerate() {
|
||||
for (idx, state) in voltex_input.laser[0..2].iter().enumerate() {
|
||||
if *state {
|
||||
led_state.paint(0 + idx * 4, &[70, 230, 250]);
|
||||
led_state.paint(1 + idx * 4, &[70, 230, 250]);
|
||||
led_state.paint(2 + idx * 4, &[70, 230, 250]);
|
||||
lights.paint(0 + idx * 4, &[70, 230, 250]);
|
||||
lights.paint(1 + idx * 4, &[70, 230, 250]);
|
||||
lights.paint(2 + idx * 4, &[70, 230, 250]);
|
||||
}
|
||||
}
|
||||
|
||||
// Right laser
|
||||
for (idx, state) in voltex_state.laser[2..4].iter().enumerate() {
|
||||
for (idx, state) in voltex_input.laser[2..4].iter().enumerate() {
|
||||
if *state {
|
||||
led_state.paint(24 + idx * 4, &[250, 60, 200]);
|
||||
led_state.paint(25 + idx * 4, &[255, 60, 200]);
|
||||
led_state.paint(26 + idx * 4, &[255, 60, 200]);
|
||||
lights.paint(24 + idx * 4, &[250, 60, 200]);
|
||||
lights.paint(25 + idx * 4, &[255, 60, 200]);
|
||||
lights.paint(26 + idx * 4, &[255, 60, 200]);
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
for (idx, state) in voltex_state.bt.iter().enumerate() {
|
||||
for (idx, state) in voltex_input.bt.iter().enumerate() {
|
||||
if *state {
|
||||
led_state.paint(8 + idx * 4, &[255, 255, 255]);
|
||||
led_state.paint(10 + idx * 4, &[255, 255, 255]);
|
||||
lights.paint(8 + idx * 4, &[255, 255, 255]);
|
||||
lights.paint(10 + idx * 4, &[255, 255, 255]);
|
||||
}
|
||||
}
|
||||
|
||||
// Fx
|
||||
for (idx, state) in voltex_state.fx.iter().enumerate() {
|
||||
for (idx, state) in voltex_input.fx.iter().enumerate() {
|
||||
if *state {
|
||||
led_state.paint(9 + idx * 8, &[250, 100, 30]);
|
||||
led_state.paint(11 + idx * 8, &[250, 100, 30]);
|
||||
led_state.paint(13 + idx * 8, &[250, 100, 30]);
|
||||
lights.paint(9 + idx * 8, &[250, 100, 30]);
|
||||
lights.paint(11 + idx * 8, &[250, 100, 30]);
|
||||
lights.paint(13 + idx * 8, &[250, 100, 30]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,7 +125,7 @@ impl LedJob {
|
||||
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]);
|
||||
lights.paint(idx, &[color.red, color.green, color.blue]);
|
||||
}
|
||||
}
|
||||
LedMode::Serial { .. } => {
|
||||
@ -142,16 +142,15 @@ impl LedJob {
|
||||
.rev()
|
||||
.enumerate()
|
||||
{
|
||||
led_state.paint(idx, &[(*buf_chunk)[1], (*buf_chunk)[2], (*buf_chunk)[0]]);
|
||||
lights.paint(idx, &[(*buf_chunk)[1], (*buf_chunk)[2], (*buf_chunk)[0]]);
|
||||
}
|
||||
// println!("leds {:?}", led_state.led_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("Not implemented"),
|
||||
}
|
||||
|
||||
led_state.dirty = true;
|
||||
lights.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,14 +182,14 @@ impl AsyncJob for LedJob {
|
||||
}
|
||||
|
||||
async fn tick(&mut self) -> bool {
|
||||
let mut flat_controller_state: Option<Vec<bool>> = None;
|
||||
let mut flat_input: Option<Vec<bool>> = None;
|
||||
let mut serial_buffer: Option<Buffer> = None;
|
||||
|
||||
// Do the IO here
|
||||
match self.mode {
|
||||
LedMode::Reactive { sensitivity, .. } => {
|
||||
let controller_state_handle = self.state.controller_state.lock();
|
||||
flat_controller_state = Some(controller_state_handle.to_flat(&sensitivity));
|
||||
let input_handle = self.state.input.lock();
|
||||
flat_input = Some(input_handle.to_flat(&sensitivity));
|
||||
}
|
||||
LedMode::Serial { .. } => {
|
||||
if let Some(serial_port) = self.serial_port.as_mut() {
|
||||
@ -218,15 +217,13 @@ impl AsyncJob for LedJob {
|
||||
|
||||
// Then calculate and transfer
|
||||
{
|
||||
let mut led_state_handle = self.state.led_state.lock();
|
||||
let mut lights_handle = self.state.lights.lock();
|
||||
self.calc_lights(
|
||||
flat_controller_state.as_ref(),
|
||||
flat_input.as_ref(),
|
||||
serial_buffer.as_ref(),
|
||||
led_state_handle.deref_mut(),
|
||||
lights_handle.deref_mut(),
|
||||
);
|
||||
}
|
||||
// thread::sleep(Duration::from_millis(30));
|
||||
// spin_sleep::sleep(Duration::from_micros(33333));
|
||||
self.timer.tick().await;
|
||||
|
||||
true
|
||||
|
@ -9,10 +9,10 @@ use tokio::{
|
||||
sync::{mpsc, oneshot},
|
||||
};
|
||||
|
||||
use crate::{config::Config, context::Context, controller_state::FullState};
|
||||
use crate::{config::Config, context::Context, state::SliderState};
|
||||
|
||||
pub struct Manager {
|
||||
state: Arc<Mutex<Option<FullState>>>,
|
||||
state: Arc<Mutex<Option<SliderState>>>,
|
||||
context: Arc<Mutex<Option<Context>>>,
|
||||
join_handle: Option<JoinHandle<()>>,
|
||||
tx_config: mpsc::UnboundedSender<Config>,
|
||||
@ -81,7 +81,7 @@ impl Manager {
|
||||
self.tx_config.send(config).unwrap();
|
||||
}
|
||||
|
||||
pub fn try_get_state(&self) -> Option<FullState> {
|
||||
pub fn try_get_state(&self) -> Option<SliderState> {
|
||||
let state_handle = self.state.lock();
|
||||
state_handle.as_ref().map(|x| x.clone())
|
||||
}
|
||||
|
@ -95,8 +95,8 @@ impl GamepadOutput {
|
||||
}
|
||||
|
||||
impl OutputHandler for GamepadOutput {
|
||||
fn tick(&mut self, flat_controller_state: &Vec<bool>) -> bool {
|
||||
let voltex_state = VoltexState::from_flat(flat_controller_state);
|
||||
fn tick(&mut self, flat_input: &Vec<bool>) -> bool {
|
||||
let voltex_state = VoltexState::from_flat(flat_input);
|
||||
|
||||
let buttons = voltex_state
|
||||
.bt
|
||||
@ -123,15 +123,13 @@ impl OutputHandler for GamepadOutput {
|
||||
});
|
||||
|
||||
let lx = self.left_wind.update(
|
||||
voltex_state.laser[0] || (self.use_air && flat_controller_state[32]),
|
||||
voltex_state.laser[1]
|
||||
|| (self.use_air && (flat_controller_state[33] || flat_controller_state[34])),
|
||||
voltex_state.laser[0] || (self.use_air && flat_input[32]),
|
||||
voltex_state.laser[1] || (self.use_air && (flat_input[33] || flat_input[34])),
|
||||
) * 20000;
|
||||
|
||||
let rx = self.right_wind.update(
|
||||
voltex_state.laser[2]
|
||||
|| (self.use_air && (flat_controller_state[35] || flat_controller_state[36])),
|
||||
voltex_state.laser[3] || (self.use_air && flat_controller_state[37]),
|
||||
voltex_state.laser[2] || (self.use_air && (flat_input[35] || flat_input[36])),
|
||||
voltex_state.laser[3] || (self.use_air && flat_input[37]),
|
||||
) * 20000;
|
||||
|
||||
let mut dirty = false;
|
||||
|
@ -187,9 +187,9 @@ impl KeyboardOutput {
|
||||
}
|
||||
|
||||
impl OutputHandler for KeyboardOutput {
|
||||
fn tick(&mut self, flat_controller_state: &Vec<bool>) -> bool {
|
||||
fn tick(&mut self, flat_input: &Vec<bool>) -> bool {
|
||||
self.next_keys.fill(false);
|
||||
for (idx, x) in flat_controller_state.iter().enumerate() {
|
||||
for (idx, x) in flat_input.iter().enumerate() {
|
||||
if *x {
|
||||
self.next_keys[self.ground_to_idx[idx]] = true;
|
||||
}
|
||||
|
@ -3,22 +3,17 @@ use log::error;
|
||||
use std::time::Duration;
|
||||
use tokio::time::{interval, Interval};
|
||||
|
||||
// use crate::slider_io::{
|
||||
// config::OutputMode, controller_state::FullState, gamepad::GamepadOutput,
|
||||
// keyboard::KeyboardOutput, worker::AsyncJob,
|
||||
// };
|
||||
|
||||
use crate::{controller_state::FullState, shared::worker::AsyncJob};
|
||||
use crate::{shared::worker::AsyncJob, state::SliderState};
|
||||
|
||||
use super::{config::OutputMode, gamepad::GamepadOutput, keyboard::KeyboardOutput};
|
||||
|
||||
pub trait OutputHandler: Send {
|
||||
fn tick(&mut self, flat_controller_state: &Vec<bool>) -> bool;
|
||||
fn tick(&mut self, flat_input: &Vec<bool>) -> bool;
|
||||
fn reset(&mut self);
|
||||
}
|
||||
|
||||
pub struct OutputJob {
|
||||
state: FullState,
|
||||
state: SliderState,
|
||||
mode: OutputMode,
|
||||
sensitivity: u8,
|
||||
handler: Option<Box<dyn OutputHandler>>,
|
||||
@ -26,7 +21,7 @@ pub struct OutputJob {
|
||||
}
|
||||
|
||||
impl OutputJob {
|
||||
pub fn new(state: &FullState, mode: &OutputMode) -> Self {
|
||||
pub fn new(state: &SliderState, mode: &OutputMode) -> Self {
|
||||
Self {
|
||||
state: state.clone(),
|
||||
mode: mode.clone(),
|
||||
@ -77,14 +72,13 @@ impl AsyncJob for OutputJob {
|
||||
}
|
||||
|
||||
async fn tick(&mut self) -> bool {
|
||||
let flat_controller_state: Vec<bool>;
|
||||
{
|
||||
let controller_state_handle = self.state.controller_state.lock();
|
||||
flat_controller_state = controller_state_handle.to_flat(&self.sensitivity);
|
||||
}
|
||||
let flat_input = {
|
||||
let input_handle = self.state.input.lock();
|
||||
input_handle.to_flat(&self.sensitivity)
|
||||
};
|
||||
|
||||
if let Some(handler) = self.handler.as_mut() {
|
||||
handler.tick(&flat_controller_state);
|
||||
handler.tick(&flat_input);
|
||||
}
|
||||
self.timer.tick().await;
|
||||
|
||||
|
@ -6,7 +6,7 @@ pub struct VoltexState {
|
||||
}
|
||||
|
||||
impl VoltexState {
|
||||
pub fn from_flat(flat_controller_state: &Vec<bool>) -> Self {
|
||||
pub fn from_flat(flat_input: &Vec<bool>) -> Self {
|
||||
let mut voltex_state = Self {
|
||||
laser: [false; 4],
|
||||
bt: [false; 4],
|
||||
@ -14,24 +14,24 @@ impl VoltexState {
|
||||
extra: [false; 3],
|
||||
};
|
||||
|
||||
voltex_state.laser[0] = flat_controller_state[0..4].contains(&true);
|
||||
voltex_state.laser[1] = flat_controller_state[4..8].contains(&true);
|
||||
voltex_state.laser[2] = flat_controller_state[24..28].contains(&true);
|
||||
voltex_state.laser[3] = flat_controller_state[28..32].contains(&true);
|
||||
voltex_state.laser[0] = flat_input[0..4].contains(&true);
|
||||
voltex_state.laser[1] = flat_input[4..8].contains(&true);
|
||||
voltex_state.laser[2] = flat_input[24..28].contains(&true);
|
||||
voltex_state.laser[3] = flat_input[28..32].contains(&true);
|
||||
|
||||
for i in 0..4 {
|
||||
voltex_state.bt[i] = flat_controller_state[9 + i * 4] || flat_controller_state[11 + i * 4];
|
||||
voltex_state.bt[i] = flat_input[9 + i * 4] || flat_input[11 + i * 4];
|
||||
}
|
||||
|
||||
for i in 0..2 {
|
||||
voltex_state.fx[i] = flat_controller_state[8 + i * 8]
|
||||
|| flat_controller_state[10 + i * 8]
|
||||
|| flat_controller_state[12 + i * 8]
|
||||
|| flat_controller_state[14 + i * 8];
|
||||
voltex_state.fx[i] = flat_input[8 + i * 8]
|
||||
|| flat_input[10 + i * 8]
|
||||
|| flat_input[12 + i * 8]
|
||||
|| flat_input[14 + i * 8];
|
||||
}
|
||||
|
||||
for i in 0..3 {
|
||||
voltex_state.extra[i] = flat_controller_state[38 + i];
|
||||
voltex_state.extra[i] = flat_input[38 + i];
|
||||
}
|
||||
|
||||
voltex_state
|
||||
|
@ -3,28 +3,28 @@ use std::{sync::Arc, time::Instant};
|
||||
|
||||
/// Stores the input state of a slider controller, including ground touch pads,
|
||||
/// air strings and extra buttons.
|
||||
pub struct ControllerState {
|
||||
pub struct SliderInput {
|
||||
/// Represents touch pressure in 32 touch pads in a 2 tall and 16 wide grid.
|
||||
/// Each pressur is in a `u8` from 0 to 255. Pads are represented in order of
|
||||
/// bottom left, then top left, then flows from left to right.
|
||||
pub ground_state: [u8; 32],
|
||||
pub ground: [u8; 32],
|
||||
|
||||
/// Represents air string state in 6 pads starting from bottom to top. 0 means
|
||||
/// uninterrupted, 1 means interrupted.
|
||||
pub air_state: [u8; 6],
|
||||
pub air: [u8; 6],
|
||||
|
||||
/// Represents extra button state, usually used for coin/test/card entry
|
||||
/// functions.
|
||||
pub extra_state: [u8; 3],
|
||||
pub extra: [u8; 3],
|
||||
}
|
||||
|
||||
impl ControllerState {
|
||||
impl SliderInput {
|
||||
/// Make a blank input state.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ground_state: [0; 32],
|
||||
air_state: [0; 6],
|
||||
extra_state: [0; 3],
|
||||
ground: [0; 32],
|
||||
air: [0; 6],
|
||||
extra: [0; 3],
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,16 +32,10 @@ impl ControllerState {
|
||||
/// visualisation.
|
||||
pub fn to_flat(&self, sensitivity: &u8) -> Vec<bool> {
|
||||
self
|
||||
.ground_state
|
||||
.ground
|
||||
.iter()
|
||||
.map(|x| x >= sensitivity)
|
||||
.chain(
|
||||
self
|
||||
.air_state
|
||||
.iter()
|
||||
.chain(self.extra_state.iter())
|
||||
.map(|x| x > &0),
|
||||
)
|
||||
.chain(self.air.iter().chain(self.extra.iter()).map(|x| x > &0))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -50,16 +44,16 @@ impl ControllerState {
|
||||
/// botton left that is used internally).
|
||||
pub fn flip_vert(&mut self) {
|
||||
for i in 0..16 {
|
||||
self.ground_state.swap(i * 2, i * 2 + 1);
|
||||
self.ground.swap(i * 2, i * 2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stores the lighting state of a slider controller.
|
||||
pub struct LedState {
|
||||
pub struct SliderLights {
|
||||
/// Represents the RGB pixel values of the slider controller from left to
|
||||
/// right. Alternates between 16 touch pad pixels and 15 divider pixels.
|
||||
pub led_state: [u8; 3 * 31],
|
||||
pub ground: [u8; 3 * 31],
|
||||
|
||||
/// Internal dirty flag used to indicate that new lighting data is available.
|
||||
pub dirty: bool,
|
||||
@ -68,11 +62,11 @@ pub struct LedState {
|
||||
pub start: Instant,
|
||||
}
|
||||
|
||||
impl LedState {
|
||||
impl SliderLights {
|
||||
/// Make a blank lighting state.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
led_state: [0; 3 * 31],
|
||||
ground: [0; 3 * 31],
|
||||
dirty: false,
|
||||
start: Instant::now(),
|
||||
}
|
||||
@ -80,27 +74,27 @@ impl LedState {
|
||||
|
||||
/// Apply a RGB color to some pixel in the lighting state.
|
||||
pub fn paint(&mut self, idx: usize, color: &[u8; 3]) {
|
||||
self.led_state[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
self.ground[3 * idx..3 * (idx + 1)].copy_from_slice(color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores data required for a single slider controller. Data and lighting
|
||||
/// states are stored seperately in their own `Arc<Mutex<T>>` so that they can
|
||||
/// be locked independently.
|
||||
pub struct FullState {
|
||||
pub struct SliderState {
|
||||
/// Input data for the slider controller.
|
||||
pub controller_state: Arc<Mutex<ControllerState>>,
|
||||
pub input: Arc<Mutex<SliderInput>>,
|
||||
|
||||
/// Lighting data for the slider controller.
|
||||
pub led_state: Arc<Mutex<LedState>>,
|
||||
pub lights: Arc<Mutex<SliderLights>>,
|
||||
}
|
||||
|
||||
impl FullState {
|
||||
impl SliderState {
|
||||
/// Creates a blank slider controller state
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
controller_state: Arc::new(Mutex::new(ControllerState::new())),
|
||||
led_state: Arc::new(Mutex::new(LedState::new())),
|
||||
input: Arc::new(Mutex::new(SliderInput::new())),
|
||||
lights: Arc::new(Mutex::new(SliderLights::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,25 +103,25 @@ impl FullState {
|
||||
pub fn snapshot(&self) -> Vec<u8> {
|
||||
let mut buf: Vec<u8> = vec![];
|
||||
{
|
||||
let controller_state_handle = self.controller_state.lock();
|
||||
buf.extend(controller_state_handle.ground_state);
|
||||
buf.extend(controller_state_handle.air_state);
|
||||
buf.extend(controller_state_handle.extra_state);
|
||||
let input_handle = self.input.lock();
|
||||
buf.extend(input_handle.ground);
|
||||
buf.extend(input_handle.air);
|
||||
buf.extend(input_handle.extra);
|
||||
};
|
||||
{
|
||||
let led_state_handle = self.led_state.lock();
|
||||
buf.extend(led_state_handle.led_state);
|
||||
let lights_handle = self.lights.lock();
|
||||
buf.extend(lights_handle.ground);
|
||||
};
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FullState {
|
||||
impl Clone for SliderState {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
controller_state: Arc::clone(&self.controller_state),
|
||||
led_state: Arc::clone(&self.led_state),
|
||||
input: Arc::clone(&self.input),
|
||||
lights: Arc::clone(&self.lights),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user