I can haz Lua?
This commit is contained in:
120
Cargo.lock
generated
120
Cargo.lock
generated
@@ -1779,6 +1779,16 @@ dependencies = [
|
|||||||
"piper",
|
"piper",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "built"
|
name = "built"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -2769,6 +2779,15 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "g13-os"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-graphics",
|
||||||
|
"g13-driver",
|
||||||
|
"mlua",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -3428,6 +3447,15 @@ dependencies = [
|
|||||||
"imgref",
|
"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]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach2"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -3528,6 +3556,55 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua"
|
||||||
|
version = "0.11.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccd36acfa49ce6ee56d1307a061dd302c564eee757e6e4cd67eb4f7204846fab"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"either",
|
||||||
|
"erased-serde",
|
||||||
|
"futures-util",
|
||||||
|
"libc",
|
||||||
|
"mlua-sys",
|
||||||
|
"mlua_derive",
|
||||||
|
"num-traits",
|
||||||
|
"parking_lot",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"rustversion",
|
||||||
|
"serde",
|
||||||
|
"serde-value",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua-sys"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f1c3a7fc7580227ece249fd90aa2fa3b39eb2b49d3aec5e103b3e85f2c3dfc8"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"luau0-src",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua_derive"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "465bddde514c4eb3b50b543250e97c1d4b284fa3ef7dc0ba2992c77545dbceb2"
|
||||||
|
dependencies = [
|
||||||
|
"itertools 0.14.0",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro-error2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "moxcms"
|
name = "moxcms"
|
||||||
version = "0.7.11"
|
version = "0.7.11"
|
||||||
@@ -4109,6 +4186,15 @@ dependencies = [
|
|||||||
"libredox",
|
"libredox",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "2.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "5.0.0"
|
version = "5.0.0"
|
||||||
@@ -4317,6 +4403,28 @@ dependencies = [
|
|||||||
"toml_edit",
|
"toml_edit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -4775,6 +4883,16 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-value"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||||
|
dependencies = [
|
||||||
|
"ordered-float 2.10.1",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_core"
|
name = "serde_core"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@@ -5793,7 +5911,7 @@ dependencies = [
|
|||||||
"ndk-sys 0.6.0+11769913",
|
"ndk-sys 0.6.0+11769913",
|
||||||
"objc",
|
"objc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-float",
|
"ordered-float 5.0.0",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"portable-atomic-util",
|
"portable-atomic-util",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["driver", "joystick", "mini-game"]
|
members = ["driver", "g13-os", "joystick", "mini-game"]
|
||||||
default-members = ["joystick", "mini-game"]
|
default-members = ["joystick", "mini-game", "g13-os"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ pub const G13_LCD_BUF_SIZE: i32 = (G13_LCD_ROWS + 5) * G13_LCD_BYTES_PER_ROW;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct G13 {
|
pub struct G13 {
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
img_buffer: [u8; G13_LCD_BUF_SIZE as usize + 8],
|
img_buffer: Arc<RwLock<[u8; G13_LCD_BUF_SIZE as usize + 8]>>,
|
||||||
state: Arc<RwLock<State>>,
|
state: Arc<RwLock<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ impl G13 {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
interface,
|
interface,
|
||||||
img_buffer,
|
img_buffer: Arc::new(RwLock::new(img_buffer)),
|
||||||
state: Arc::new(RwLock::new(Default::default())),
|
state: Arc::new(RwLock::new(Default::default())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -191,9 +191,11 @@ impl G13 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn render(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let img_buffer = self.img_buffer.read().expect("Poisoned");
|
||||||
|
|
||||||
let mut buffer = [0u8; G13_LCD_BUF_SIZE as usize + 32 + 8];
|
let mut buffer = [0u8; G13_LCD_BUF_SIZE as usize + 32 + 8];
|
||||||
buffer[0] = 0x03;
|
buffer[0] = 0x03;
|
||||||
buffer[32..G13_LCD_BUF_SIZE as usize + 32 + 8].copy_from_slice(&self.img_buffer);
|
buffer[32..G13_LCD_BUF_SIZE as usize + 32 + 8].copy_from_slice(&(*img_buffer));
|
||||||
|
|
||||||
let mut w = self.interface.endpoint::<Interrupt, Out>(0x02)?.writer(64);
|
let mut w = self.interface.endpoint::<Interrupt, Out>(0x02)?.writer(64);
|
||||||
w.write_all(&buffer)?;
|
w.write_all(&buffer)?;
|
||||||
@@ -219,6 +221,7 @@ impl DrawTarget for G13 {
|
|||||||
where
|
where
|
||||||
I: IntoIterator<Item = embedded_graphics_core::Pixel<Self::Color>>,
|
I: IntoIterator<Item = embedded_graphics_core::Pixel<Self::Color>>,
|
||||||
{
|
{
|
||||||
|
let mut img_buffer = self.img_buffer.write().expect("Poisoned");
|
||||||
for p in pixels {
|
for p in pixels {
|
||||||
if p.0.x < 0 || p.0.x > G13_LCD_COLUMNS - 1 || p.0.y < 0 || p.0.y > G13_LCD_ROWS - 1 {
|
if p.0.x < 0 || p.0.x > G13_LCD_COLUMNS - 1 || p.0.y < 0 || p.0.y > G13_LCD_ROWS - 1 {
|
||||||
continue;
|
continue;
|
||||||
@@ -228,9 +231,9 @@ impl DrawTarget for G13 {
|
|||||||
let mask = 1 << (p.0.y.rem_euclid(8));
|
let mask = 1 << (p.0.y.rem_euclid(8));
|
||||||
|
|
||||||
if p.1.is_on() {
|
if p.1.is_on() {
|
||||||
self.img_buffer[offset as usize] |= mask;
|
img_buffer[offset as usize] |= mask;
|
||||||
} else {
|
} else {
|
||||||
self.img_buffer[offset as usize] &= !mask;
|
img_buffer[offset as usize] &= !mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
g13-os/Cargo.toml
Normal file
9
g13-os/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "g13-os"
|
||||||
|
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"] }
|
||||||
87
g13-os/src/main.rs
Normal file
87
g13-os/src/main.rs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
thread::sleep,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use g13_driver::{G13, G13_LCD_COLUMNS, G13_LCD_ROWS};
|
||||||
|
use mlua::{ExternalResult, Lua};
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let g13 = G13::new()?;
|
||||||
|
let lua = Lua::new();
|
||||||
|
let globals = lua.globals();
|
||||||
|
|
||||||
|
let g13_table = lua.create_table()?;
|
||||||
|
|
||||||
|
let _g13 = g13.clone();
|
||||||
|
g13_table.set(
|
||||||
|
"set_color",
|
||||||
|
lua.create_function(move |_, (r, g, b)| _g13.set_lcd_color(r, g, b).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?)?;
|
||||||
|
|
||||||
|
g13_table.set("display_width", G13_LCD_COLUMNS)?;
|
||||||
|
g13_table.set("display_height", G13_LCD_ROWS)?;
|
||||||
|
|
||||||
|
globals.set("g13", g13_table)?;
|
||||||
|
|
||||||
|
// load all files from dir `./scripts` for now, user configurable later or ~/.config/g13-os/*.<lua[u]>
|
||||||
|
// for now, just main.luau
|
||||||
|
let main = fs::read_to_string("./scripts/main.luau")?;
|
||||||
|
|
||||||
|
lua.load(main).set_name("main.luau").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;
|
||||||
|
loop {
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
delta = (Instant::now() - start).as_secs_f32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -28,7 +28,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let mut _g13 = g13.clone();
|
let mut _g13 = g13.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let character_style = MonoTextStyle::new(&FONT_10X20, BinaryColor::On);
|
let character_style_time = MonoTextStyle::new(&FONT_10X20, BinaryColor::On);
|
||||||
|
let character_style_date = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||||
let textstyle = TextStyleBuilder::new()
|
let textstyle = TextStyleBuilder::new()
|
||||||
.alignment(Alignment::Center)
|
.alignment(Alignment::Center)
|
||||||
.baseline(embedded_graphics::text::Baseline::Middle)
|
.baseline(embedded_graphics::text::Baseline::Middle)
|
||||||
@@ -39,21 +40,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let now = OffsetDateTime::now_utc().to_offset(offset!(+1)); // GMT+1
|
let now = OffsetDateTime::now_utc().to_offset(offset!(+1)); // GMT+1
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
let string = format!(
|
let time = format!(
|
||||||
"{:0>2}:{:0>2}:{:0>2}",
|
"{:0>2}:{:0>2}:{:0>2}",
|
||||||
now.hour(),
|
now.hour(),
|
||||||
now.minute(),
|
now.minute(),
|
||||||
now.second()
|
now.second()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let date = format!("{}, {} {}", now.weekday(), now.day(), now.month());
|
||||||
|
|
||||||
_g13.clear(BinaryColor::Off).unwrap();
|
_g13.clear(BinaryColor::Off).unwrap();
|
||||||
Text::with_text_style(
|
Text::with_text_style(
|
||||||
&string,
|
&time,
|
||||||
Point::new(
|
Point::new(
|
||||||
(G13_LCD_COLUMNS as f64 / 2.0) as i32,
|
(G13_LCD_COLUMNS as f64 / 2.0) as i32,
|
||||||
(G13_LCD_ROWS as f64 / 2.0) as i32,
|
(G13_LCD_ROWS as f64 / 2.0) as i32 - 8,
|
||||||
),
|
),
|
||||||
character_style,
|
character_style_time,
|
||||||
|
textstyle,
|
||||||
|
)
|
||||||
|
.draw(&mut _g13)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Text::with_text_style(
|
||||||
|
&date,
|
||||||
|
Point::new(
|
||||||
|
(G13_LCD_COLUMNS as f64 / 2.0) as i32,
|
||||||
|
(G13_LCD_ROWS as f64 / 2.0) as i32 + 8,
|
||||||
|
),
|
||||||
|
character_style_date,
|
||||||
textstyle,
|
textstyle,
|
||||||
)
|
)
|
||||||
.draw(&mut _g13)
|
.draw(&mut _g13)
|
||||||
|
|||||||
43
scripts/main.luau
Normal file
43
scripts/main.luau
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name = "DVD"
|
||||||
|
authors = {"AviiNL"}
|
||||||
|
description = "Bouncing 'dvd' Logo"
|
||||||
|
|
||||||
|
local width = g13.display_width
|
||||||
|
local height = g13.display_height
|
||||||
|
|
||||||
|
local x = 22.0
|
||||||
|
local y = 6.0
|
||||||
|
|
||||||
|
local x_direction = 1
|
||||||
|
local y_direction = 1
|
||||||
|
|
||||||
|
local speed = 20
|
||||||
|
|
||||||
|
local size = 3
|
||||||
|
|
||||||
|
function update(delta: number)
|
||||||
|
x = x + speed * delta * x_direction
|
||||||
|
y = y + speed * delta * y_direction
|
||||||
|
|
||||||
|
if x <= size or x >= width - size then
|
||||||
|
x_direction = -x_direction
|
||||||
|
end
|
||||||
|
|
||||||
|
if y <= size or y >= height - size then
|
||||||
|
y_direction = -y_direction
|
||||||
|
end
|
||||||
|
|
||||||
|
color_x = (x / width) * 255
|
||||||
|
color_y = (y / height) * 255
|
||||||
|
color_z = 255 - (color_x + color_y) / 2
|
||||||
|
|
||||||
|
g13.set_color(color_x/2, color_y/2, color_z/2)
|
||||||
|
|
||||||
|
g13.clear()
|
||||||
|
|
||||||
|
for sy = -size,size do
|
||||||
|
for sx = -size,size do
|
||||||
|
g13.set_pixel(x + sx, y + sy, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user