mouse stuff

This commit is contained in:
2026-02-12 22:59:27 +01:00
parent 3db5b5e094
commit 37d834d80b
6 changed files with 357 additions and 40 deletions

11
Cargo.lock generated
View File

@@ -2787,6 +2787,7 @@ dependencies = [
"embedded-graphics",
"g13-driver",
"mlua",
"time",
]
[[package]]
@@ -3448,15 +3449,6 @@ dependencies = [
"imgref",
]
[[package]]
name = "luau0-src"
version = "0.18.2+luau708"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eed3214ab526e7e7b76c3f324a965d363db94a99ae67f65e67ec6fc499eb5e6d"
dependencies = [
"cc",
]
[[package]]
name = "mach2"
version = "0.4.3"
@@ -3587,7 +3579,6 @@ dependencies = [
"cc",
"cfg-if",
"libc",
"luau0-src",
"pkg-config",
]

View File

@@ -1,5 +1,5 @@
name = "DVD"
authors = {"AviiNL"}
authors = { "AviiNL" }
description = "Bouncing 'dvd' Logo"
local width = g13.display_width
@@ -19,7 +19,7 @@ function setup()
joy.deadzone = 40
end
function update(delta: number)
function update(delta)
x = x + speed * delta * joy.x * 1.2
y = y + speed * delta * joy.y
@@ -29,26 +29,26 @@ function update(delta: number)
g13.clear()
g13.set_color(color_x/2, color_y/2, color_z/2)
g13.set_color(color_x / 2, color_y / 2, color_z / 2)
g13.text("Hello World!", 1, 1, true, 0, 0, 1)
for sy = -size,size do
for sx = -size,size do
for sy = -size, size do
for sx = -size, size do
g13.set_pixel(x + sx, y + sy, true)
end
end
end
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
if type(o) == 'table' then
local s = '{ '
for k, v in pairs(o) do
if type(k) ~= 'number' then k = '"' .. k .. '"' end
s = s .. '[' .. k .. '] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end

View File

@@ -4,12 +4,8 @@ version.workspace = true
edition.workspace = true
[dependencies]
g13-driver.workspace = true
embedded-graphics = "0.8"
mlua = { version = "0.11.6", features = [
"luau-jit",
"async",
"macros",
"serde",
] }
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"] }

View File

@@ -1,3 +1,6 @@
pub mod mouse;
mod os;
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
use mlua::{Error, ExternalResult, Lua};
use std::{
@@ -10,14 +13,18 @@ use std::{
time::{Duration, Instant},
};
use crate::os::G13Os;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let running = Arc::new(AtomicBool::new(true));
let _running = running.clone();
ctrlc::set_handler(move || _running.store(false, Ordering::SeqCst))
.expect("Error setting Ctrl-C handler");
let g13 = G13::new()?;
let os = G13Os::new();
os.run();
/*
let lua = Lua::new();
let globals = lua.globals();
let g13_table = lua.create_table()?;
@@ -172,11 +179,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
joy.set("deadzone", 40)?;
globals.set("joy", joy)?;
// load all files from dir `./scripts` for now, user configurable later or ~/.config/g13-os/*.<lua[u]>
// 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.luau")?;
let main = fs::read_to_string("./scripts/main.lua")?;
lua.load(main).set_name("main.luau").exec()?;
lua.load(main).set_name("main.lua").exec()?;
if lua.load("setup ~= nil").eval()? {
lua.load("setup()").exec()?;
@@ -239,6 +246,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
running.store(false, Ordering::SeqCst);
*/
Ok(())
}

92
g13-os/src/mouse.rs Normal file
View File

@@ -0,0 +1,92 @@
use std::cell::RefCell;
use embedded_graphics::{Drawable, Pixel, pixelcolor::BinaryColor, prelude::Point};
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS, State};
#[rustfmt::skip]
const MOUSE_CURSOR: &[u8] = &[
2, 0, 0, 0, 0,
2, 2, 0, 0, 0,
2, 1, 2, 0, 0,
2, 1, 1, 2, 0,
2, 1, 2, 2, 2,
2, 2, 0, 0, 0,
];
pub struct Mouse {
deadzone: i32,
speed: f32,
x: RefCell<f32>,
y: RefCell<f32>,
}
impl Default for Mouse {
fn default() -> Self {
Self::new()
}
}
impl Mouse {
pub fn new() -> Self {
Self {
deadzone: 40,
speed: 20.0,
x: RefCell::new(G13_LCD_COLUMNS as f32 / 2.0 - 2.0),
y: RefCell::new(G13_LCD_ROWS as f32 / 2.0 - 3.0),
}
}
pub fn update(&self, state: State, delta: f32) {
let offset: i32 = 512 - self.deadzone;
let mut x = state.x;
let mut y = state.y;
x = if x.abs() < self.deadzone {
0
} else {
x - self.deadzone * x.signum()
};
y = if y.abs() < self.deadzone {
0
} else {
y - self.deadzone * y.signum()
};
let x = x as f32 / offset as f32;
let y = y as f32 / offset as f32;
let mut sx = self.x.borrow_mut();
let mut sy = self.y.borrow_mut();
*sx = (*sx + x * delta * self.speed * 1.2).clamp(0., (G13_LCD_COLUMNS - 1) as f32);
*sy = (*sy + y * delta * self.speed).clamp(0., (G13_LCD_ROWS - 1) as f32);
}
pub fn get_x(&self) -> i32 {
*self.x.borrow() as i32
}
pub fn get_y(&self) -> i32 {
*self.y.borrow() as i32
}
pub fn render(&self, g13: &mut G13) {
for (i, value) in MOUSE_CURSOR.iter().enumerate() {
let x = i as i32 % 5;
let y = i as i32 / 5;
let color = if *value == 1 {
BinaryColor::Off
} else if *value == 2 {
BinaryColor::On
} else {
continue;
};
Pixel(Point::new(self.get_x() + x, self.get_y() + y), color)
.draw(g13)
.expect("G13 to be Connected");
}
}
}

231
g13-os/src/os.rs Normal file
View File

@@ -0,0 +1,231 @@
use std::{
fs::read_dir,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
time::Instant,
};
use embedded_graphics::{
Drawable,
mono_font::ascii::*,
pixelcolor::BinaryColor,
prelude::{DrawTarget, Point, Primitive, Size},
primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle},
text::{Alignment, Baseline, Text, TextStyleBuilder},
};
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
use mlua::Lua;
use time::{OffsetDateTime, macros::offset};
use crate::mouse::Mouse;
pub struct App {
name: String,
}
pub struct Button {
label: String,
action: Option<fn()>,
}
pub struct G13Os {
g13: G13,
lua: Lua,
running: Arc<AtomicBool>,
apps: Vec<App>,
running_app: Option<App>,
buttons: [Option<Button>; 4],
mouse: Mouse,
}
impl G13Os {
pub fn new() -> Self {
let g13 = G13::new().expect("G13 to be connected");
let lua = Lua::new();
let running = Arc::new(AtomicBool::new(false));
let mut apps = Vec::new();
let buttons = [
Some(Button {
label: "Settings".to_owned(),
action: None,
}),
// Some(Button {
// label: "Down".to_owned(),
// action: None,
// }),
None,
// Some(Button {
// label: "Up".to_owned(),
// action: None,
// }),
None,
Some(Button {
label: "00:00".to_owned(),
action: None,
}),
];
for entry in read_dir("./apps").unwrap() {
apps.push(App {
name: entry.unwrap().file_name().into_string().unwrap(),
});
}
Self {
g13,
lua,
running,
apps,
running_app: None,
buttons,
mouse: Mouse::new(),
}
}
pub fn run(&self) {
let running = self.running.clone();
running.store(true, Ordering::SeqCst);
ctrlc::set_handler(move || running.store(false, Ordering::SeqCst))
.expect("Error setting Ctrl-C handler");
self.start_input_thread();
let mut g13 = self.g13.clone();
let mut delta = 0.0;
while self.running.load(Ordering::SeqCst) {
let start = Instant::now();
g13.clear(BinaryColor::Off).expect("G13 to be connected");
let mut show_mouse = false;
if self.running_app.is_none() {
self.render_menu();
show_mouse = true;
} else {
// render app
// if app.is_init == false
// app.is_init = true
// app.init()
// ..
// app.update();
}
if show_mouse {
self.mouse.update(g13.state(), delta);
self.mouse.render(&mut g13);
}
g13.render().expect("G13 to be connected");
delta = (Instant::now() - start).as_secs_f32();
}
}
fn render_menu(&self) {
let mut g13 = self.g13.clone();
// todo: const
let button_count = 4;
let button_width = G13_LCD_COLUMNS / button_count;
let fill = PrimitiveStyleBuilder::new()
.fill_color(BinaryColor::On)
.build();
let stroke = PrimitiveStyleBuilder::new()
.stroke_color(BinaryColor::On)
.stroke_width(1)
.build();
let character_style =
embedded_graphics::mono_font::MonoTextStyle::new(&FONT_4X6, BinaryColor::On);
let character_style_inv =
embedded_graphics::mono_font::MonoTextStyle::new(&FONT_4X6, BinaryColor::Off);
let textstyle = TextStyleBuilder::new()
.alignment(Alignment::Center)
.baseline(Baseline::Top)
.build();
for (i, btn) in self.buttons.iter().enumerate() {
let Some(btn) = btn else {
continue;
};
let line_x = i as i32 * button_width;
Line::new(Point::new(line_x, 8), Point::new(line_x + button_width, 8))
.into_styled(stroke)
.draw(&mut g13)
.expect("G13 to be connected");
if i > 0 && i < 4 {
Line::new(Point::new(line_x, 0), Point::new(line_x, 8))
.into_styled(stroke)
.draw(&mut g13)
.expect("G13 to be connected");
}
Line::new(
Point::new(line_x + button_width, 0),
Point::new(line_x + button_width, 8),
)
.into_styled(stroke)
.draw(&mut g13)
.expect("G13 to be connected");
let i = i as i32;
let text_x = ((i + 1) * button_width) - (button_width / 2);
let mut label = btn.label.clone();
if label.len() > 8 {
let _ = label.split_off(8);
}
if label == "00:00" {
let now = OffsetDateTime::now_utc().to_offset(offset!(+1)); // GMT+1
// Render
label = format!(
"{:0>2}:{:0>2}:{:0>2}",
now.hour(),
now.minute(),
now.second()
);
}
let style = if self.mouse.get_x() > i * button_width
&& self.mouse.get_x() < (i + 1) * button_width
&& self.mouse.get_y() < 8
{
Rectangle::new(
Point::new(i * button_width, 0),
Size::new(button_width as u32, 8),
)
.into_styled(fill)
.draw(&mut g13)
.expect("G13 to be Connected");
character_style_inv
} else {
character_style
};
Text::with_text_style(&label, Point::new(text_x, 1), style, textstyle)
.draw(&mut g13)
.expect("G13 to be connected");
}
}
fn start_input_thread(&self) {
let g13 = self.g13.clone();
let running = self.running.clone();
std::thread::spawn(move || {
while running.load(Ordering::SeqCst) {
let _ = g13.read();
}
});
}
}