This commit is contained in:
2026-02-09 12:13:19 +01:00
parent 93fbc8fc12
commit a122fde6da
4 changed files with 136 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
use std::slice;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Axis {
X,
Y,

View File

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

View File

@@ -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<RwLock<i32>>,
y: Arc<RwLock<i32>>,
buttons: Arc<RwLock<HashMap<Button, bool>>>,
}
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<Item = embedded_graphics_core::Pixel<Self::Color>>,
{
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));

View File

@@ -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<dyn std::error::Error>> {
.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();
}
});