input as events
This commit is contained in:
98
Cargo.lock
generated
98
Cargo.lock
generated
@@ -103,6 +103,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aliasable"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
|
||||
|
||||
[[package]]
|
||||
name = "aligned"
|
||||
version = "0.4.3"
|
||||
@@ -2376,6 +2382,19 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics-simulator"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31606a4fb7d9d3a79a38d27bc2954cfa98682c8fea4b22c09a442785a80424e"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"embedded-graphics",
|
||||
"image",
|
||||
"ouroboros",
|
||||
"sdl2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encase"
|
||||
version = "0.12.0"
|
||||
@@ -2785,6 +2804,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"ctrlc",
|
||||
"embedded-graphics",
|
||||
"embedded-graphics-simulator",
|
||||
"g13-driver",
|
||||
"mlua",
|
||||
"time",
|
||||
@@ -3076,6 +3096,12 @@ dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
@@ -4196,6 +4222,30 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ouroboros"
|
||||
version = "0.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
|
||||
dependencies = [
|
||||
"aliasable",
|
||||
"ouroboros_macro",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ouroboros_macro"
|
||||
version = "0.18.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.25.1"
|
||||
@@ -4426,6 +4476,19 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2-diagnostics"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiling"
|
||||
version = "1.0.17"
|
||||
@@ -4847,6 +4910,29 @@ dependencies = [
|
||||
"tiny-skia",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"sdl2-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2-sys"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.2.2"
|
||||
@@ -5549,6 +5635,12 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -6625,6 +6717,12 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
||||
[[package]]
|
||||
name = "yazi"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod joystick;
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, hash_map::Entry},
|
||||
io::{Read, Write},
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
@@ -16,62 +17,78 @@ use nusb::{
|
||||
transfer::{ControlOut, ControlType, In, Interrupt, Out, Recipient},
|
||||
};
|
||||
|
||||
use crate::joystick::Button;
|
||||
|
||||
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;
|
||||
pub const G13_LCD_BUF_SIZE: i32 = (G13_LCD_ROWS + 5) * G13_LCD_BYTES_PER_ROW;
|
||||
|
||||
const BUTTON_MAP: &[(Button, usize, u8)] = &[
|
||||
// buf[6]
|
||||
(Button::Action, 6, 0b00000001),
|
||||
(Button::Screen1, 6, 0b00000010),
|
||||
(Button::Screen2, 6, 0b00000100),
|
||||
(Button::Screen3, 6, 0b00001000),
|
||||
(Button::Screen4, 6, 0b00010000),
|
||||
(Button::M1, 6, 0b00100000),
|
||||
(Button::M2, 6, 0b01000000),
|
||||
(Button::M3, 6, 0b10000000),
|
||||
// buf[7]
|
||||
(Button::Light, 7, 0b01000000),
|
||||
(Button::MR, 7, 0b00000001),
|
||||
(Button::Stick1, 7, 0b00000010),
|
||||
(Button::Stick2, 7, 0b00000100),
|
||||
(Button::Stick3, 7, 0b00001000),
|
||||
// buf[3]
|
||||
(Button::G1, 3, 0b00000001),
|
||||
(Button::G2, 3, 0b00000010),
|
||||
(Button::G3, 3, 0b00000100),
|
||||
(Button::G4, 3, 0b00001000),
|
||||
(Button::G5, 3, 0b00010000),
|
||||
(Button::G6, 3, 0b00100000),
|
||||
(Button::G7, 3, 0b01000000),
|
||||
(Button::G8, 3, 0b10000000),
|
||||
// buf[4]
|
||||
(Button::G9, 4, 0b00000001),
|
||||
(Button::G10, 4, 0b00000010),
|
||||
(Button::G11, 4, 0b00000100),
|
||||
(Button::G12, 4, 0b00001000),
|
||||
(Button::G13, 4, 0b00010000),
|
||||
(Button::G14, 4, 0b00100000),
|
||||
(Button::G15, 4, 0b01000000),
|
||||
(Button::G16, 4, 0b10000000),
|
||||
// buf[5]
|
||||
(Button::G17, 5, 0b00000001),
|
||||
(Button::G18, 5, 0b00000010),
|
||||
(Button::G19, 5, 0b00000100),
|
||||
(Button::G20, 5, 0b00001000),
|
||||
(Button::G21, 5, 0b00010000),
|
||||
(Button::G22, 5, 0b00100000),
|
||||
];
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Vec2<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
}
|
||||
|
||||
impl<T> Vec2<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub fn new(x: T, y: T) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct G13 {
|
||||
interface: Interface,
|
||||
img_buffer: Arc<RwLock<[u8; G13_LCD_BUF_SIZE as usize + 8]>>,
|
||||
state: Arc<RwLock<State>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct State {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub buttons: Buttons,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct Buttons {
|
||||
pub action: bool,
|
||||
pub screen1: bool,
|
||||
pub screen2: bool,
|
||||
pub screen3: bool,
|
||||
pub screen4: bool,
|
||||
pub light: bool,
|
||||
pub m1: bool,
|
||||
pub m2: bool,
|
||||
pub m3: bool,
|
||||
pub mr: bool,
|
||||
pub g1: bool,
|
||||
pub g2: bool,
|
||||
pub g3: bool,
|
||||
pub g4: bool,
|
||||
pub g5: bool,
|
||||
pub g6: bool,
|
||||
pub g7: bool,
|
||||
pub g8: bool,
|
||||
pub g9: bool,
|
||||
pub g10: bool,
|
||||
pub g11: bool,
|
||||
pub g12: bool,
|
||||
pub g13: bool,
|
||||
pub g14: bool,
|
||||
pub g15: bool,
|
||||
pub g16: bool,
|
||||
pub g17: bool,
|
||||
pub g18: bool,
|
||||
pub g19: bool,
|
||||
pub g20: bool,
|
||||
pub g21: bool,
|
||||
pub g22: bool,
|
||||
pub stick1: bool,
|
||||
pub stick2: bool,
|
||||
pub stick3: bool,
|
||||
display: G13Display,
|
||||
input: G13Input,
|
||||
}
|
||||
|
||||
impl G13 {
|
||||
@@ -96,80 +113,142 @@ impl G13 {
|
||||
Err(e) => return Err(format!("Unable to claim interface: {:#?}", e).into()),
|
||||
};
|
||||
|
||||
let img_buffer = [0u8; G13_LCD_BUF_SIZE as usize + 8];
|
||||
let mut buffer = [0u8; G13_LCD_BUF_SIZE as usize + 32 + 8];
|
||||
buffer[0] = 0x03;
|
||||
buffer[32..G13_LCD_BUF_SIZE as usize + 32 + 8].copy_from_slice(&img_buffer);
|
||||
|
||||
let mut w = interface.endpoint::<Interrupt, Out>(0x02)?.writer(64);
|
||||
w.write_all(&buffer)?;
|
||||
w.flush()?;
|
||||
|
||||
Ok(Self {
|
||||
interface,
|
||||
img_buffer: Arc::new(RwLock::new(img_buffer)),
|
||||
state: Arc::new(RwLock::new(Default::default())),
|
||||
input: G13Input::new(interface.clone()),
|
||||
display: G13Display::new(interface),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn state(&self) -> State {
|
||||
*self.state.read().expect("Poisoned")
|
||||
pub fn split(self) -> (G13Display, G13Input) {
|
||||
(self.display, self.input)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum G13Event {
|
||||
Axis(u8, u8),
|
||||
Button(Button, (bool, bool)), // (old, new)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct G13Input {
|
||||
interface: Interface,
|
||||
buttons: HashMap<Button, bool>,
|
||||
axis: Vec2<u8>,
|
||||
calibrated_axis: (Vec2<u8>, Vec2<u8>), // this needs to be saved/loaded
|
||||
calibrating: bool,
|
||||
}
|
||||
|
||||
impl G13Input {
|
||||
pub fn new(interface: Interface) -> Self {
|
||||
Self {
|
||||
interface,
|
||||
buttons: HashMap::new(),
|
||||
axis: Default::default(),
|
||||
calibrated_axis: (Vec2::new(127, 127), Vec2::new(127, 127)),
|
||||
calibrating: false,
|
||||
}
|
||||
}
|
||||
pub fn calibrate(mut self) -> Self {
|
||||
self.calibrating = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn read(&self) -> Result<State, Box<dyn std::error::Error>> {
|
||||
let mut state = self.state();
|
||||
pub fn with_calibration_axis(mut self, min: Vec2<u8>, max: Vec2<u8>) -> Self {
|
||||
self.calibrated_axis.0 = min;
|
||||
self.calibrated_axis.1 = max;
|
||||
self.calibrating = false;
|
||||
self
|
||||
}
|
||||
|
||||
let mut reader = self.interface.endpoint::<Interrupt, In>(0x81)?.reader(8);
|
||||
pub fn get_calibration_axis(&self) -> (Vec2<u8>, Vec2<u8>) {
|
||||
self.calibrated_axis
|
||||
}
|
||||
|
||||
fn handle_button(&mut self, button: Button, value: bool) -> Option<G13Event> {
|
||||
if let Entry::Vacant(e) = self.buttons.entry(button) {
|
||||
e.insert(value);
|
||||
if value {
|
||||
return Some(G13Event::Button(button, (!value, value)));
|
||||
}
|
||||
}
|
||||
|
||||
let prev = self.buttons[&button];
|
||||
if self.buttons[&button] == value {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.buttons.insert(button, value);
|
||||
Some(G13Event::Button(button, (prev, value)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for G13Input {
|
||||
type Item = Option<G13Event>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut reader = self
|
||||
.interface
|
||||
.endpoint::<Interrupt, In>(0x81)
|
||||
.ok()?
|
||||
.reader(8);
|
||||
let mut buf = [0; 8];
|
||||
reader.read_exact(&mut buf)?;
|
||||
reader.read_exact(&mut buf).ok()?;
|
||||
|
||||
state.x = (((buf[1] as f64) / 256.0 * 1024.0) - 512.0) as i32;
|
||||
state.y = (((buf[2] as f64) / 256.0 * 1024.0) - 512.0) as i32;
|
||||
for &(button, index, mask) in BUTTON_MAP {
|
||||
if let Some(event) = self.handle_button(button, buf[index] & mask != 0) {
|
||||
self.calibrating = false;
|
||||
return Some(Some(event));
|
||||
}
|
||||
}
|
||||
|
||||
state.buttons.action = buf[6] & 0b00000001 != 0;
|
||||
state.buttons.screen1 = buf[6] & 0b00000010 != 0;
|
||||
state.buttons.screen2 = buf[6] & 0b00000100 != 0;
|
||||
state.buttons.screen3 = buf[6] & 0b00001000 != 0;
|
||||
state.buttons.screen4 = buf[6] & 0b00010000 != 0;
|
||||
state.buttons.light = buf[7] & 0b0100000 != 0;
|
||||
let axis = Vec2::new(buf[1], buf[2]);
|
||||
|
||||
state.buttons.m1 = buf[6] & 0b00100000 != 0;
|
||||
state.buttons.m2 = buf[6] & 0b01000000 != 0;
|
||||
state.buttons.m3 = buf[6] & 0b10000000 != 0;
|
||||
state.buttons.mr = buf[7] & 0b00000001 != 0;
|
||||
if self.axis == axis {
|
||||
return Some(None);
|
||||
}
|
||||
|
||||
state.buttons.g1 = buf[3] & 0b00000001 != 0;
|
||||
state.buttons.g2 = buf[3] & 0b00000010 != 0;
|
||||
state.buttons.g3 = buf[3] & 0b00000100 != 0;
|
||||
state.buttons.g4 = buf[3] & 0b00001000 != 0;
|
||||
state.buttons.g5 = buf[3] & 0b00010000 != 0;
|
||||
state.buttons.g6 = buf[3] & 0b00100000 != 0;
|
||||
state.buttons.g7 = buf[3] & 0b01000000 != 0;
|
||||
state.buttons.g8 = buf[3] & 0b10000000 != 0;
|
||||
self.axis = axis;
|
||||
|
||||
state.buttons.g9 = buf[4] & 0b00000001 != 0;
|
||||
state.buttons.g10 = buf[4] & 0b00000010 != 0;
|
||||
state.buttons.g11 = buf[4] & 0b00000100 != 0;
|
||||
state.buttons.g12 = buf[4] & 0b00001000 != 0;
|
||||
state.buttons.g13 = buf[4] & 0b00010000 != 0;
|
||||
state.buttons.g14 = buf[4] & 0b00100000 != 0;
|
||||
state.buttons.g15 = buf[4] & 0b01000000 != 0;
|
||||
state.buttons.g16 = buf[4] & 0b10000000 != 0;
|
||||
self.calibrated_axis.0.x = self.calibrated_axis.0.x.min(axis.x);
|
||||
self.calibrated_axis.1.x = self.calibrated_axis.1.x.max(axis.x);
|
||||
self.calibrated_axis.0.y = self.calibrated_axis.0.y.min(axis.y);
|
||||
self.calibrated_axis.1.y = self.calibrated_axis.1.y.max(axis.y);
|
||||
|
||||
state.buttons.g17 = buf[5] & 0b00000001 != 0;
|
||||
state.buttons.g18 = buf[5] & 0b00000010 != 0;
|
||||
state.buttons.g19 = buf[5] & 0b00000100 != 0;
|
||||
state.buttons.g20 = buf[5] & 0b00001000 != 0;
|
||||
state.buttons.g21 = buf[5] & 0b00010000 != 0;
|
||||
state.buttons.g22 = buf[5] & 0b00100000 != 0;
|
||||
let (xmin, xmax) = (self.calibrated_axis.0.x, self.calibrated_axis.1.x);
|
||||
let (ymin, ymax) = (self.calibrated_axis.0.y, self.calibrated_axis.1.y);
|
||||
|
||||
state.buttons.stick1 = buf[7] & 0b00000010 != 0;
|
||||
state.buttons.stick2 = buf[7] & 0b00000100 != 0;
|
||||
state.buttons.stick3 = buf[7] & 0b00001000 != 0;
|
||||
let x_output = map_range(self.axis.x, xmin, xmax);
|
||||
let y_output = map_range(self.axis.y, ymin, ymax);
|
||||
|
||||
*self.state.write().expect("Poisoned") = state;
|
||||
Some(Some(G13Event::Axis(x_output as u8, y_output as u8)))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(state)
|
||||
fn map_range(v: u8, in_min: u8, in_max: u8) -> f64 {
|
||||
if in_min == in_max {
|
||||
return 0.0;
|
||||
}
|
||||
255.0 * (v as f64 - in_min as f64) / (in_max as f64 - in_min as f64)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct G13Display {
|
||||
interface: Interface,
|
||||
img_buffer: Arc<RwLock<[u8; G13_LCD_BUF_SIZE as usize + 8]>>,
|
||||
}
|
||||
|
||||
impl G13Display {
|
||||
pub fn new(interface: Interface) -> Self {
|
||||
let img_buffer = [0u8; G13_LCD_BUF_SIZE as usize + 8];
|
||||
// let mut buffer = [0u8; G13_LCD_BUF_SIZE as usize + 32 + 8];
|
||||
// buffer[0] = 0x03;
|
||||
// buffer[32..G13_LCD_BUF_SIZE as usize + 32 + 8].copy_from_slice(&img_buffer);
|
||||
|
||||
Self {
|
||||
interface,
|
||||
img_buffer: Arc::new(RwLock::new(img_buffer)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_lcd_color(&self, r: u8, g: u8, b: u8) -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -202,9 +281,13 @@ impl G13 {
|
||||
w.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Size {
|
||||
Size::new(G13_LCD_COLUMNS as u32, G13_LCD_ROWS as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dimensions for G13 {
|
||||
impl Dimensions for G13Display {
|
||||
fn bounding_box(&self) -> Rectangle {
|
||||
Rectangle::new(
|
||||
Point::new(0, 0),
|
||||
@@ -213,7 +296,7 @@ impl Dimensions for G13 {
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawTarget for G13 {
|
||||
impl DrawTarget for G13Display {
|
||||
type Color = BinaryColor;
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
# buoyant = "0.6.1"
|
||||
ctrlc = "3.5"
|
||||
embedded-graphics = "0.8"
|
||||
g13-driver.workspace = true
|
||||
mlua = { version = "0.11.6", features = ["lua54", "async", "macros", "serde"] }
|
||||
time = { version = "0.3.47", features = ["formatting", "macros"] }
|
||||
|
||||
embedded-graphics-simulator = "0.7.0"
|
||||
|
||||
@@ -1,251 +1,73 @@
|
||||
pub mod mouse;
|
||||
mod os;
|
||||
// pub mod mouse;
|
||||
// mod os;
|
||||
|
||||
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
|
||||
use mlua::{Error, ExternalResult, Lua};
|
||||
use std::{
|
||||
fs,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
},
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
// use embedded_graphics::prelude::{Dimensions, DrawTarget};
|
||||
// use embedded_graphics::{pixelcolor::BinaryColor, prelude::Size};
|
||||
// use embedded_graphics_simulator::{OutputSettingsBuilder, SimulatorDisplay, Window};
|
||||
// use mlua::{Error, ExternalResult, Lua};
|
||||
// use rsact_ui::prelude::*;
|
||||
// use rsact_ui::{
|
||||
// col,
|
||||
// event::simulator::simulator_single_encoder,
|
||||
// render::{AntiAliasing, RendererOptions},
|
||||
// row,
|
||||
// style::accent::AccentStyler,
|
||||
// ui::UI,
|
||||
// };
|
||||
// use std::fmt::Binary;
|
||||
// use std::{
|
||||
// fs,
|
||||
// sync::{
|
||||
// Arc,
|
||||
// atomic::{AtomicBool, Ordering},
|
||||
// },
|
||||
// thread::sleep,
|
||||
// time::{Duration, Instant},
|
||||
// };
|
||||
|
||||
// use crate::os::G13Os;
|
||||
|
||||
use embedded_graphics::{
|
||||
Drawable,
|
||||
pixelcolor::BinaryColor,
|
||||
prelude::{DrawTarget, Point},
|
||||
};
|
||||
|
||||
use crate::os::G13Os;
|
||||
use g13_driver::{G13, G13Event};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
let g13 = G13::new()?;
|
||||
let (mut display, input) = g13.split();
|
||||
|
||||
let _running = running.clone();
|
||||
|
||||
let os = G13Os::new();
|
||||
|
||||
os.run();
|
||||
|
||||
/*
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
let g13_table = lua.create_table()?;
|
||||
|
||||
let _running = running.clone();
|
||||
let _g13 = g13.clone();
|
||||
std::thread::spawn(move || {
|
||||
while _running.load(Ordering::SeqCst) {
|
||||
if _g13.read().is_err() {
|
||||
_running.store(false, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let _g13 = g13.clone();
|
||||
g13_table.set(
|
||||
"set_color",
|
||||
lua.create_function(move |_, (r, g, b): (i32, i32, i32)| {
|
||||
_g13.set_lcd_color(
|
||||
r.clamp(0, 255) as u8,
|
||||
g.clamp(0, 255) as u8,
|
||||
b.clamp(0, 255) as u8,
|
||||
)
|
||||
.into_lua_err()
|
||||
})?,
|
||||
)?;
|
||||
|
||||
let _g13 = g13.clone();
|
||||
let fn_clear = lua.create_function(move |_, on| {
|
||||
let mut _g13 = _g13.clone();
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::prelude::*;
|
||||
let color = if on {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
BinaryColor::Off
|
||||
};
|
||||
_g13.clear(color).into_lua_err()
|
||||
})?;
|
||||
g13_table.set("clear", fn_clear)?;
|
||||
|
||||
let mut _g13 = g13.clone();
|
||||
let fn_set_pixel = lua.create_function_mut(move |_, (x, y, on)| {
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::prelude::*;
|
||||
let color = if on {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
BinaryColor::Off
|
||||
};
|
||||
Pixel(Point::new(x, y), color)
|
||||
.draw(&mut _g13)
|
||||
.into_lua_err()
|
||||
})?;
|
||||
g13_table.set("set_pixel", fn_set_pixel)?;
|
||||
|
||||
let mut _g13 = g13.clone();
|
||||
let fn_text = lua.create_function_mut(
|
||||
move |_,
|
||||
(text, x, y, color, alignment, baseline, size): (
|
||||
String,
|
||||
i32,
|
||||
i32,
|
||||
bool,
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
)| {
|
||||
use embedded_graphics::mono_font::ascii::*;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::prelude::*;
|
||||
use embedded_graphics::text::*;
|
||||
|
||||
let alignment = match alignment {
|
||||
0 => Alignment::Left,
|
||||
1 => Alignment::Center,
|
||||
2 => Alignment::Right,
|
||||
_ => {
|
||||
return Err(Error::RuntimeError(
|
||||
"Invalid alignment, allowed values: 0, 1, 2".into(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let baseline = match baseline {
|
||||
0 => Baseline::Top,
|
||||
1 => Baseline::Middle,
|
||||
2 => Baseline::Bottom,
|
||||
_ => {
|
||||
return Err(Error::RuntimeError(
|
||||
"Invalid baseline, allowed values: 0, 1, 2".into(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let color = if color {
|
||||
BinaryColor::On
|
||||
} else {
|
||||
BinaryColor::Off
|
||||
};
|
||||
|
||||
let size = match size {
|
||||
2 => FONT_5X7,
|
||||
3 => FONT_5X8,
|
||||
4 => FONT_6X9,
|
||||
5 => FONT_6X10,
|
||||
6 => FONT_6X12,
|
||||
7 => FONT_6X13,
|
||||
8 => FONT_6X13_BOLD,
|
||||
9 => FONT_6X13_ITALIC,
|
||||
10 => FONT_7X13,
|
||||
11 => FONT_7X13_BOLD,
|
||||
12 => FONT_7X13_ITALIC,
|
||||
13 => FONT_7X14,
|
||||
14 => FONT_7X14_BOLD,
|
||||
15 => FONT_8X13,
|
||||
16 => FONT_8X13_BOLD,
|
||||
17 => FONT_8X13_ITALIC,
|
||||
18 => FONT_9X15,
|
||||
19 => FONT_9X15_BOLD,
|
||||
20 => FONT_9X18,
|
||||
21 => FONT_9X18_BOLD,
|
||||
22 => FONT_10X20,
|
||||
_ => FONT_4X6,
|
||||
};
|
||||
|
||||
let character_style = embedded_graphics::mono_font::MonoTextStyle::new(&size, color);
|
||||
|
||||
let textstyle = TextStyleBuilder::new()
|
||||
.alignment(alignment)
|
||||
.baseline(baseline)
|
||||
let character_style = embedded_graphics::mono_font::MonoTextStyle::new(
|
||||
&embedded_graphics::mono_font::ascii::FONT_10X20,
|
||||
embedded_graphics::pixelcolor::BinaryColor::On,
|
||||
);
|
||||
let textstyle = embedded_graphics::text::TextStyleBuilder::new()
|
||||
.alignment(embedded_graphics::text::Alignment::Left)
|
||||
.baseline(embedded_graphics::text::Baseline::Top)
|
||||
.build();
|
||||
|
||||
let pos = Point::new(x, y);
|
||||
|
||||
Text::with_text_style(&text, pos, character_style, textstyle)
|
||||
.draw(&mut _g13)
|
||||
.into_lua_err()?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
g13_table.set("text", fn_text)?;
|
||||
|
||||
g13_table.set("display_width", G13_LCD_COLUMNS)?;
|
||||
g13_table.set("display_height", G13_LCD_ROWS)?;
|
||||
|
||||
globals.set("g13", g13_table)?;
|
||||
|
||||
let joy = lua.create_table()?;
|
||||
joy.set("x", 0.0f32)?;
|
||||
joy.set("y", 0.0f32)?;
|
||||
joy.set("deadzone", 40)?;
|
||||
globals.set("joy", joy)?;
|
||||
|
||||
// load all files from dir `./scripts` for now, user configurable later or ~/.config/g13-os/\*.<lua>
|
||||
// for now, just main.luau
|
||||
let main = fs::read_to_string("./scripts/main.lua")?;
|
||||
|
||||
lua.load(main).set_name("main.lua").exec()?;
|
||||
|
||||
if lua.load("setup ~= nil").eval()? {
|
||||
lua.load("setup()").exec()?;
|
||||
}
|
||||
|
||||
if lua.load("update ~= nil").eval()? {
|
||||
let mut _g13 = g13.clone();
|
||||
let mut delta: f32 = 0.0;
|
||||
while running.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
let start = Instant::now();
|
||||
let state = g13.state();
|
||||
|
||||
let mut deadzone: i32 = lua.load("joy.deadzone").eval()?;
|
||||
if deadzone > 512 {
|
||||
deadzone = 0;
|
||||
}
|
||||
let offset: i32 = 512 - deadzone;
|
||||
let mut x = state.x;
|
||||
let mut y = state.y;
|
||||
|
||||
x = if x.abs() < deadzone {
|
||||
0
|
||||
} else {
|
||||
x - deadzone * x.signum()
|
||||
for event in input {
|
||||
let Some(event) = event else {
|
||||
continue;
|
||||
};
|
||||
|
||||
y = if y.abs() < deadzone {
|
||||
0
|
||||
} else {
|
||||
y - deadzone * y.signum()
|
||||
};
|
||||
println!("{:?}", event);
|
||||
|
||||
lua.load(format!(
|
||||
"joy.x = {}\njoy.y = {}",
|
||||
x as f32 / offset as f32,
|
||||
y as f32 / offset as f32
|
||||
))
|
||||
.exec()?;
|
||||
display.clear(BinaryColor::Off)?;
|
||||
|
||||
let buttons = lua.create_table()?;
|
||||
buttons.set("t1", state.buttons.screen1)?;
|
||||
buttons.set("t2", state.buttons.screen2)?;
|
||||
buttons.set("t3", state.buttons.screen3)?;
|
||||
buttons.set("t4", state.buttons.screen4)?;
|
||||
globals.set("buttons", buttons)?;
|
||||
|
||||
lua.load(format!("update({})", delta)).exec()?;
|
||||
|
||||
_g13.render()?;
|
||||
|
||||
let duration = Instant::now() - start;
|
||||
|
||||
// 30 fps lock
|
||||
if duration < Duration::from_millis(33) {
|
||||
sleep(Duration::from_millis(33) - duration);
|
||||
if let G13Event::Axis(x, y) = event {
|
||||
embedded_graphics::text::Text::with_text_style(
|
||||
&format!("{}x{}", x, y),
|
||||
Point::new(5, 5),
|
||||
character_style,
|
||||
textstyle,
|
||||
)
|
||||
.draw(&mut display)?;
|
||||
}
|
||||
|
||||
delta = (Instant::now() - start).as_secs_f32();
|
||||
}
|
||||
display.render()?;
|
||||
}
|
||||
|
||||
running.store(false, Ordering::SeqCst);
|
||||
*/
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user