From a122fde6dad07685561dc99f65095232e90bf8bb Mon Sep 17 00:00:00 2001 From: Avii Date: Mon, 9 Feb 2026 12:13:19 +0100 Subject: [PATCH] I/O --- src/g13/joystick/axis.rs | 2 +- src/g13/joystick/button.rs | 4 +- src/g13/mod.rs | 119 +++++++++++++++++++++++++++++++++++-- src/main.rs | 28 ++++++--- 4 files changed, 136 insertions(+), 17 deletions(-) diff --git a/src/g13/joystick/axis.rs b/src/g13/joystick/axis.rs index 379f55f..0e2e6ed 100644 --- a/src/g13/joystick/axis.rs +++ b/src/g13/joystick/axis.rs @@ -1,6 +1,6 @@ use std::slice; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Axis { X, Y, diff --git a/src/g13/joystick/button.rs b/src/g13/joystick/button.rs index 034a1f2..0ccdbef 100644 --- a/src/g13/joystick/button.rs +++ b/src/g13/joystick/button.rs @@ -1,6 +1,6 @@ use std::slice; -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Button { Back, Screen1, @@ -88,7 +88,7 @@ impl Button { } } - pub(super) fn all_buttons() -> slice::Iter<'static, Self> { + pub fn all_buttons() -> slice::Iter<'static, Self> { use Button::*; [ Back, Screen1, Screen2, Screen3, Screen4, Light, M1, M2, M3, MR, G1, G2, G3, G4, G5, G6, G7, G8, G9, G10, diff --git a/src/g13/mod.rs b/src/g13/mod.rs index 8a1d581..5e0c78a 100644 --- a/src/g13/mod.rs +++ b/src/g13/mod.rs @@ -1,7 +1,9 @@ pub mod joystick; use std::{ + collections::HashMap, io::{Read, Write}, + sync::Arc, time::Duration, }; @@ -14,9 +16,12 @@ use nusb::{ Interface, transfer::{ControlOut, ControlType, In, Interrupt, Out, Recipient}, }; +use tokio::sync::RwLock; use crate::g13::joystick::{Axis, Button, Joystick}; +const STICK_DEADZONE: i32 = 30; + pub const G13_LCD_COLUMNS: i32 = 160; pub const G13_LCD_ROWS: i32 = 43; pub const G13_LCD_BYTES_PER_ROW: i32 = G13_LCD_COLUMNS / 8; @@ -27,6 +32,66 @@ pub struct G13 { interface: Interface, joystick: Joystick, img_buffer: [u8; G13_LCD_BUF_SIZE as usize + 8], + pub state: State, +} + +#[derive(Debug, Clone)] +pub struct State { + x: Arc>, + y: Arc>, + buttons: Arc>>, +} + +impl Default for State { + fn default() -> Self { + let mut buttons = HashMap::new(); + for button in Button::all_buttons() { + buttons.insert(button.clone(), false); + } + + Self { + x: Arc::new(RwLock::new(0)), + y: Arc::new(RwLock::new(0)), + buttons: Arc::new(RwLock::new(buttons)), + } + } +} + +#[allow(unused)] +impl State { + pub async fn get_x(&self) -> f64 { + let mut value = *self.x.read().await; + if value < STICK_DEADZONE && value > -STICK_DEADZONE { + value = 0; + } + + value as f64 / 512.0 + } + + pub async fn get_y(&self) -> f64 { + let mut value = *self.y.read().await; + if value < STICK_DEADZONE && value > -STICK_DEADZONE { + value = 0; + } + + value as f64 / 512.0 + } + + pub async fn is_down(&self, button: Button) -> bool { + self.buttons.read().await[&button] + } + + async fn set_x(&self, value: i32) { + *self.x.write().await = value; + } + + async fn set_y(&self, value: i32) { + *self.y.write().await = value; + } + + async fn set_button(&self, button: Button, value: bool) { + self.buttons.write().await.insert(button, value); + } } impl G13 { @@ -65,6 +130,7 @@ impl G13 { interface, joystick, img_buffer, + state: Default::default(), }) } @@ -73,52 +139,91 @@ impl G13 { let mut buf = [0; 8]; reader.read_exact(&mut buf)?; - self.joystick - .move_axis(Axis::X, (((buf[1] as f64) / 256.0 * 1024.0) - 512.0) as i32)?; - self.joystick - .move_axis(Axis::Y, (((buf[2] as f64) / 256.0 * 1024.0) - 512.0) as i32)?; + let x = (((buf[1] as f64) / 256.0 * 1024.0) - 512.0) as i32; + let y = (((buf[2] as f64) / 256.0 * 1024.0) - 512.0) as i32; + + self.state.set_x(x).await; + self.state.set_y(y).await; + + self.joystick.move_axis(Axis::X, x)?; + self.joystick.move_axis(Axis::Y, y)?; // the right most bit of the 7th byte is the back button self.joystick.button_press(Button::Back, buf[6] & 0b00000001 != 0)?; + self.state.set_button(Button::Back, buf[6] & 0b00000001 != 0).await; self.joystick.button_press(Button::Screen1, buf[6] & 0b00000010 != 0)?; + self.state.set_button(Button::Screen1, buf[6] & 0b00000010 != 0).await; self.joystick.button_press(Button::Screen2, buf[6] & 0b00000100 != 0)?; + self.state.set_button(Button::Screen2, buf[6] & 0b00000100 != 0).await; self.joystick.button_press(Button::Screen3, buf[6] & 0b00001000 != 0)?; + self.state.set_button(Button::Screen3, buf[6] & 0b00001000 != 0).await; self.joystick.button_press(Button::Screen4, buf[6] & 0b00010000 != 0)?; + self.state.set_button(Button::Screen4, buf[6] & 0b00010000 != 0).await; self.joystick.button_press(Button::Light, buf[7] & 0b0100000 != 0)?; + self.state.set_button(Button::Light, buf[7] & 0b0100000 != 0).await; self.joystick.button_press(Button::M1, buf[6] & 0b00100000 != 0)?; + self.state.set_button(Button::M1, buf[6] & 0b00100000 != 0).await; self.joystick.button_press(Button::M2, buf[6] & 0b01000000 != 0)?; + self.state.set_button(Button::M2, buf[6] & 0b01000000 != 0).await; self.joystick.button_press(Button::M3, buf[6] & 0b10000000 != 0)?; + self.state.set_button(Button::M3, buf[6] & 0b10000000 != 0).await; self.joystick.button_press(Button::MR, buf[7] & 0b00000001 != 0)?; + self.state.set_button(Button::MR, buf[7] & 0b00000001 != 0).await; self.joystick.button_press(Button::G1, buf[3] & 0b00000001 != 0)?; + self.state.set_button(Button::G1, buf[3] & 0b00000001 != 0).await; self.joystick.button_press(Button::G2, buf[3] & 0b00000010 != 0)?; + self.state.set_button(Button::G2, buf[3] & 0b00000010 != 0).await; self.joystick.button_press(Button::G3, buf[3] & 0b00000100 != 0)?; + self.state.set_button(Button::G3, buf[3] & 0b00000100 != 0).await; self.joystick.button_press(Button::G4, buf[3] & 0b00001000 != 0)?; + self.state.set_button(Button::G4, buf[3] & 0b00001000 != 0).await; self.joystick.button_press(Button::G5, buf[3] & 0b00010000 != 0)?; + self.state.set_button(Button::G5, buf[3] & 0b00010000 != 0).await; self.joystick.button_press(Button::G6, buf[3] & 0b00100000 != 0)?; + self.state.set_button(Button::G6, buf[3] & 0b00100000 != 0).await; self.joystick.button_press(Button::G7, buf[3] & 0b01000000 != 0)?; + self.state.set_button(Button::G7, buf[3] & 0b01000000 != 0).await; self.joystick.button_press(Button::G8, buf[3] & 0b10000000 != 0)?; + self.state.set_button(Button::G8, buf[3] & 0b10000000 != 0).await; self.joystick.button_press(Button::G9, buf[4] & 0b00000001 != 0)?; + self.state.set_button(Button::G9, buf[4] & 0b00000001 != 0).await; self.joystick.button_press(Button::G10, buf[4] & 0b00000010 != 0)?; + self.state.set_button(Button::G10, buf[4] & 0b00000010 != 0).await; self.joystick.button_press(Button::G11, buf[4] & 0b00000100 != 0)?; + self.state.set_button(Button::G11, buf[4] & 0b00000100 != 0).await; self.joystick.button_press(Button::G12, buf[4] & 0b00001000 != 0)?; + self.state.set_button(Button::G12, buf[4] & 0b00001000 != 0).await; self.joystick.button_press(Button::G13, buf[4] & 0b00010000 != 0)?; + self.state.set_button(Button::G13, buf[4] & 0b00010000 != 0).await; self.joystick.button_press(Button::G14, buf[4] & 0b00100000 != 0)?; + self.state.set_button(Button::G14, buf[4] & 0b00100000 != 0).await; self.joystick.button_press(Button::G15, buf[4] & 0b01000000 != 0)?; + self.state.set_button(Button::G15, buf[4] & 0b01000000 != 0).await; self.joystick.button_press(Button::G16, buf[4] & 0b10000000 != 0)?; + self.state.set_button(Button::G16, buf[4] & 0b10000000 != 0).await; self.joystick.button_press(Button::G17, buf[5] & 0b00000001 != 0)?; + self.state.set_button(Button::G17, buf[5] & 0b00000001 != 0).await; self.joystick.button_press(Button::G18, buf[5] & 0b00000010 != 0)?; + self.state.set_button(Button::G18, buf[5] & 0b00000010 != 0).await; self.joystick.button_press(Button::G19, buf[5] & 0b00000100 != 0)?; + self.state.set_button(Button::G19, buf[5] & 0b00000100 != 0).await; self.joystick.button_press(Button::G20, buf[5] & 0b00001000 != 0)?; + self.state.set_button(Button::G20, buf[5] & 0b00001000 != 0).await; self.joystick.button_press(Button::G21, buf[5] & 0b00010000 != 0)?; + self.state.set_button(Button::G21, buf[5] & 0b00010000 != 0).await; self.joystick.button_press(Button::G22, buf[5] & 0b00100000 != 0)?; + self.state.set_button(Button::G22, buf[5] & 0b00100000 != 0).await; self.joystick.button_press(Button::Stick1, buf[7] & 0b00000010 != 0)?; + self.state.set_button(Button::Stick1, buf[7] & 0b00000010 != 0).await; self.joystick.button_press(Button::Stick2, buf[7] & 0b00000100 != 0)?; + self.state.set_button(Button::Stick2, buf[7] & 0b00000100 != 0).await; self.joystick.button_press(Button::Stick3, buf[7] & 0b00001000 != 0)?; + self.state.set_button(Button::Stick3, buf[7] & 0b00001000 != 0).await; self.joystick.synchronise()?; @@ -157,7 +262,7 @@ impl G13 { impl Dimensions for G13 { fn bounding_box(&self) -> Rectangle { - Rectangle::new(Point::new(1, 1), Size::new(160, 42)) + Rectangle::new(Point::new(0, 0), Size::new(160, 42)) } } @@ -170,6 +275,10 @@ impl DrawTarget for G13 { I: IntoIterator>, { for p in pixels { + if p.0.x < 0 || p.0.x > G13_LCD_COLUMNS || p.0.y < 0 || p.0.y > G13_LCD_ROWS { + continue; + } + let offset = image_byte_offset(p.0.y, p.0.x); let mask = 1 << (p.0.y.rem_euclid(8)); diff --git a/src/main.rs b/src/main.rs index c333489..86c445a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use embedded_graphics::{ text::{Alignment, Text, TextStyleBuilder}, }; use time::{OffsetDateTime, macros::offset}; +use tokio::time::Instant; use crate::g13::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS}; @@ -26,24 +27,33 @@ async fn main() -> Result<(), Box> { .baseline(embedded_graphics::text::Baseline::Middle) .build(); + let mut x = G13_LCD_COLUMNS as f64 / 2.0; + let mut y = G13_LCD_ROWS as f64 / 2.0; + + // 30 fps render loop + let mut dt = 0.0; loop { + let start = Instant::now(); let now = OffsetDateTime::now_utc().to_offset(offset!(+1)); + // Update Logic + x += _g13.state.get_x().await * dt * 25.0; + y += _g13.state.get_y().await * dt * 25.0; + + // Render let string = format!("{:0>2}:{:0>2}:{:0>2}", now.hour(), now.minute(), now.second()); _g13.clear(BinaryColor::Off).unwrap(); - Text::with_text_style( - &string, - Point::new(G13_LCD_COLUMNS / 2, G13_LCD_ROWS / 2), - character_style, - textstyle, - ) - .draw(&mut _g13) - .unwrap(); + Text::with_text_style(&string, Point::new(x as i32, y as i32), character_style, textstyle) + .draw(&mut _g13) + .unwrap(); _g13.render().unwrap(); - tokio::time::sleep(Duration::from_secs(1)).await; + // Calculate delta time + let delta = Instant::now() - start; + tokio::time::sleep(Duration::from_millis(33) - delta).await; + dt = (Instant::now() - start).as_secs_f64(); } });