Compare commits

..

12 Commits

Author SHA1 Message Date
Ghoul
da7395b9df Merge branch 'main' into 'devel'
Draft: Add custom image and gif support for G835L

See merge request asus-linux/asusctl!249
2026-01-21 20:56:13 +00:00
Yaseen
ca65efd51b fix: G835L animatrix edge and gif tests fixed to work with last modified image and gif 2026-01-22 01:54:49 +05:00
Yaseen
cc3de63a92 fix(simulator): add better error message when virtual device creation fails 2026-01-22 01:32:56 +05:00
Yaseen
d681049ca8 feat: dump untested G835L simulator map with todo to fix simulator
simulator doesn't seem to be working right now. fix later and test this
properly
2026-01-22 01:32:02 +05:00
Yaseen
514aa7c179 fix(anime_cli): default gif loops to infinite 2026-01-22 00:45:33 +05:00
Yaseen
4b42071a77 chore: test case for G835L GIF animation 2026-01-22 00:14:00 +05:00
Yaseen
ce9f85733e Feat: full image support for G835L and proper test written 2026-01-21 23:52:53 +05:00
Yaseen
73a10ddf52 wip: support for G835L 2026-01-21 23:14:04 +05:00
Yaseen
7cf6c477eb feat: add G835L diagonal test images 2026-01-21 20:00:15 +05:00
Yaseen
b9c251d403 feat: add anime-led-scan tool
Usage: cargo run --example anime-led-scan
2026-01-21 20:00:03 +05:00
Yaseen
6ef977f6ae chore: fix comments documenting Scar 18 implementation plan
Removed comments mentioning monochrome/grayscale LEDs added under the
impression G14 and M16 used to have RGB LED lighting. This assumption
has been proved false.

Additionally added agent md files to gitignore and uncommented G635L
width as even a random value is likely necessary
2026-01-21 16:27:33 +05:00
Yaseen
d006837198 chore: add implementation planning for G635L/G835L support 2026-01-21 01:12:14 +05:00
3 changed files with 12 additions and 27 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

View File

@@ -121,6 +121,8 @@ impl AnimeImage {
match anime_type {
AnimeType::GA401 => 0.8,
AnimeType::GU604 => 0.78,
// TODO: Measure physical display and calculate correct value
AnimeType::G835L => 0.77,
_ => 0.77,
}
}
@@ -137,8 +139,12 @@ impl AnimeImage {
fn scale_y(anime_type: AnimeType) -> f32 {
match anime_type {
AnimeType::GA401 => 0.3,
AnimeType::GA402 => 0.283,
_ => 0.28,
AnimeType::GU604 => 0.28,
// TODO: Calculate correct values for G635L and G835L.
// Known values for G835L diagonal W*H is 68*34
AnimeType::G635L => 0.28,
AnimeType::G835L => 0.28,
_ => 0.283,
}
}
@@ -161,7 +167,7 @@ impl AnimeImage {
/// \ |
/// |----|\ |
/// ^ ------+
/// first_x
/// first_x (grows as y increases)
/// ```
///
/// For G835L (inverted pattern - triangle grows then rectangle shifts):
@@ -270,7 +276,8 @@ impl AnimeImage {
// 33.0 = Longest row LED count (physical) plus half-pixel offset
AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type),
AnimeType::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type),
AnimeType::G835L => (33.0 + 0.5) * Self::scale_x(anime_type),
// G835L: max 15 LEDs wide + rectangle shift (~20 pixels) + stagger
AnimeType::G835L => (35.0 + 0.5) * Self::scale_x(anime_type),
_ => (35.0 + 0.5) * Self::scale_x(anime_type),
}
}
@@ -441,35 +448,13 @@ impl AnimeImage {
let transform =
Mat3::from_scale_angle_translation(self.scale, self.angle, self.translation);
let pos_in_leds = Mat3::from_translation(self.led_center());
let pos_in_leds = Mat3::from_translation(Vec2::new(20.0, 20.0));
// Get LED-to-image coords
let led_from_px = pos_in_leds * led_from_cm * transform * cm_from_px * center;
led_from_px.inverse()
}
fn led_center(&self) -> Vec2 {
if self.anime_type != AnimeType::G835L {
return Vec2::new(20.0, 20.0);
}
let mut min = Vec2::splat(f32::INFINITY);
let mut max = Vec2::splat(f32::NEG_INFINITY);
for led in self.led_pos.iter().flatten() {
let pos = Vec2::new(led.x(), led.y());
min = min.min(pos);
max = max.max(pos);
}
if min.x.is_finite() {
let mut center = (min + max) * 0.5;
center.y += 1.0;
center
} else {
Vec2::new(20.0, 20.0)
}
}
/// Generate the base image from inputs. The result can be displayed as is
/// or updated via scale, position, or angle then displayed again after
/// `update()`.