Animatrix: simulators, add features

This commit is contained in:
Luke D. Jones
2023-06-25 18:29:19 +12:00
parent 3d6d92ae7d
commit 8b77078a6f
8 changed files with 50 additions and 24 deletions

View File

@@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Pixel gifs - Pixel gifs
- Power options - Power options
- Builtin animations - Builtin animations
- In-progress simulators for GA402, GU604 animatrix - In-progress simulators for GA402, GU604 animatrix, optional build and takes a single arg
- Add `model_override` option to anime config, this is handy for forcing a model for "Unknown" anime, and for simulators - Add `model_override` option to anime config, this is handy for forcing a model for "Unknown" anime, and for simulators
### Changed ### Changed
- Move FX506HC to FX506H in arua DB to catch full series of this range - Move FX506HC to FX506H in arua DB to catch full series of this range

View File

@@ -1,10 +1,13 @@
use gumdrop::Options; use gumdrop::Options;
use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness}; use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use rog_anime::AnimeType;
#[derive(Options)] #[derive(Options)]
pub struct AnimeCommand { pub struct AnimeCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
pub help: bool, pub help: bool,
#[options(meta = "", help = "override the display type")]
pub override_type: Option<AnimeType>,
#[options(meta = "", help = "enable/disable the display")] #[options(meta = "", help = "enable/disable the display")]
pub enable_display: Option<bool>, pub enable_display: Option<bool>,
#[options(meta = "", help = "enable/disable the builtin run/powersave animation")] #[options(meta = "", help = "enable/disable the builtin run/powersave animation")]

View File

@@ -9,7 +9,7 @@ use aura_cli::{LedPowerCommand1, LedPowerCommand2};
use gumdrop::{Opt, Options}; use gumdrop::{Opt, Options};
use profiles_cli::{FanCurveCommand, ProfileCommand}; use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::usb::get_anime_type; use rog_anime::usb::get_anime_type;
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2}; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, Vec2};
use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev}; use rog_aura::usb::{AuraDevRog1, AuraDevRog2, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{self, AuraEffect}; use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClientBlocking; use rog_dbus::RogDbusClientBlocking;
@@ -248,15 +248,21 @@ fn handle_anime(
verify_brightness(bright); verify_brightness(bright);
dbus.proxies().anime().set_image_brightness(bright)?; dbus.proxies().anime().set_image_brightness(bright)?;
} }
let mut anime_type = get_anime_type()?;
if let AnimeType::Unknown = anime_type {
if let Some(model) = cmd.override_type {
anime_type = model;
}
}
if cmd.clear { if cmd.clear {
let anime_type = get_anime_type()?;
let data = vec![255u8; anime_type.data_length()]; let data = vec![255u8; anime_type.data_length()];
let tmp = AnimeDataBuffer::from_vec(anime_type, data)?; let tmp = AnimeDataBuffer::from_vec(anime_type, data)?;
dbus.proxies().anime().write(tmp)?; dbus.proxies().anime().write(tmp)?;
} }
if let Some(action) = cmd.command.as_ref() { if let Some(action) = cmd.command.as_ref() {
let anime_type = get_anime_type()?;
match action { match action {
AnimeActions::Image(image) => { AnimeActions::Image(image) => {
if image.help_requested() || image.path.is_empty() { if image.help_requested() || image.path.is_empty() {

View File

@@ -77,6 +77,7 @@ impl CtrlAnime {
let mut anime_type = get_anime_type()?; let mut anime_type = get_anime_type()?;
if let AnimeType::Unknown = anime_type { if let AnimeType::Unknown = anime_type {
if let Some(model) = config.model_override { if let Some(model) = config.model_override {
warn!("Overriding the Animatrix type as {model:?}");
anime_type = model; anime_type = model;
} }
} }

View File

@@ -1,4 +1,5 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use std::str::FromStr;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@@ -53,6 +54,19 @@ pub enum AnimeType {
Unknown, Unknown,
} }
impl FromStr for AnimeType {
type Err = AnimeError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(match s {
"ga401" | "GA401" => Self::GA401,
"ga402" | "GA402" => Self::GA402,
"gu604" | "GU604" => Self::GU604,
_ => Self::Unknown,
})
}
}
impl AnimeType { impl AnimeType {
/// The width of diagonal images /// The width of diagonal images
pub fn width(&self) -> usize { pub fn width(&self) -> usize {

View File

@@ -156,7 +156,7 @@ pub fn get_anime_type() -> Result<AnimeType, AnimeError> {
return Ok(AnimeType::GU604); return Ok(AnimeType::GU604);
} }
log::warn!("AniMe Matrix device found but not yet supported, will default to a GA402 layout"); log::warn!("AniMe Matrix device found but not yet supported, will default to a GA402 layout");
Ok(AnimeType::GA402) Ok(AnimeType::Unknown)
} }
/// Get the two device initialization packets. These are required for device /// Get the two device initialization packets. These are required for device

View File

@@ -1,3 +1,5 @@
use rog_anime::AnimeType;
use self::map_ga401::GA401; use self::map_ga401::GA401;
use self::map_ga402::GA402; use self::map_ga402::GA402;
use self::map_gu604::GU604; use self::map_gu604::GU604;
@@ -6,12 +8,6 @@ mod map_ga401;
mod map_ga402; mod map_ga402;
mod map_gu604; mod map_gu604;
pub enum Model {
GA401,
GA402,
GU604,
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Row( pub struct Row(
/// The USB packet index, this is mapped to the 4th byte (idx = 3) and is /// The USB packet index, this is mapped to the 4th byte (idx = 3) and is
@@ -41,17 +37,17 @@ pub struct AniMatrix {
} }
impl AniMatrix { impl AniMatrix {
pub fn new(model: Model) -> Self { pub fn new(model: AnimeType) -> Self {
let led_shape = match model { let led_shape = match model {
Model::GA401 => LedShape { AnimeType::GA401 => LedShape {
vertical: 2, vertical: 2,
horizontal: 5, horizontal: 5,
}, },
Model::GA402 => LedShape { AnimeType::GA402 | AnimeType::Unknown => LedShape {
vertical: 2, vertical: 2,
horizontal: 5, horizontal: 5,
}, },
Model::GU604 => LedShape { AnimeType::GU604 => LedShape {
vertical: 2, vertical: 2,
horizontal: 5, horizontal: 5,
}, },
@@ -59,9 +55,9 @@ impl AniMatrix {
// Do a hard mapping of each (derived from wireshardk captures) // Do a hard mapping of each (derived from wireshardk captures)
let rows = match model { let rows = match model {
Model::GA401 => GA401.to_vec(), AnimeType::GA401 => GA401.to_vec(),
Model::GA402 => GA402.to_vec(), AnimeType::GA402 | AnimeType::Unknown => GA402.to_vec(),
Model::GU604 => GU604.to_vec(), AnimeType::GU604 => GU604.to_vec(),
}; };
Self { rows, led_shape } Self { rows, led_shape }

View File

@@ -1,8 +1,10 @@
use std::env;
use std::error::Error; use std::error::Error;
use std::str::FromStr;
use log::error; use log::error;
use rog_anime::usb::{PROD_ID, VENDOR_ID}; use rog_anime::usb::{PROD_ID, VENDOR_ID};
use rog_anime::USB_PREFIX2; use rog_anime::{AnimeType, USB_PREFIX2};
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
use sdl2::pixels::Color; use sdl2::pixels::Color;
@@ -19,7 +21,7 @@ pub struct VirtAnimeMatrix {
} }
impl VirtAnimeMatrix { impl VirtAnimeMatrix {
pub fn new(model: Model) -> Self { pub fn new(model: AnimeType) -> Self {
VirtAnimeMatrix { VirtAnimeMatrix {
buffer: [0; 640], buffer: [0; 640],
animatrix: AniMatrix::new(model), animatrix: AniMatrix::new(model),
@@ -110,6 +112,13 @@ impl VirtAnimeMatrix {
} }
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
if args.len() <= 1 {
println!("Must supply arg, one of <GA401, GA402, GU604>");
return Ok(());
}
let anime_type = AnimeType::from_str(&args[1])?;
let sdl_context = sdl2::init().unwrap(); let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap(); let video_subsystem = sdl_context.video().unwrap();
@@ -121,7 +130,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut canvas = window.into_canvas().build().unwrap(); let mut canvas = window.into_canvas().build().unwrap();
let mut dev = VirtAnimeMatrix::new(Model::GU604); let mut dev = VirtAnimeMatrix::new(anime_type);
canvas.set_draw_color(Color::RGB(0, 0, 0)); canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear(); canvas.clear();
@@ -130,7 +139,6 @@ fn main() -> Result<(), Box<dyn Error>> {
dev.read(); // it's blocking, and damned hard to sync with arc/mutex dev.read(); // it's blocking, and damned hard to sync with arc/mutex
// let one = dev.buffer[0..7] != USB_PREFIX2; // let one = dev.buffer[0..7] != USB_PREFIX2;
let index = dev.buffer[3]; let index = dev.buffer[3];
println!("{:02x}", index);
let w = dev.animatrix.led_shape().horizontal * 6; let w = dev.animatrix.led_shape().horizontal * 6;
let h = dev.animatrix.led_shape().vertical * 6; let h = dev.animatrix.led_shape().vertical * 6;
@@ -147,7 +155,6 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
} }
for (x_count, b) in dev.buffer[start..=end].iter().enumerate() { for (x_count, b) in dev.buffer[start..=end].iter().enumerate() {
// print!("{b},");
canvas.set_draw_color(Color::RGB(*b as u8, *b as u8, *b as u8)); canvas.set_draw_color(Color::RGB(*b as u8, *b as u8, *b as u8));
let x: i32 = w + x_count as i32 * w let x: i32 = w + x_count as i32 * w
@@ -162,7 +169,6 @@ fn main() -> Result<(), Box<dyn Error>> {
.fill_rect(Rect::new(x, y, w as u32, h as u32)) .fill_rect(Rect::new(x, y, w as u32, h as u32))
.unwrap(); .unwrap();
} }
// println!();
} }
} }