diff --git a/CHANGELOG.md b/CHANGELOG.md index 540a17db..053051c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased ] +### Changed +- Data for anime-matrix now requires passing the laptop model as enum + ### Added - Support for GA503R LED modes ### Changed diff --git a/Cargo.lock b/Cargo.lock index 05eddef7..2d39f79a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1027,6 +1027,8 @@ dependencies = [ "png_pong", "serde", "serde_derive", + "sysfs-class", + "udev", "zvariant", ] diff --git a/asusctl/examples/anime-diag-png.rs b/asusctl/examples/anime-diag-png.rs index 2fe4303d..25c617a7 100644 --- a/asusctl/examples/anime-diag-png.rs +++ b/asusctl/examples/anime-diag-png.rs @@ -1,6 +1,6 @@ use std::{env, error::Error, path::Path, process::exit}; -use rog_anime::{AnimeDataBuffer, AnimeDiagonal}; +use rog_anime::{usb::get_anime_type, AnimeDiagonal, AnimeType}; use rog_dbus::RogDbusClientBlocking; fn main() -> Result<(), Box> { @@ -13,13 +13,19 @@ fn main() -> Result<(), Box> { exit(-1); } - let matrix = - AnimeDiagonal::from_png(Path::new(&args[1]), None, args[2].parse::().unwrap())?; + let matrix = AnimeDiagonal::from_png( + Path::new(&args[1]), + None, + args[2].parse::().unwrap(), + AnimeType::GA401, + )?; + + let anime_type = get_anime_type()?; client .proxies() .anime() - .write(::from(&matrix)) + .write(matrix.into_data_buffer(anime_type)) .unwrap(); Ok(()) diff --git a/asusctl/examples/anime-diag.rs b/asusctl/examples/anime-diag.rs index 0a9a97b4..9874b1bc 100644 --- a/asusctl/examples/anime-diag.rs +++ b/asusctl/examples/anime-diag.rs @@ -1,6 +1,6 @@ use std::{thread::sleep, time::Duration}; -use rog_anime::{AnimeDataBuffer, AnimeDiagonal}; +use rog_anime::{usb::get_anime_type, AnimeDiagonal, AnimeType}; use rog_dbus::RogDbusClientBlocking; // In usable data: @@ -12,7 +12,7 @@ fn main() { let (client, _) = RogDbusClientBlocking::new().unwrap(); for step in (2..50).rev() { - let mut matrix = AnimeDiagonal::new(None); + let mut matrix = AnimeDiagonal::new(AnimeType::GA401, None); for c in (0..60).into_iter().step_by(step) { for i in matrix.get_mut().iter_mut() { i[c] = 50; @@ -25,8 +25,12 @@ fn main() { } } - let m = ::from(&matrix); - client.proxies().anime().write(m).unwrap(); + let anime_type = get_anime_type().unwrap(); + client + .proxies() + .anime() + .write(matrix.into_data_buffer(anime_type)) + .unwrap(); sleep(Duration::from_millis(300)); } } diff --git a/asusctl/examples/anime-gif.rs b/asusctl/examples/anime-gif.rs index 045b1592..79deecf0 100644 --- a/asusctl/examples/anime-gif.rs +++ b/asusctl/examples/anime-gif.rs @@ -1,6 +1,6 @@ use std::{env, path::Path, thread::sleep}; -use rog_anime::{ActionData, ActionLoader, Sequences}; +use rog_anime::{usb::get_anime_type, ActionData, ActionLoader, Sequences}; use rog_dbus::RogDbusClientBlocking; fn main() { @@ -14,7 +14,8 @@ fn main() { let path = Path::new(&args[1]); let brightness = args[2].parse::().unwrap(); - let mut seq = Sequences::new(); + let anime_type = get_anime_type().unwrap(); + let mut seq = Sequences::new(anime_type); seq.insert( 0, &ActionLoader::AsusAnimation { diff --git a/asusctl/examples/anime-grid.rs b/asusctl/examples/anime-grid.rs index a862edb6..ea532899 100644 --- a/asusctl/examples/anime-grid.rs +++ b/asusctl/examples/anime-grid.rs @@ -1,4 +1,4 @@ -use rog_anime::{AnimeDataBuffer, AnimeGrid}; +use rog_anime::{usb::get_anime_type, AnimeDataBuffer, AnimeGrid}; use rog_dbus::RogDbusClientBlocking; // In usable data: @@ -8,7 +8,8 @@ use rog_dbus::RogDbusClientBlocking; fn main() { let (client, _) = RogDbusClientBlocking::new().unwrap(); - let mut matrix = AnimeGrid::new(None); + let anime_type = get_anime_type().unwrap(); + let mut matrix = AnimeGrid::new(anime_type); let tmp = matrix.get_mut(); let mut i = 0; diff --git a/asusctl/examples/anime-outline.rs b/asusctl/examples/anime-outline.rs index 88602872..f7a0fba9 100644 --- a/asusctl/examples/anime-outline.rs +++ b/asusctl/examples/anime-outline.rs @@ -1,4 +1,4 @@ -use rog_anime::AnimeDataBuffer; +use rog_anime::{usb::get_anime_type, AnimeDataBuffer}; use rog_dbus::RogDbusClientBlocking; // In usable data: @@ -6,123 +6,124 @@ use rog_dbus::RogDbusClientBlocking; fn main() { let (client, _) = RogDbusClientBlocking::new().unwrap(); - let mut matrix = AnimeDataBuffer::new(); - matrix.get_mut()[1] = 100; // start = 1 - for n in matrix.get_mut()[2..32].iter_mut() { + let anime_type = get_anime_type().unwrap(); + let mut matrix = AnimeDataBuffer::new(anime_type); + matrix.data_mut()[1] = 100; // start = 1 + for n in matrix.data_mut()[2..32].iter_mut() { *n = 250; } - matrix.get_mut()[32] = 100; // end - matrix.get_mut()[34] = 100; // start x = 0 - matrix.get_mut()[66] = 100; // end - matrix.get_mut()[69] = 100; // start x = 1 - matrix.get_mut()[101] = 100; // end - matrix.get_mut()[102] = 100; // start - matrix.get_mut()[134] = 100; // end - matrix.get_mut()[137] = 100; // start - matrix.get_mut()[169] = 100; // end - matrix.get_mut()[170] = 100; // start - matrix.get_mut()[202] = 100; // end - matrix.get_mut()[204] = 100; // start - matrix.get_mut()[236] = 100; // end - matrix.get_mut()[237] = 100; // start - matrix.get_mut()[268] = 100; // end - matrix.get_mut()[270] = 100; // start - matrix.get_mut()[301] = 100; // end - matrix.get_mut()[302] = 100; // start - matrix.get_mut()[332] = 100; // end - matrix.get_mut()[334] = 100; // start - matrix.get_mut()[364] = 100; // end - matrix.get_mut()[365] = 100; // start - matrix.get_mut()[394] = 100; // end - matrix.get_mut()[396] = 100; // start - matrix.get_mut()[425] = 100; // end - matrix.get_mut()[426] = 100; // start - matrix.get_mut()[454] = 100; // end - matrix.get_mut()[456] = 100; // start - matrix.get_mut()[484] = 100; // end - matrix.get_mut()[485] = 100; // start - matrix.get_mut()[512] = 100; // end - matrix.get_mut()[514] = 100; // start - matrix.get_mut()[541] = 100; // end - matrix.get_mut()[542] = 100; // start - matrix.get_mut()[568] = 100; // end - matrix.get_mut()[570] = 100; // start - matrix.get_mut()[596] = 100; // end - matrix.get_mut()[597] = 100; // start - matrix.get_mut()[622] = 100; // end - matrix.get_mut()[624] = 100; // start - matrix.get_mut()[649] = 100; // end - matrix.get_mut()[650] = 100; // start - matrix.get_mut()[674] = 100; // end - matrix.get_mut()[676] = 100; // start - matrix.get_mut()[700] = 100; // end - matrix.get_mut()[701] = 100; // start - matrix.get_mut()[724] = 100; // end - matrix.get_mut()[726] = 100; // start - matrix.get_mut()[749] = 100; // end - matrix.get_mut()[750] = 100; // start - matrix.get_mut()[772] = 100; // end - matrix.get_mut()[774] = 100; // start - matrix.get_mut()[796] = 100; // end - matrix.get_mut()[797] = 100; // start - matrix.get_mut()[818] = 100; // end - matrix.get_mut()[820] = 100; // start - matrix.get_mut()[841] = 100; // end - matrix.get_mut()[842] = 100; // start - matrix.get_mut()[862] = 100; // end - matrix.get_mut()[864] = 100; // start - matrix.get_mut()[884] = 100; // end - matrix.get_mut()[885] = 100; // start - matrix.get_mut()[904] = 100; // end - matrix.get_mut()[906] = 100; // start - matrix.get_mut()[925] = 100; // end - matrix.get_mut()[926] = 100; // start - matrix.get_mut()[944] = 100; // end - matrix.get_mut()[946] = 100; // start - matrix.get_mut()[964] = 100; // end - matrix.get_mut()[965] = 100; // start - matrix.get_mut()[982] = 100; // end - matrix.get_mut()[984] = 100; // start - matrix.get_mut()[1001] = 100; // end - matrix.get_mut()[1002] = 100; // start - matrix.get_mut()[1018] = 100; // end - matrix.get_mut()[1020] = 100; // start - matrix.get_mut()[1036] = 100; // end - matrix.get_mut()[1037] = 100; // start - matrix.get_mut()[1052] = 100; // end - matrix.get_mut()[1054] = 100; // start - matrix.get_mut()[1069] = 100; // end - matrix.get_mut()[1070] = 100; // start - matrix.get_mut()[1084] = 100; // end - matrix.get_mut()[1086] = 100; // start - matrix.get_mut()[1100] = 100; // end - matrix.get_mut()[1101] = 100; // start - matrix.get_mut()[1114] = 100; // end - matrix.get_mut()[1116] = 100; // start - matrix.get_mut()[1129] = 100; // end - matrix.get_mut()[1130] = 100; // start - matrix.get_mut()[1142] = 100; // end - matrix.get_mut()[1144] = 100; // start - matrix.get_mut()[1156] = 100; // end - matrix.get_mut()[1157] = 100; // start - matrix.get_mut()[1168] = 100; // end - matrix.get_mut()[1170] = 100; // start - matrix.get_mut()[1181] = 100; // end - matrix.get_mut()[1182] = 100; // start - matrix.get_mut()[1192] = 100; // end - matrix.get_mut()[1194] = 100; // start - matrix.get_mut()[1204] = 100; // end - matrix.get_mut()[1205] = 100; // start - matrix.get_mut()[1214] = 100; // end - matrix.get_mut()[1216] = 100; // start - matrix.get_mut()[1225] = 100; // end - matrix.get_mut()[1226] = 100; // start - matrix.get_mut()[1234] = 100; // end - matrix.get_mut()[1236] = 100; // start - for n in matrix.get_mut()[1237..1244].iter_mut() { + matrix.data_mut()[32] = 100; // end + matrix.data_mut()[34] = 100; // start x = 0 + matrix.data_mut()[66] = 100; // end + matrix.data_mut()[69] = 100; // start x = 1 + matrix.data_mut()[101] = 100; // end + matrix.data_mut()[102] = 100; // start + matrix.data_mut()[134] = 100; // end + matrix.data_mut()[137] = 100; // start + matrix.data_mut()[169] = 100; // end + matrix.data_mut()[170] = 100; // start + matrix.data_mut()[202] = 100; // end + matrix.data_mut()[204] = 100; // start + matrix.data_mut()[236] = 100; // end + matrix.data_mut()[237] = 100; // start + matrix.data_mut()[268] = 100; // end + matrix.data_mut()[270] = 100; // start + matrix.data_mut()[301] = 100; // end + matrix.data_mut()[302] = 100; // start + matrix.data_mut()[332] = 100; // end + matrix.data_mut()[334] = 100; // start + matrix.data_mut()[364] = 100; // end + matrix.data_mut()[365] = 100; // start + matrix.data_mut()[394] = 100; // end + matrix.data_mut()[396] = 100; // start + matrix.data_mut()[425] = 100; // end + matrix.data_mut()[426] = 100; // start + matrix.data_mut()[454] = 100; // end + matrix.data_mut()[456] = 100; // start + matrix.data_mut()[484] = 100; // end + matrix.data_mut()[485] = 100; // start + matrix.data_mut()[512] = 100; // end + matrix.data_mut()[514] = 100; // start + matrix.data_mut()[541] = 100; // end + matrix.data_mut()[542] = 100; // start + matrix.data_mut()[568] = 100; // end + matrix.data_mut()[570] = 100; // start + matrix.data_mut()[596] = 100; // end + matrix.data_mut()[597] = 100; // start + matrix.data_mut()[622] = 100; // end + matrix.data_mut()[624] = 100; // start + matrix.data_mut()[649] = 100; // end + matrix.data_mut()[650] = 100; // start + matrix.data_mut()[674] = 100; // end + matrix.data_mut()[676] = 100; // start + matrix.data_mut()[700] = 100; // end + matrix.data_mut()[701] = 100; // start + matrix.data_mut()[724] = 100; // end + matrix.data_mut()[726] = 100; // start + matrix.data_mut()[749] = 100; // end + matrix.data_mut()[750] = 100; // start + matrix.data_mut()[772] = 100; // end + matrix.data_mut()[774] = 100; // start + matrix.data_mut()[796] = 100; // end + matrix.data_mut()[797] = 100; // start + matrix.data_mut()[818] = 100; // end + matrix.data_mut()[820] = 100; // start + matrix.data_mut()[841] = 100; // end + matrix.data_mut()[842] = 100; // start + matrix.data_mut()[862] = 100; // end + matrix.data_mut()[864] = 100; // start + matrix.data_mut()[884] = 100; // end + matrix.data_mut()[885] = 100; // start + matrix.data_mut()[904] = 100; // end + matrix.data_mut()[906] = 100; // start + matrix.data_mut()[925] = 100; // end + matrix.data_mut()[926] = 100; // start + matrix.data_mut()[944] = 100; // end + matrix.data_mut()[946] = 100; // start + matrix.data_mut()[964] = 100; // end + matrix.data_mut()[965] = 100; // start + matrix.data_mut()[982] = 100; // end + matrix.data_mut()[984] = 100; // start + matrix.data_mut()[1001] = 100; // end + matrix.data_mut()[1002] = 100; // start + matrix.data_mut()[1018] = 100; // end + matrix.data_mut()[1020] = 100; // start + matrix.data_mut()[1036] = 100; // end + matrix.data_mut()[1037] = 100; // start + matrix.data_mut()[1052] = 100; // end + matrix.data_mut()[1054] = 100; // start + matrix.data_mut()[1069] = 100; // end + matrix.data_mut()[1070] = 100; // start + matrix.data_mut()[1084] = 100; // end + matrix.data_mut()[1086] = 100; // start + matrix.data_mut()[1100] = 100; // end + matrix.data_mut()[1101] = 100; // start + matrix.data_mut()[1114] = 100; // end + matrix.data_mut()[1116] = 100; // start + matrix.data_mut()[1129] = 100; // end + matrix.data_mut()[1130] = 100; // start + matrix.data_mut()[1142] = 100; // end + matrix.data_mut()[1144] = 100; // start + matrix.data_mut()[1156] = 100; // end + matrix.data_mut()[1157] = 100; // start + matrix.data_mut()[1168] = 100; // end + matrix.data_mut()[1170] = 100; // start + matrix.data_mut()[1181] = 100; // end + matrix.data_mut()[1182] = 100; // start + matrix.data_mut()[1192] = 100; // end + matrix.data_mut()[1194] = 100; // start + matrix.data_mut()[1204] = 100; // end + matrix.data_mut()[1205] = 100; // start + matrix.data_mut()[1214] = 100; // end + matrix.data_mut()[1216] = 100; // start + matrix.data_mut()[1225] = 100; // end + matrix.data_mut()[1226] = 100; // start + matrix.data_mut()[1234] = 100; // end + matrix.data_mut()[1236] = 100; // start + for n in matrix.data_mut()[1237..1244].iter_mut() { *n = 250; } - matrix.get_mut()[1244] = 100; // end + matrix.data_mut()[1244] = 100; // end println!("{:?}", &matrix); client.proxies().anime().write(matrix).unwrap(); diff --git a/asusctl/examples/anime-png.rs b/asusctl/examples/anime-png.rs index 69cd8b9e..99c24656 100644 --- a/asusctl/examples/anime-png.rs +++ b/asusctl/examples/anime-png.rs @@ -1,6 +1,7 @@ use std::{env, error::Error, path::Path, process::exit}; use rog_anime::{ + usb::get_anime_type, AnimeDataBuffer, {AnimeImage, Vec2}, }; use rog_dbus::RogDbusClientBlocking; @@ -15,6 +16,7 @@ fn main() -> Result<(), Box> { exit(-1); } + let anime_type = get_anime_type()?; let matrix = AnimeImage::from_png( Path::new(&args[1]), args[2].parse::().unwrap(), @@ -24,6 +26,7 @@ fn main() -> Result<(), Box> { args[5].parse::().unwrap(), ), args[6].parse::().unwrap(), + anime_type, )?; client diff --git a/asusctl/examples/anime-spinning.rs b/asusctl/examples/anime-spinning.rs index 6f1d4db0..0beb53ca 100644 --- a/asusctl/examples/anime-spinning.rs +++ b/asusctl/examples/anime-spinning.rs @@ -3,6 +3,7 @@ use std::{ }; use rog_anime::{ + usb::get_anime_type, AnimeDataBuffer, {AnimeImage, Vec2}, }; use rog_dbus::RogDbusClientBlocking; @@ -17,6 +18,7 @@ fn main() -> Result<(), Box> { exit(-1); } + let anime_type = get_anime_type()?; let mut matrix = AnimeImage::from_png( Path::new(&args[1]), args[2].parse::().unwrap(), @@ -26,6 +28,7 @@ fn main() -> Result<(), Box> { args[5].parse::().unwrap(), ), args[6].parse::().unwrap(), + anime_type, )?; loop { diff --git a/asusctl/src/main.rs b/asusctl/src/main.rs index 8702ce7f..331980fc 100644 --- a/asusctl/src/main.rs +++ b/asusctl/src/main.rs @@ -7,6 +7,7 @@ use gumdrop::{Opt, Options}; use anime_cli::{AnimeActions, AnimeCommand}; use profiles_cli::{FanCurveCommand, ProfileCommand}; +use rog_anime::usb::get_anime_type; use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2}; use rog_aura::usb::AuraControl; use rog_aura::{self, AuraEffect}; @@ -234,6 +235,7 @@ fn handle_anime( dbus.proxies().anime().set_brightness(bright as f32)? } if let Some(action) = cmd.command.as_ref() { + let anime_type = get_anime_type()?; match action { AnimeActions::Image(image) => { if image.help_requested() || image.path.is_empty() { @@ -250,6 +252,7 @@ fn handle_anime( image.angle, Vec2::new(image.x_pos, image.y_pos), image.bright, + anime_type, )?; dbus.proxies() @@ -265,11 +268,16 @@ fn handle_anime( std::process::exit(1); } - let matrix = AnimeDiagonal::from_png(Path::new(&image.path), None, image.bright)?; + let matrix = AnimeDiagonal::from_png( + Path::new(&image.path), + None, + image.bright, + anime_type, + )?; dbus.proxies() .anime() - .write(::from(&matrix))?; + .write(matrix.into_data_buffer(anime_type))?; } AnimeActions::Gif(gif) => { if gif.help_requested() || gif.path.is_empty() { @@ -287,6 +295,7 @@ fn handle_anime( Vec2::new(gif.x_pos, gif.y_pos), AnimTime::Count(1), gif.bright, + anime_type, )?; let mut loops = gif.loops as i32; @@ -316,6 +325,7 @@ fn handle_anime( Path::new(&gif.path), AnimTime::Count(1), gif.bright, + anime_type, )?; let mut loops = gif.loops as i32; diff --git a/daemon-user/src/daemon.rs b/daemon-user/src/daemon.rs index 67294c99..39c8c99f 100644 --- a/daemon-user/src/daemon.rs +++ b/daemon-user/src/daemon.rs @@ -1,3 +1,4 @@ +use rog_anime::usb::get_anime_type; use rog_dbus::RogDbusClientBlocking; use rog_user::{ ctrl_anime::{CtrlAnime, CtrlAnimeInner}, @@ -28,8 +29,9 @@ fn main() -> Result<(), Box> { let early_return = Arc::new(AtomicBool::new(false)); // Set up the anime data and run loop/thread if supported.anime_ctrl.0 { + let anime_type = get_anime_type()?; let anime_config = UserAnimeConfig::load_config(config.active_anime)?; - let anime = anime_config.create_anime()?; + let anime = anime_config.create_anime(anime_type)?; let anime_config = Arc::new(Mutex::new(anime_config)); executor diff --git a/daemon-user/src/user_config.rs b/daemon-user/src/user_config.rs index c0762604..5f424096 100644 --- a/daemon-user/src/user_config.rs +++ b/daemon-user/src/user_config.rs @@ -4,7 +4,7 @@ use std::{ time::Duration, }; -use rog_anime::{ActionLoader, AnimTime, Fade, Sequences, Vec2}; +use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences, Vec2}; use serde_derive::{Deserialize, Serialize}; use crate::error::Error; @@ -16,8 +16,8 @@ pub struct UserAnimeConfig { } impl UserAnimeConfig { - pub fn create_anime(&self) -> Result { - let mut seq = Sequences::new(); + pub fn create_anime(&self, anime_type: AnimeType) -> Result { + let mut seq = Sequences::new(anime_type); for (idx, action) in self.anime.iter().enumerate() { seq.insert(idx, action)?; diff --git a/daemon/src/ctrl_anime/config.rs b/daemon/src/ctrl_anime/config.rs index c18c4220..7d6a2a98 100644 --- a/daemon/src/ctrl_anime/config.rs +++ b/daemon/src/ctrl_anime/config.rs @@ -1,7 +1,7 @@ use crate::VERSION; use log::{error, info, warn}; -use rog_anime::Fade; use rog_anime::{error::AnimeError, ActionData, ActionLoader, AnimTime, Vec2}; +use rog_anime::{AnimeType, Fade}; use serde_derive::{Deserialize, Serialize}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; @@ -80,28 +80,32 @@ pub struct AnimeConfigCached { } impl AnimeConfigCached { - pub fn init_from_config(&mut self, config: &AnimeConfig) -> Result<(), AnimeError> { + pub fn init_from_config( + &mut self, + config: &AnimeConfig, + anime_type: AnimeType, + ) -> Result<(), AnimeError> { let mut sys = Vec::with_capacity(config.system.len()); for ani in config.system.iter() { - sys.push(ActionData::from_anime_action(ani)?); + sys.push(ActionData::from_anime_action(anime_type, ani)?); } self.system = sys; let mut boot = Vec::with_capacity(config.boot.len()); for ani in config.boot.iter() { - boot.push(ActionData::from_anime_action(ani)?); + boot.push(ActionData::from_anime_action(anime_type, ani)?); } self.boot = boot; let mut wake = Vec::with_capacity(config.wake.len()); for ani in config.wake.iter() { - wake.push(ActionData::from_anime_action(ani)?); + wake.push(ActionData::from_anime_action(anime_type, ani)?); } self.wake = wake; let mut shutdown = Vec::with_capacity(config.shutdown.len()); for ani in config.shutdown.iter() { - shutdown.push(ActionData::from_anime_action(ani)?); + shutdown.push(ActionData::from_anime_action(anime_type, ani)?); } self.shutdown = shutdown; Ok(()) diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index fef33c46..fed5a296 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -8,10 +8,10 @@ use logind_zbus::manager::ManagerProxy; use rog_anime::{ error::AnimeError, usb::{ - pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID, - VENDOR_ID, + find_node, get_anime_type, pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, + pkts_for_init, PROD_ID, VENDOR_ID, }, - ActionData, AnimeDataBuffer, AnimePacketType, ANIME_DATA_LEN, + ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, }; use rog_supported::AnimeSupportedFunctions; use rusb::{Device, DeviceHandle}; @@ -41,6 +41,7 @@ impl GetSupported for CtrlAnime { pub struct CtrlAnime { _node: String, + anime_type: AnimeType, handle: RefCell>, cache: AnimeConfigCached, config: AnimeConfig, @@ -53,15 +54,17 @@ pub struct CtrlAnime { impl CtrlAnime { #[inline] pub fn new(config: AnimeConfig) -> Result> { - let node = Self::find_node("193b")?; + let node = find_node("193b")?; + let anime_type = get_anime_type()?; let device = Self::get_dev_handle()?; info!("Device has an AniMe Matrix display"); let mut cache = AnimeConfigCached::default(); - cache.init_from_config(&config)?; + cache.init_from_config(&config, anime_type)?; let ctrl = CtrlAnime { _node: node, + anime_type, handle: RefCell::new(device), cache, config, @@ -73,34 +76,6 @@ impl CtrlAnime { Ok(ctrl) } - fn find_node(id_product: &str) -> Result { - let mut enumerator = udev::Enumerator::new().map_err(|err| { - warn!("{}", err); - RogError::Udev("enumerator failed".into(), err) - })?; - enumerator.match_subsystem("usb").map_err(|err| { - warn!("{}", err); - RogError::Udev("match_subsystem failed".into(), err) - })?; - - for device in enumerator.scan_devices().map_err(|err| { - warn!("{}", err); - RogError::Udev("scan_devices failed".into(), err) - })? { - if let Some(attr) = device.attribute_value("idProduct") { - if attr == id_product { - if let Some(dev_node) = device.devnode() { - info!("Using device at: {:?} for AniMe control", dev_node); - return Ok(dev_node.to_string_lossy().to_string()); - } - } - } - } - Err(RogError::MissingFunction( - "ASUS AniMe device node not found".into(), - )) - } - fn get_dev_handle() -> Result, Box> { // We don't expect this ID to ever change let device = CtrlAnime::get_device(0x0b05, 0x193b)?; @@ -156,10 +131,12 @@ impl CtrlAnime { // we don't block other threads/main let thread_exit; let thread_running; + let anime_type; loop { if let Ok(lock) = inner.try_lock() { thread_exit = lock.thread_exit.clone(); thread_running = lock.thread_running.clone(); + anime_type = lock.anime_type; break; } } @@ -224,7 +201,8 @@ impl CtrlAnime { } // Clear the display on exit if let Ok(lock) = inner.try_lock() { - let data = AnimeDataBuffer::from_vec([0u8; ANIME_DATA_LEN].to_vec()); + let data = + AnimeDataBuffer::from_vec(anime_type, vec![0u8; anime_type.data_length()]); lock.write_data_buffer(data); } // Loop ended, set the atmonics @@ -277,7 +255,7 @@ impl CtrlAnime { /// Write only a data packet. This will modify the leds brightness using the /// global brightness set in config. fn write_data_buffer(&self, mut buffer: AnimeDataBuffer) { - for led in buffer.get_mut()[7..].iter_mut() { + for led in buffer.data_mut()[7..].iter_mut() { let mut bright = *led as f32 * self.config.brightness; if bright > 254.0 { bright = 254.0; diff --git a/rog-anime/Cargo.toml b/rog-anime/Cargo.toml index 2d410ee6..34f14643 100644 --- a/rog-anime/Cargo.toml +++ b/rog-anime/Cargo.toml @@ -13,8 +13,9 @@ edition = "2018" exclude = ["data"] [features] -default = ["dbus"] +default = ["dbus", "detect"] dbus = ["zvariant"] +detect = ["udev", "sysfs-class"] [dependencies] png_pong = "^0.8.0" @@ -28,3 +29,6 @@ serde_derive = "^1.0" glam = { version = "0.20.5", features = ["serde"] } zvariant = { version = "^3.0", optional = true } + +udev = { version = "^0.6", optional = true } +sysfs-class = { version = "^0.1", optional = true } \ No newline at end of file diff --git a/rog-anime/src/data.rs b/rog-anime/src/data.rs index 9029afd7..af72ae03 100644 --- a/rog-anime/src/data.rs +++ b/rog-anime/src/data.rs @@ -16,11 +16,13 @@ const BLOCK_START: usize = 7; const BLOCK_END: usize = 634; /// Individual usable data length of each USB packet const PANE_LEN: usize = BLOCK_END - BLOCK_START; -/// The length of usable data -pub const ANIME_DATA_LEN: usize = PANE_LEN * 2; +/// First packet is for GA401 + GA402 const USB_PREFIX1: [u8; 7] = [0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02]; +/// Second packet is for GA401 + GA402 const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02]; +/// Third packet is for GA402 matrix +const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02]; #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Debug, PartialEq, Copy, Clone, Deserialize, Serialize)] @@ -30,34 +32,69 @@ pub struct AnimePowerStates { pub boot_anim_enabled: bool, } +#[cfg_attr(feature = "dbus", derive(Type))] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] +pub enum AnimeType { + GA401, + GA402, +} + +impl AnimeType { + /// The width of diagonal images + pub fn width(&self) -> usize { + match self { + AnimeType::GA401 => 74, + AnimeType::GA402 => 74, + } + } + + /// The height of diagonal images + pub fn height(&self) -> usize { + match self { + AnimeType::GA401 => 36, + AnimeType::GA402 => 39, + } + } + + /// The length of usable data for this type + pub fn data_length(&self) -> usize { + match self { + AnimeType::GA401 => PANE_LEN * 2, + AnimeType::GA402 => PANE_LEN * 3, + } + } +} + /// The minimal serializable data that can be transferred over wire types. /// Other data structures in `rog_anime` will convert to this. #[cfg_attr(feature = "dbus", derive(Type))] #[derive(Debug, Clone, Deserialize, Serialize)] -pub struct AnimeDataBuffer(Vec); - -impl Default for AnimeDataBuffer { - fn default() -> Self { - Self::new() - } +pub struct AnimeDataBuffer { + data: Vec, + anime: AnimeType, } impl AnimeDataBuffer { #[inline] - pub fn new() -> Self { - AnimeDataBuffer(vec![0u8; ANIME_DATA_LEN]) + pub fn new(anime: AnimeType) -> Self { + let len = anime.data_length(); + + AnimeDataBuffer { + data: vec![0u8; len], + anime, + } } /// Get the inner data buffer #[inline] - pub fn get(&self) -> &[u8] { - &self.0 + pub fn data(&self) -> &[u8] { + &self.data } /// Get a mutable slice of the inner buffer #[inline] - pub fn get_mut(&mut self) -> &mut [u8] { - &mut self.0 + pub fn data_mut(&mut self) -> &mut [u8] { + &mut self.data } /// Create from a vector of bytes @@ -65,25 +102,35 @@ impl AnimeDataBuffer { /// # Panics /// Will panic if the vector length is not `ANIME_DATA_LEN` #[inline] - pub fn from_vec(input: Vec) -> Self { - assert_eq!(input.len(), ANIME_DATA_LEN); - Self(input) + pub fn from_vec(anime: AnimeType, data: Vec) -> Self { + assert_eq!(data.len(), anime.data_length()); + + Self { data, anime } } } /// The two packets to be written to USB -pub type AnimePacketType = [[u8; 640]; 2]; +pub type AnimePacketType = Vec<[u8; 640]>; impl From for AnimePacketType { #[inline] fn from(anime: AnimeDataBuffer) -> Self { - assert!(anime.0.len() == ANIME_DATA_LEN); - let mut buffers = [[0; 640]; 2]; - for (idx, chunk) in anime.0.as_slice().chunks(PANE_LEN).enumerate() { + assert_eq!(anime.data.len(), anime.anime.data_length()); + + let mut buffers = match anime.anime { + AnimeType::GA401 => vec![[0; 640]; 2], + AnimeType::GA402 => vec![[0; 640]; 3], + }; + + for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() { buffers[idx][BLOCK_START..BLOCK_END].copy_from_slice(chunk); } buffers[0][..7].copy_from_slice(&USB_PREFIX1); buffers[1][..7].copy_from_slice(&USB_PREFIX2); + + if matches!(anime.anime, AnimeType::GA402) { + buffers[2][..7].copy_from_slice(&USB_PREFIX3); + } buffers } } @@ -142,7 +189,7 @@ pub fn run_animation( if let AnimTime::Fade(_) = frames.duration() { if frame_start <= start + fade_in { - for pixel in output.get_mut() { + for pixel in output.data_mut() { *pixel = (*pixel as f32 * fade_in_accum) as u8; } fade_in_accum = fade_in_step * (frame_start - start).as_secs_f32(); @@ -153,7 +200,7 @@ pub fn run_animation( } else { fade_out_accum = 0.0; } - for pixel in output.get_mut() { + for pixel in output.data_mut() { *pixel = (*pixel as f32 * fade_out_accum) as u8; } } diff --git a/rog-anime/src/diagonal.rs b/rog-anime/src/diagonal.rs index ba770baa..e89aeb40 100644 --- a/rog-anime/src/diagonal.rs +++ b/rog-anime/src/diagonal.rs @@ -1,40 +1,32 @@ use std::{path::Path, time::Duration}; -use crate::{ - data::{AnimeDataBuffer, ANIME_DATA_LEN}, - error::AnimeError, -}; - -const WIDTH: usize = 74; -const HEIGHT: usize = 36; +use crate::{data::AnimeDataBuffer, error::AnimeError, AnimeType}; /// Mostly intended to be used with ASUS gifs, but can be used for other purposes (like images) #[derive(Debug, Clone)] -pub struct AnimeDiagonal([[u8; WIDTH]; HEIGHT], Option); - -impl Default for AnimeDiagonal { - #[inline] - fn default() -> Self { - Self::new(None) - } -} +pub struct AnimeDiagonal(AnimeType, Vec>, Option); impl AnimeDiagonal { #[inline] - pub fn new(duration: Option) -> Self { - Self([[0u8; WIDTH]; HEIGHT], duration) + pub fn new(anime_type: AnimeType, duration: Option) -> Self { + Self( + anime_type, + vec![vec![0; anime_type.width()]; anime_type.height()], + duration, + ) } #[inline] - pub fn get_mut(&mut self) -> &mut [[u8; WIDTH]; HEIGHT] { - &mut self.0 + pub fn get_mut(&mut self) -> &mut Vec> { + &mut self.1 } /// Get a full diagonal row where `x` `y` is the starting point and `len` is the length of data. fn get_row(&self, x: usize, y: usize, len: usize) -> Vec { let mut buf = Vec::with_capacity(len); for i in 0..len { - let val = self.0[HEIGHT - y - i - 1][x + i]; + let y = self.0.height() - y - i - 1; + let val = self.1[y][x + i]; buf.push(val); } buf @@ -47,13 +39,14 @@ impl AnimeDiagonal { path: &Path, duration: Option, bright: f32, + anime_type: AnimeType, ) -> Result { let data = std::fs::read(path)?; let data = std::io::Cursor::new(data); let decoder = png_pong::Decoder::new(data)?.into_steps(); let png_pong::Step { raster, delay: _ } = decoder.last().ok_or(AnimeError::NoFrames)??; - let mut matrix = AnimeDiagonal::new(duration); + let mut matrix = AnimeDiagonal::new(anime_type, duration); match raster { png_pong::PngRaster::Gray8(ras) => { @@ -100,7 +93,9 @@ impl AnimeDiagonal { + (::from(px.two()) / 3) as f32 + (::from(px.three()) / 3) as f32 }; - matrix.0[y][x] = (v * bright) as u8; + if y < matrix.1.len() && x < matrix.1[y].len() { + matrix.1[y][x] = (v * bright) as u8; + } } } } @@ -123,75 +118,547 @@ impl AnimeDiagonal { + ((::from(px.two()) / 3) >> 8) as f32 + ((::from(px.three()) / 3) >> 8) as f32 }; - matrix.0[y][x] = (v * bright) as u8; + matrix.1[y][x] = (v * bright) as u8; } } } -} -impl From<&AnimeDiagonal> for AnimeDataBuffer { + /// Convert to a data buffer that can be sent over dbus + #[inline] + pub fn into_data_buffer(&self, anime_type: AnimeType) -> AnimeDataBuffer { + match anime_type { + AnimeType::GA401 => self.into_ga401_packets(), + AnimeType::GA402 => self.into_ga402_packets(), + } + } + /// Do conversion from the nested Vec in AnimeMatrix to the two required /// packets suitable for sending over USB - #[inline] - fn from(anime: &AnimeDiagonal) -> Self { - let mut buf = vec![0u8; ANIME_DATA_LEN]; + fn into_ga401_packets(&self) -> AnimeDataBuffer { + let mut buf = vec![0u8; AnimeType::GA401.data_length()]; - buf[1..=32].copy_from_slice(&anime.get_row(0, 3, 32)); - buf[34..=66].copy_from_slice(&anime.get_row(0, 2, 33)); - buf[69..=101].copy_from_slice(&anime.get_row(1, 2, 33)); // ?! - buf[102..=134].copy_from_slice(&anime.get_row(1, 1, 33)); - buf[137..=169].copy_from_slice(&anime.get_row(2, 1, 33)); - buf[170..=202].copy_from_slice(&anime.get_row(2, 0, 33)); - buf[204..=236].copy_from_slice(&anime.get_row(3, 0, 33)); - buf[237..=268].copy_from_slice(&anime.get_row(4, 0, 32)); - buf[270..=301].copy_from_slice(&anime.get_row(5, 0, 32)); - buf[302..=332].copy_from_slice(&anime.get_row(6, 0, 31)); - buf[334..=364].copy_from_slice(&anime.get_row(7, 0, 31)); - buf[365..=394].copy_from_slice(&anime.get_row(8, 0, 30)); - buf[396..=425].copy_from_slice(&anime.get_row(9, 0, 30)); - buf[426..=454].copy_from_slice(&anime.get_row(10, 0, 29)); - buf[456..=484].copy_from_slice(&anime.get_row(11, 0, 29)); - buf[485..=512].copy_from_slice(&anime.get_row(12, 0, 28)); - buf[514..=541].copy_from_slice(&anime.get_row(13, 0, 28)); - buf[542..=568].copy_from_slice(&anime.get_row(14, 0, 27)); - buf[570..=596].copy_from_slice(&anime.get_row(15, 0, 27)); - buf[597..=622].copy_from_slice(&anime.get_row(16, 0, 26)); - buf[624..=649].copy_from_slice(&anime.get_row(17, 0, 26)); - buf[650..=674].copy_from_slice(&anime.get_row(18, 0, 25)); - buf[676..=700].copy_from_slice(&anime.get_row(19, 0, 25)); - buf[701..=724].copy_from_slice(&anime.get_row(20, 0, 24)); - buf[726..=749].copy_from_slice(&anime.get_row(21, 0, 24)); - buf[750..=772].copy_from_slice(&anime.get_row(22, 0, 23)); - buf[774..=796].copy_from_slice(&anime.get_row(23, 0, 23)); - buf[797..=818].copy_from_slice(&anime.get_row(24, 0, 22)); - buf[820..=841].copy_from_slice(&anime.get_row(25, 0, 22)); - buf[842..=862].copy_from_slice(&anime.get_row(26, 0, 21)); - buf[864..=884].copy_from_slice(&anime.get_row(27, 0, 21)); - buf[885..=904].copy_from_slice(&anime.get_row(28, 0, 20)); - buf[906..=925].copy_from_slice(&anime.get_row(29, 0, 20)); - buf[926..=944].copy_from_slice(&anime.get_row(30, 0, 19)); - buf[946..=964].copy_from_slice(&anime.get_row(31, 0, 19)); - buf[965..=982].copy_from_slice(&anime.get_row(32, 0, 18)); - buf[984..=1001].copy_from_slice(&anime.get_row(33, 0, 18)); - buf[1002..=1018].copy_from_slice(&anime.get_row(34, 0, 17)); - buf[1020..=1036].copy_from_slice(&anime.get_row(35, 0, 17)); - buf[1037..=1052].copy_from_slice(&anime.get_row(36, 0, 16)); - buf[1054..=1069].copy_from_slice(&anime.get_row(37, 0, 16)); - buf[1070..=1084].copy_from_slice(&anime.get_row(38, 0, 15)); - buf[1086..=1100].copy_from_slice(&anime.get_row(39, 0, 15)); - buf[1101..=1114].copy_from_slice(&anime.get_row(40, 0, 14)); - buf[1116..=1129].copy_from_slice(&anime.get_row(41, 0, 14)); - buf[1130..=1142].copy_from_slice(&anime.get_row(42, 0, 13)); - buf[1144..=1156].copy_from_slice(&anime.get_row(43, 0, 13)); - buf[1157..=1168].copy_from_slice(&anime.get_row(44, 0, 12)); - buf[1170..=1181].copy_from_slice(&anime.get_row(45, 0, 12)); - buf[1182..=1192].copy_from_slice(&anime.get_row(46, 0, 11)); - buf[1194..=1204].copy_from_slice(&anime.get_row(47, 0, 11)); - buf[1205..=1214].copy_from_slice(&anime.get_row(48, 0, 10)); - buf[1216..=1225].copy_from_slice(&anime.get_row(49, 0, 10)); - buf[1226..=1234].copy_from_slice(&anime.get_row(50, 0, 9)); - buf[1236..=1244].copy_from_slice(&anime.get_row(51, 0, 9)); + buf[1..=32].copy_from_slice(&self.get_row(0, 3, 32)); + buf[34..=66].copy_from_slice(&self.get_row(0, 2, 33)); + buf[69..=101].copy_from_slice(&self.get_row(1, 2, 33)); // ?! + buf[102..=134].copy_from_slice(&self.get_row(1, 1, 33)); + buf[137..=169].copy_from_slice(&self.get_row(2, 1, 33)); + buf[170..=202].copy_from_slice(&self.get_row(2, 0, 33)); + buf[204..=236].copy_from_slice(&self.get_row(3, 0, 33)); // This and above cause overflow? + buf[237..=268].copy_from_slice(&self.get_row(4, 0, 32)); + buf[270..=301].copy_from_slice(&self.get_row(5, 0, 32)); + buf[302..=332].copy_from_slice(&self.get_row(6, 0, 31)); + buf[334..=364].copy_from_slice(&self.get_row(7, 0, 31)); + buf[365..=394].copy_from_slice(&self.get_row(8, 0, 30)); + buf[396..=425].copy_from_slice(&self.get_row(9, 0, 30)); + buf[426..=454].copy_from_slice(&self.get_row(10, 0, 29)); + buf[456..=484].copy_from_slice(&self.get_row(11, 0, 29)); + buf[485..=512].copy_from_slice(&self.get_row(12, 0, 28)); + buf[514..=541].copy_from_slice(&self.get_row(13, 0, 28)); + buf[542..=568].copy_from_slice(&self.get_row(14, 0, 27)); + buf[570..=596].copy_from_slice(&self.get_row(15, 0, 27)); + buf[597..=622].copy_from_slice(&self.get_row(16, 0, 26)); + buf[624..=649].copy_from_slice(&self.get_row(17, 0, 26)); + buf[650..=674].copy_from_slice(&self.get_row(18, 0, 25)); + buf[676..=700].copy_from_slice(&self.get_row(19, 0, 25)); + buf[701..=724].copy_from_slice(&self.get_row(20, 0, 24)); + buf[726..=749].copy_from_slice(&self.get_row(21, 0, 24)); + buf[750..=772].copy_from_slice(&self.get_row(22, 0, 23)); + buf[774..=796].copy_from_slice(&self.get_row(23, 0, 23)); + buf[797..=818].copy_from_slice(&self.get_row(24, 0, 22)); + buf[820..=841].copy_from_slice(&self.get_row(25, 0, 22)); + buf[842..=862].copy_from_slice(&self.get_row(26, 0, 21)); + buf[864..=884].copy_from_slice(&self.get_row(27, 0, 21)); + buf[885..=904].copy_from_slice(&self.get_row(28, 0, 20)); + buf[906..=925].copy_from_slice(&self.get_row(29, 0, 20)); + buf[926..=944].copy_from_slice(&self.get_row(30, 0, 19)); + buf[946..=964].copy_from_slice(&self.get_row(31, 0, 19)); + buf[965..=982].copy_from_slice(&self.get_row(32, 0, 18)); + buf[984..=1001].copy_from_slice(&self.get_row(33, 0, 18)); + buf[1002..=1018].copy_from_slice(&self.get_row(34, 0, 17)); + buf[1020..=1036].copy_from_slice(&self.get_row(35, 0, 17)); + buf[1037..=1052].copy_from_slice(&self.get_row(36, 0, 16)); + buf[1054..=1069].copy_from_slice(&self.get_row(37, 0, 16)); + buf[1070..=1084].copy_from_slice(&self.get_row(38, 0, 15)); + buf[1086..=1100].copy_from_slice(&self.get_row(39, 0, 15)); + buf[1101..=1114].copy_from_slice(&self.get_row(40, 0, 14)); + buf[1116..=1129].copy_from_slice(&self.get_row(41, 0, 14)); + buf[1130..=1142].copy_from_slice(&self.get_row(42, 0, 13)); + buf[1144..=1156].copy_from_slice(&self.get_row(43, 0, 13)); + buf[1157..=1168].copy_from_slice(&self.get_row(44, 0, 12)); + buf[1170..=1181].copy_from_slice(&self.get_row(45, 0, 12)); + buf[1182..=1192].copy_from_slice(&self.get_row(46, 0, 11)); + buf[1194..=1204].copy_from_slice(&self.get_row(47, 0, 11)); + buf[1205..=1214].copy_from_slice(&self.get_row(48, 0, 10)); + buf[1216..=1225].copy_from_slice(&self.get_row(49, 0, 10)); + buf[1226..=1234].copy_from_slice(&self.get_row(50, 0, 9)); + buf[1236..=1244].copy_from_slice(&self.get_row(51, 0, 9)); - AnimeDataBuffer::from_vec(buf) + AnimeDataBuffer::from_vec(crate::AnimeType::GA401, buf) + } + + fn into_ga402_packets(&self) -> AnimeDataBuffer { + let mut buf = vec![0u8; AnimeType::GA402.data_length()]; + let mut start_index: usize = 0; + + fn copy_slice( + buf: &mut Vec, + anime: &AnimeDiagonal, + x: usize, + y: usize, + start_index: &mut usize, + len: usize, + ) { + buf[*start_index..*start_index + len].copy_from_slice(&anime.get_row(x, y, len)); + *start_index += len; + } + + let b = &mut buf; + let a = &self; + copy_slice(b, a, 0, 5, &mut start_index, 34); + copy_slice(b, a, 1, 5, &mut start_index, 34); + copy_slice(b, a, 1, 4, &mut start_index, 34); + copy_slice(b, a, 2, 4, &mut start_index, 34); + copy_slice(b, a, 2, 3, &mut start_index, 34); + copy_slice(b, a, 3, 3, &mut start_index, 34); + copy_slice(b, a, 3, 2, &mut start_index, 34); + copy_slice(b, a, 4, 2, &mut start_index, 34); + copy_slice(b, a, 4, 1, &mut start_index, 34); + copy_slice(b, a, 5, 1, &mut start_index, 34); + copy_slice(b, a, 5, 0, &mut start_index, 34); + copy_slice(b, a, 6, 0, &mut start_index, 34); + copy_slice(b, a, 7, 0, &mut start_index, 33); + copy_slice(b, a, 8, 0, &mut start_index, 33); + copy_slice(b, a, 9, 0, &mut start_index, 32); + copy_slice(b, a, 10, 0, &mut start_index, 32); + copy_slice(b, a, 11, 0, &mut start_index, 31); + copy_slice(b, a, 12, 0, &mut start_index, 31); + copy_slice(b, a, 13, 0, &mut start_index, 30); + copy_slice(b, a, 14, 0, &mut start_index, 30); + copy_slice(b, a, 15, 0, &mut start_index, 29); + copy_slice(b, a, 16, 0, &mut start_index, 29); + copy_slice(b, a, 17, 0, &mut start_index, 28); + copy_slice(b, a, 18, 0, &mut start_index, 28); + copy_slice(b, a, 19, 0, &mut start_index, 27); + copy_slice(b, a, 20, 0, &mut start_index, 27); + copy_slice(b, a, 21, 0, &mut start_index, 26); + copy_slice(b, a, 22, 0, &mut start_index, 26); + copy_slice(b, a, 23, 0, &mut start_index, 25); + copy_slice(b, a, 24, 0, &mut start_index, 25); + copy_slice(b, a, 25, 0, &mut start_index, 24); + copy_slice(b, a, 26, 0, &mut start_index, 24); + copy_slice(b, a, 27, 0, &mut start_index, 23); + copy_slice(b, a, 28, 0, &mut start_index, 23); + copy_slice(b, a, 29, 0, &mut start_index, 22); + copy_slice(b, a, 30, 0, &mut start_index, 22); + copy_slice(b, a, 31, 0, &mut start_index, 21); + copy_slice(b, a, 32, 0, &mut start_index, 21); + copy_slice(b, a, 33, 0, &mut start_index, 20); + copy_slice(b, a, 34, 0, &mut start_index, 20); + copy_slice(b, a, 35, 0, &mut start_index, 19); + copy_slice(b, a, 36, 0, &mut start_index, 19); + copy_slice(b, a, 37, 0, &mut start_index, 18); + copy_slice(b, a, 38, 0, &mut start_index, 18); + copy_slice(b, a, 39, 0, &mut start_index, 17); + copy_slice(b, a, 40, 0, &mut start_index, 17); + copy_slice(b, a, 41, 0, &mut start_index, 16); + copy_slice(b, a, 42, 0, &mut start_index, 16); + copy_slice(b, a, 43, 0, &mut start_index, 15); + copy_slice(b, a, 44, 0, &mut start_index, 15); + copy_slice(b, a, 45, 0, &mut start_index, 14); + copy_slice(b, a, 46, 0, &mut start_index, 14); + copy_slice(b, a, 47, 0, &mut start_index, 13); + copy_slice(b, a, 48, 0, &mut start_index, 13); + copy_slice(b, a, 49, 0, &mut start_index, 12); + copy_slice(b, a, 50, 0, &mut start_index, 12); + copy_slice(b, a, 51, 0, &mut start_index, 11); + copy_slice(b, a, 52, 0, &mut start_index, 11); + copy_slice(b, a, 53, 0, &mut start_index, 10); + copy_slice(b, a, 54, 0, &mut start_index, 10); + copy_slice(b, a, 55, 0, &mut start_index, 9); + + AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf) + } +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use crate::{AnimeDiagonal, AnimePacketType, AnimeType}; + + #[test] + fn ga401_diagonal_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test/ga401-diagonal.png"); + + let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA401).unwrap(); + let data = matrix.into_data_buffer(crate::AnimeType::GA401); + let pkt = AnimePacketType::from(data); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + } + + #[test] + fn ga402_diagonal_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + let pkt2_check = [ + 0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test/ga402-diagonal.png"); + + let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap(); + let data = matrix.into_data_buffer(crate::AnimeType::GA402); + let pkt = AnimePacketType::from(data); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + assert_eq!(pkt[2], pkt2_check); + } + + #[test] + #[ignore = "Needs the packets verified with capture"] + fn ga402_diagonal_fullbright_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x67, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + let pkt2_check = [ + 0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test/ga402-diagonal-fullbright.png"); + + let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::GA402).unwrap(); + let data = matrix.into_data_buffer(crate::AnimeType::GA402); + let pkt = AnimePacketType::from(data); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + assert_eq!(pkt[2], pkt2_check); } } diff --git a/rog-anime/src/error.rs b/rog-anime/src/error.rs index ee12a440..9a97859a 100644 --- a/rog-anime/src/error.rs +++ b/rog-anime/src/error.rs @@ -13,6 +13,9 @@ pub enum AnimeError { /// The input was incorrect size, expected size is `IncorrectSize(width, height)` IncorrectSize(u32, u32), Dbus(String), + Udev(String, std::io::Error), + NoDevice, + UnsupportedDevice, } impl fmt::Display for AnimeError { @@ -30,6 +33,9 @@ impl fmt::Display for AnimeError { width, height ), AnimeError::Dbus(detail) => write!(f, "{}", detail), + AnimeError::Udev(deets, error) => write!(f, "udev {}: {}", deets, error), + AnimeError::NoDevice => write!(f, "No AniMe Matrix device found"), + AnimeError::UnsupportedDevice => write!(f, "Unsupported AniMe Matrix device found"), } } } diff --git a/rog-anime/src/gif.rs b/rog-anime/src/gif.rs index ef89ad4b..5e33ba55 100644 --- a/rog-anime/src/gif.rs +++ b/rog-anime/src/gif.rs @@ -2,7 +2,7 @@ use glam::Vec2; use serde_derive::{Deserialize, Serialize}; use std::{fs::File, path::Path, time::Duration}; -use crate::{error::AnimeError, AnimeDataBuffer, AnimeDiagonal, AnimeImage, Pixel}; +use crate::{error::AnimeError, AnimeDataBuffer, AnimeDiagonal, AnimeImage, AnimeType, Pixel}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AnimeFrame { @@ -92,8 +92,9 @@ impl AnimeGif { file_name: &Path, duration: AnimTime, brightness: f32, + anime_type: AnimeType, ) -> Result { - let mut matrix = AnimeDiagonal::new(None); + let mut matrix = AnimeDiagonal::new(anime_type, None); let mut decoder = gif::DecodeOptions::new(); // Configure the decoder such that it will expand the image to RGBA. @@ -121,7 +122,7 @@ impl AnimeGif { } frames.push(AnimeFrame { - data: ::from(&matrix), + data: matrix.into_data_buffer(anime_type), delay: Duration::from_millis(wait as u64), }); } @@ -132,10 +133,11 @@ impl AnimeGif { #[inline] pub fn from_diagonal_png( file_name: &Path, + anime_type: AnimeType, duration: AnimTime, brightness: f32, ) -> Result { - let image = AnimeDiagonal::from_png(file_name, None, brightness)?; + let image = AnimeDiagonal::from_png(file_name, None, brightness, anime_type)?; let mut total = Duration::from_millis(1000); if let AnimTime::Fade(fade) = duration { @@ -148,7 +150,7 @@ impl AnimeGif { let frame_count = total.as_millis() / 30; let single = AnimeFrame { - data: ::from(&image), + data: image.into_data_buffer(anime_type), delay: Duration::from_millis(30), }; let frames = vec![single; frame_count as usize]; @@ -166,6 +168,7 @@ impl AnimeGif { translation: Vec2, duration: AnimTime, brightness: f32, + anime_type: AnimeType, ) -> Result { let mut frames = Vec::new(); @@ -187,6 +190,7 @@ impl AnimeGif { brightness, pixels, decoder.width() as u32, + anime_type, ); while let Some(frame) = decoder.read_next_frame()? { @@ -201,6 +205,7 @@ impl AnimeGif { brightness, pixels, width as u32, + anime_type, ); } for (y, row) in frame.buffer.chunks(frame.width as usize * 4).enumerate() { @@ -238,8 +243,10 @@ impl AnimeGif { translation: Vec2, duration: AnimTime, brightness: f32, + anime_type: AnimeType, ) -> Result { - let image = AnimeImage::from_png(file_name, scale, angle, translation, brightness)?; + let image = + AnimeImage::from_png(file_name, scale, angle, translation, brightness, anime_type)?; let mut total = Duration::from_millis(1000); if let AnimTime::Fade(fade) = duration { diff --git a/rog-anime/src/grid.rs b/rog-anime/src/grid.rs index c53ab0dd..f80e84e2 100644 --- a/rog-anime/src/grid.rs +++ b/rog-anime/src/grid.rs @@ -1,8 +1,7 @@ -use std::time::Duration; - -use crate::data::{AnimeDataBuffer, ANIME_DATA_LEN}; -use crate::image::LED_IMAGE_POSITIONS; +use crate::data::AnimeDataBuffer; +use crate::{AnimeImage, AnimeType}; +// TODO: Adjust these sizes as WIDTH_GA401 WIDTH_GA402 const WIDTH: usize = 33; const HEIGHT: usize = 55; @@ -14,41 +13,40 @@ const HEIGHT: usize = 55; /// /// **Note:** the columns in each odd row are offset by half a pixel left #[derive(Debug, Clone)] -pub struct AnimeGrid([[u8; WIDTH]; HEIGHT], Option); - -impl Default for AnimeGrid { - #[inline] - fn default() -> Self { - Self::new(None) - } +pub struct AnimeGrid { + anime_type: AnimeType, + data: [[u8; WIDTH]; HEIGHT], } impl AnimeGrid { #[inline] - pub fn new(duration: Option) -> Self { - AnimeGrid([[0u8; WIDTH]; HEIGHT], duration) + pub fn new(anime_type: AnimeType) -> Self { + Self { + anime_type, + data: [[0u8; WIDTH]; HEIGHT], + } } /// Set a position in the grid with a brightness value #[inline] pub fn set(&mut self, x: usize, y: usize, b: u8) { - self.0[y][x] = b; + self.data[y][x] = b; } #[inline] pub fn get(&self) -> &[[u8; WIDTH]; HEIGHT] { - &self.0 + &self.data } #[inline] pub fn get_mut(&mut self) -> &mut [[u8; WIDTH]; HEIGHT] { - &mut self.0 + &mut self.data } /// Fill the grid with a value #[inline] pub fn fill_with(&mut self, fill: u8) { - for row in self.0.iter_mut() { + for row in self.data.iter_mut() { for x in row.iter_mut() { *x = fill; } @@ -94,16 +92,19 @@ impl From for AnimeDataBuffer { /// packets suitable for sending over USB #[inline] fn from(anime: AnimeGrid) -> Self { - let mut buf = vec![0u8; ANIME_DATA_LEN]; + let mut buf = vec![0u8; anime.anime_type.data_length()]; - for (idx, pos) in LED_IMAGE_POSITIONS.iter().enumerate() { + for (idx, pos) in AnimeImage::generate_image_positioning(anime.anime_type) + .iter() + .enumerate() + { if let Some(pos) = pos { let x = pos.x().ceil() as usize; let y = pos.y().ceil() as usize; - buf[idx + 1] = anime.0[y][x]; + buf[idx + 1] = anime.data[y][x]; } } - AnimeDataBuffer::from_vec(buf) + AnimeDataBuffer::from_vec(anime.anime_type, buf) } } @@ -113,7 +114,7 @@ mod tests { #[test] fn check_data_alignment() { - let mut matrix = AnimeGrid::new(None); + let mut matrix = AnimeGrid::new(AnimeType::GA401); { let tmp = matrix.get_mut(); for row in tmp.iter_mut() { @@ -171,6 +172,6 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - assert_eq!(matrix.get(), &data_cmp); + assert_eq!(matrix.data(), &data_cmp); } } diff --git a/rog-anime/src/image.rs b/rog-anime/src/image.rs index e69ec96c..de1441a2 100644 --- a/rog-anime/src/image.rs +++ b/rog-anime/src/image.rs @@ -3,12 +3,7 @@ use std::path::Path; pub use glam::Vec2; use glam::{Mat3, Vec3}; -use crate::{ - data::{AnimeDataBuffer, ANIME_DATA_LEN}, - error::AnimeError, -}; - -const LED_PIXEL_LEN: usize = 1244; +use crate::{data::AnimeDataBuffer, error::AnimeError, AnimeType}; /// A single greyscale + alpha pixel in the image #[derive(Copy, Clone, Debug)] @@ -69,81 +64,178 @@ pub struct AnimeImage { /// Brightness of final image, `0.0` = off, `1.0` = full pub bright: f32, /// Positions of all the LEDs - led_pos: [Option; LED_PIXEL_LEN], + led_pos: Vec>, /// THe image data for sampling img_pixels: Vec, /// width of the image width: u32, + /// The type of the display. The GA401 and GA402 use the same controller and therefore same ID, + /// so the identifier must be by laptop model in `AnimeType`. + anime_type: AnimeType, } impl AnimeImage { - pub(crate) const fn new( + pub(crate) fn new( scale: Vec2, angle: f32, translation: Vec2, bright: f32, pixels: Vec, width: u32, + anime_type: AnimeType, ) -> Self { Self { scale, angle, translation, bright, - led_pos: LED_IMAGE_POSITIONS, + led_pos: Self::generate_image_positioning(anime_type), img_pixels: pixels, width, + anime_type, + } + } + + // TODO: Convert functions back to const after todo completed + + /// Scale ratio in CM + /// + /// This is worked out by measuring the physical width of the display from pixel center to + /// center, then dividing by ` + 0.5`, where the LED count is + /// first/longest row. + /// + /// For GA401 this is `26.8 / (33 + 0.5) = 0.8` + /// For GA402 this is `27.4 / (35 + 0.5) = 0.77` + fn scale_x(anime_type: AnimeType) -> f32 { + match anime_type { + AnimeType::GA401 => 0.8, + AnimeType::GA402 => 0.77, } } /// Scale ratio in CM - const fn scale_x() -> f32 { - 0.8 - } - - /// Scale ratio in CM - const fn scale_y() -> f32 { - 0.3 + /// + /// This is worked out by measuring the physical height of the display from pixel center to + /// pixel center, then dividing by ` + 1.0`, where the LED count is + /// first/longest row. + /// + /// For GA401 this is `16.5 / (54.0 + 1.0) = 0.3` + /// For GA402 this is `17.3 / (61.0) = 0.283` + fn scale_y(anime_type: AnimeType) -> f32 { + match anime_type { + AnimeType::GA401 => 0.3, + AnimeType::GA402 => 0.283, + } } /// Get the starting X position for the data we actually require when writing - /// it out to LEDs - const fn first_x(y: u32) -> u32 { - if y < 5 { - return 0; + /// it out to LEDs. + /// + /// In relation to the display itself you should think of it as a full square grid, so `first_x` + /// is the x position on that grid where the LED is actually positioned in relation to the Y. + /// ```text + /// +------------+ + /// | | + /// | | + /// \ | + /// \ | + /// \ | + /// \ | + /// \ | + /// |----|\ | + /// ^ ------+ + /// first_x + /// ``` + fn first_x(anime_type: AnimeType, y: u32) -> u32 { + match anime_type { + AnimeType::GA401 => { + if y < 5 { + // first 5 rows for GA401 are always at X = 0 + return 0; + } + (y + 1) / 2 - 3 + } + AnimeType::GA402 => { + // first 11 rows start at zero + if y <= 11 { + return 0; + } + // and then their offset grows by one every two rows + (y + 1) / 2 - 5 + } } - (y + 1) / 2 - 3 } /// Width in LED count - const fn width(y: u32) -> u32 { - if y < 5 { - return 33; + /// + /// This is how many LED's are physically in a row + /// ```text + /// +------------+ + /// | | + /// | | + /// \ | + /// \ width | + /// \ v | + /// \|------|| + /// \ | + /// \ | + /// ------+ + /// ``` + fn width(anime_type: AnimeType, y: u32) -> u32 { + match anime_type { + AnimeType::GA401 => { + if y < 5 { + // First 5 rows for GA401 are always 33 physical LEDs long + return 33; + } + 36 - (y + 1) / 2 + } + AnimeType::GA402 => { + if y <= 11 { + return 34; + } + 39 - y / 2 + } } - 36 - (y + 1) / 2 } - /// Physical display width - fn phys_width() -> f32 { - (32.0 - -0.5 + 1.0) * Self::scale_x() + /// Physical display width by count of LED + fn phys_width(anime_type: AnimeType) -> f32 { + match anime_type { + // 33.0 = Longest row LED count (physical) plus half-pixel offset + AnimeType::GA401 => (33.0 + 0.5) * Self::scale_x(anime_type), + AnimeType::GA402 => (35.0 + 0.5) * Self::scale_x(anime_type), + } } - /// Height in LED count - const fn height() -> u32 { - 55 + /// Height in LED count of longest column (physical count) + fn height(anime_type: AnimeType) -> u32 { + match anime_type { + AnimeType::GA401 => 55, + AnimeType::GA402 => 61, + } } /// Physical display height - fn phys_height() -> f32 { - (54.0 + 1.0) * Self::scale_y() + fn phys_height(anime_type: AnimeType) -> f32 { + match anime_type { + // 54.0 = End column LED count (physical) plus one dead pixel + AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type), + // GA402 may not have dead pixels and require only the physical LED count + AnimeType::GA402 => 61.0 * Self::scale_y(anime_type), + } } /// Find the actual width of the data including the dead pixels - const fn pitch(y: u32) -> u32 { - match y { - 0 | 2 | 4 => 33, - 1 | 3 => 35, - _ => 36 - y / 2, + fn pitch(anime_type: AnimeType, y: u32) -> u32 { + match anime_type { + AnimeType::GA401 => match y { + 0 | 2 | 4 => 33, + 1 | 3 => 35, // Some rows are padded + _ => 36 - y / 2, + }, + // GA402 does not have padding, equivalent to width + AnimeType::GA402 => AnimeImage::width(anime_type, y), } } @@ -151,17 +243,19 @@ impl AnimeImage { &mut self.img_pixels } - /// Really only used to generate the output for including as a full const in `LED_IMAGE_POSITIONS` + /// Generate a list of LED positions. These are then used to sample the Image data, + /// and will contain their resulting brightness. #[inline] - pub fn generate() -> Vec> { - (0..AnimeImage::height()) + pub fn generate_image_positioning(anime_type: AnimeType) -> Vec> { + (0..AnimeImage::height(anime_type)) .flat_map(|y| { - (0..AnimeImage::pitch(y)).map(move |l| { - if l < AnimeImage::width(y) { - let x = AnimeImage::first_x(y) + l; + // For each row (Y) get actual length + (0..AnimeImage::pitch(anime_type, y)).map(move |l| { + if l < AnimeImage::width(anime_type, y) { + let x = AnimeImage::first_x(anime_type, y) + l; Some(Led::new(x as f32 - 0.5 * (y % 2) as f32, y as f32)) } else { - None + None // dead/non-existent pixels to the left } }) }) @@ -170,7 +264,10 @@ impl AnimeImage { /// Called after setting new angle, position, or scale to refresh the image /// samples, the result can then been transformed to the appropriate data - /// for displaying + /// for displaying. + /// + /// The internal for loop iterates over the LED positions, skipping the blank/dead + /// pixels if any. #[inline] pub fn update(&mut self) { let width = self.width as i32; @@ -211,13 +308,50 @@ impl AnimeImage { } } + fn edge_outline(&mut self) { + // Janky shit here just to try help align images + let mut last_x = 0.0; + let mut last_y = 0.0; + let mut last_was_led = false; + let mut ends = Vec::new(); + for (idx, led) in self.led_pos.iter_mut().enumerate() { + if let Some(led) = led { + // Capture the starting LED + if led.x() - last_x != 1.0 { + led.set_bright(255); + last_x = led.x(); + } else { + // top and bottom + if led.y() == 0.0 || led.y() >= AnimeImage::height(self.anime_type) as f32 - 1.0 + { + led.set_bright(255); + } + last_x += 1.0; + } + if led.y() - last_y == 1.0 { + ends.push(idx); + last_y = led.y(); + } + last_was_led = true; + } else if last_was_led { + //ends.push(idx); + last_was_led = false; + } + } + for end in ends { + if let Some(led) = self.led_pos[end - 1].as_mut() { + led.set_bright(255); + } + } + } + /// Put the render window in place on the image fn put(&self, bmp_w: f32, bmp_h: f32) -> Mat3 { // Center of image let center = Mat3::from_translation(Vec2::new(-0.5 * bmp_w, -0.5 * bmp_h)); // Find the scale required for cleanly showing the image - let h = AnimeImage::phys_height() / bmp_h; - let mut base_scale = AnimeImage::phys_width() / bmp_w; + let h = AnimeImage::phys_height(self.anime_type) / bmp_h; + let mut base_scale = AnimeImage::phys_width(self.anime_type) / bmp_w; if base_scale > h { base_scale = h; } @@ -225,8 +359,8 @@ impl AnimeImage { let cm_from_px = Mat3::from_scale(Vec2::new(base_scale, base_scale)); let led_from_cm = Mat3::from_scale(Vec2::new( - 1.0 / AnimeImage::scale_x(), - 1.0 / AnimeImage::scale_y(), + 1.0 / AnimeImage::scale_x(self.anime_type), + 1.0 / AnimeImage::scale_y(self.anime_type), )); let transform = @@ -248,6 +382,7 @@ impl AnimeImage { angle: f32, translation: Vec2, bright: f32, + anime_type: AnimeType, ) -> Result { let data = std::fs::read(path)?; let data = std::io::Cursor::new(data); @@ -298,6 +433,7 @@ impl AnimeImage { bright, pixels, width, + anime_type, ); matrix.update(); @@ -353,1272 +489,25 @@ impl From<&AnimeImage> for AnimeDataBuffer { .iter() .map(|l| if let Some(l) = l { l.bright() } else { 0 }) .collect(); - let mut v = Vec::with_capacity(ANIME_DATA_LEN); - v.push(0); + let mut v = Vec::with_capacity(leds.anime_type.data_length()); + if leds.anime_type == AnimeType::GA401 { + v.push(0); + } v.append(&mut l); - v.append(&mut vec![0u8; 9]); - AnimeDataBuffer::from_vec(v) + v.append(&mut vec![0u8; leds.anime_type.data_length() - v.len()]); + AnimeDataBuffer::from_vec(leds.anime_type, v) } } -/// Data starts at first index which means that when mapping this data to the final -/// USB packet it must start from index 8, not 7. -/// -/// Verbatim copy of `generate()`. `LED_IMAGE_POSITIONS` is `const` so prefer this. -pub const LED_IMAGE_POSITIONS: [Option; LED_PIXEL_LEN] = [ - Some(Led(0.0, 0.0, 0)), - Some(Led(1.0, 0.0, 0)), - Some(Led(2.0, 0.0, 0)), - Some(Led(3.0, 0.0, 0)), - Some(Led(4.0, 0.0, 0)), - Some(Led(5.0, 0.0, 0)), - Some(Led(6.0, 0.0, 0)), - Some(Led(7.0, 0.0, 0)), - Some(Led(8.0, 0.0, 0)), - Some(Led(9.0, 0.0, 0)), - Some(Led(10.0, 0.0, 0)), - Some(Led(11.0, 0.0, 0)), - Some(Led(12.0, 0.0, 0)), - Some(Led(13.0, 0.0, 0)), - Some(Led(14.0, 0.0, 0)), - Some(Led(15.0, 0.0, 0)), - Some(Led(16.0, 0.0, 0)), - Some(Led(17.0, 0.0, 0)), - Some(Led(18.0, 0.0, 0)), - Some(Led(19.0, 0.0, 0)), - Some(Led(20.0, 0.0, 0)), - Some(Led(21.0, 0.0, 0)), - Some(Led(22.0, 0.0, 0)), - Some(Led(23.0, 0.0, 0)), - Some(Led(24.0, 0.0, 0)), - Some(Led(25.0, 0.0, 0)), - Some(Led(26.0, 0.0, 0)), - Some(Led(27.0, 0.0, 0)), - Some(Led(28.0, 0.0, 0)), - Some(Led(29.0, 0.0, 0)), - Some(Led(30.0, 0.0, 0)), - Some(Led(31.0, 0.0, 0)), - Some(Led(32.0, 0.0, 0)), - Some(Led(-0.5, 1.0, 0)), - Some(Led(0.5, 1.0, 0)), - Some(Led(1.5, 1.0, 0)), - Some(Led(2.5, 1.0, 0)), - Some(Led(3.5, 1.0, 0)), - Some(Led(4.5, 1.0, 0)), - Some(Led(5.5, 1.0, 0)), - Some(Led(6.5, 1.0, 0)), - Some(Led(7.5, 1.0, 0)), - Some(Led(8.5, 1.0, 0)), - Some(Led(9.5, 1.0, 0)), - Some(Led(10.5, 1.0, 0)), - Some(Led(11.5, 1.0, 0)), - Some(Led(12.5, 1.0, 0)), - Some(Led(13.5, 1.0, 0)), - Some(Led(14.5, 1.0, 0)), - Some(Led(15.5, 1.0, 0)), - Some(Led(16.5, 1.0, 0)), - Some(Led(17.5, 1.0, 0)), - Some(Led(18.5, 1.0, 0)), - Some(Led(19.5, 1.0, 0)), - Some(Led(20.5, 1.0, 0)), - Some(Led(21.5, 1.0, 0)), - Some(Led(22.5, 1.0, 0)), - Some(Led(23.5, 1.0, 0)), - Some(Led(24.5, 1.0, 0)), - Some(Led(25.5, 1.0, 0)), - Some(Led(26.5, 1.0, 0)), - Some(Led(27.5, 1.0, 0)), - Some(Led(28.5, 1.0, 0)), - Some(Led(29.5, 1.0, 0)), - Some(Led(30.5, 1.0, 0)), - Some(Led(31.5, 1.0, 0)), - None, - None, - Some(Led(0.0, 2.0, 0)), - Some(Led(1.0, 2.0, 0)), - Some(Led(2.0, 2.0, 0)), - Some(Led(3.0, 2.0, 0)), - Some(Led(4.0, 2.0, 0)), - Some(Led(5.0, 2.0, 0)), - Some(Led(6.0, 2.0, 0)), - Some(Led(7.0, 2.0, 0)), - Some(Led(8.0, 2.0, 0)), - Some(Led(9.0, 2.0, 0)), - Some(Led(10.0, 2.0, 0)), - Some(Led(11.0, 2.0, 0)), - Some(Led(12.0, 2.0, 0)), - Some(Led(13.0, 2.0, 0)), - Some(Led(14.0, 2.0, 0)), - Some(Led(15.0, 2.0, 0)), - Some(Led(16.0, 2.0, 0)), - Some(Led(17.0, 2.0, 0)), - Some(Led(18.0, 2.0, 0)), - Some(Led(19.0, 2.0, 0)), - Some(Led(20.0, 2.0, 0)), - Some(Led(21.0, 2.0, 0)), - Some(Led(22.0, 2.0, 0)), - Some(Led(23.0, 2.0, 0)), - Some(Led(24.0, 2.0, 0)), - Some(Led(25.0, 2.0, 0)), - Some(Led(26.0, 2.0, 0)), - Some(Led(27.0, 2.0, 0)), - Some(Led(28.0, 2.0, 0)), - Some(Led(29.0, 2.0, 0)), - Some(Led(30.0, 2.0, 0)), - Some(Led(31.0, 2.0, 0)), - Some(Led(32.0, 2.0, 0)), - Some(Led(-0.5, 3.0, 0)), - Some(Led(0.5, 3.0, 0)), - Some(Led(1.5, 3.0, 0)), - Some(Led(2.5, 3.0, 0)), - Some(Led(3.5, 3.0, 0)), - Some(Led(4.5, 3.0, 0)), - Some(Led(5.5, 3.0, 0)), - Some(Led(6.5, 3.0, 0)), - Some(Led(7.5, 3.0, 0)), - Some(Led(8.5, 3.0, 0)), - Some(Led(9.5, 3.0, 0)), - Some(Led(10.5, 3.0, 0)), - Some(Led(11.5, 3.0, 0)), - Some(Led(12.5, 3.0, 0)), - Some(Led(13.5, 3.0, 0)), - Some(Led(14.5, 3.0, 0)), - Some(Led(15.5, 3.0, 0)), - Some(Led(16.5, 3.0, 0)), - Some(Led(17.5, 3.0, 0)), - Some(Led(18.5, 3.0, 0)), - Some(Led(19.5, 3.0, 0)), - Some(Led(20.5, 3.0, 0)), - Some(Led(21.5, 3.0, 0)), - Some(Led(22.5, 3.0, 0)), - Some(Led(23.5, 3.0, 0)), - Some(Led(24.5, 3.0, 0)), - Some(Led(25.5, 3.0, 0)), - Some(Led(26.5, 3.0, 0)), - Some(Led(27.5, 3.0, 0)), - Some(Led(28.5, 3.0, 0)), - Some(Led(29.5, 3.0, 0)), - Some(Led(30.5, 3.0, 0)), - Some(Led(31.5, 3.0, 0)), - None, - None, - Some(Led(0.0, 4.0, 0)), - Some(Led(1.0, 4.0, 0)), - Some(Led(2.0, 4.0, 0)), - Some(Led(3.0, 4.0, 0)), - Some(Led(4.0, 4.0, 0)), - Some(Led(5.0, 4.0, 0)), - Some(Led(6.0, 4.0, 0)), - Some(Led(7.0, 4.0, 0)), - Some(Led(8.0, 4.0, 0)), - Some(Led(9.0, 4.0, 0)), - Some(Led(10.0, 4.0, 0)), - Some(Led(11.0, 4.0, 0)), - Some(Led(12.0, 4.0, 0)), - Some(Led(13.0, 4.0, 0)), - Some(Led(14.0, 4.0, 0)), - Some(Led(15.0, 4.0, 0)), - Some(Led(16.0, 4.0, 0)), - Some(Led(17.0, 4.0, 0)), - Some(Led(18.0, 4.0, 0)), - Some(Led(19.0, 4.0, 0)), - Some(Led(20.0, 4.0, 0)), - Some(Led(21.0, 4.0, 0)), - Some(Led(22.0, 4.0, 0)), - Some(Led(23.0, 4.0, 0)), - Some(Led(24.0, 4.0, 0)), - Some(Led(25.0, 4.0, 0)), - Some(Led(26.0, 4.0, 0)), - Some(Led(27.0, 4.0, 0)), - Some(Led(28.0, 4.0, 0)), - Some(Led(29.0, 4.0, 0)), - Some(Led(30.0, 4.0, 0)), - Some(Led(31.0, 4.0, 0)), - Some(Led(32.0, 4.0, 0)), - Some(Led(-0.5, 5.0, 0)), - Some(Led(0.5, 5.0, 0)), - Some(Led(1.5, 5.0, 0)), - Some(Led(2.5, 5.0, 0)), - Some(Led(3.5, 5.0, 0)), - Some(Led(4.5, 5.0, 0)), - Some(Led(5.5, 5.0, 0)), - Some(Led(6.5, 5.0, 0)), - Some(Led(7.5, 5.0, 0)), - Some(Led(8.5, 5.0, 0)), - Some(Led(9.5, 5.0, 0)), - Some(Led(10.5, 5.0, 0)), - Some(Led(11.5, 5.0, 0)), - Some(Led(12.5, 5.0, 0)), - Some(Led(13.5, 5.0, 0)), - Some(Led(14.5, 5.0, 0)), - Some(Led(15.5, 5.0, 0)), - Some(Led(16.5, 5.0, 0)), - Some(Led(17.5, 5.0, 0)), - Some(Led(18.5, 5.0, 0)), - Some(Led(19.5, 5.0, 0)), - Some(Led(20.5, 5.0, 0)), - Some(Led(21.5, 5.0, 0)), - Some(Led(22.5, 5.0, 0)), - Some(Led(23.5, 5.0, 0)), - Some(Led(24.5, 5.0, 0)), - Some(Led(25.5, 5.0, 0)), - Some(Led(26.5, 5.0, 0)), - Some(Led(27.5, 5.0, 0)), - Some(Led(28.5, 5.0, 0)), - Some(Led(29.5, 5.0, 0)), - Some(Led(30.5, 5.0, 0)), - Some(Led(31.5, 5.0, 0)), - None, - Some(Led(0.0, 6.0, 0)), - Some(Led(1.0, 6.0, 0)), - Some(Led(2.0, 6.0, 0)), - Some(Led(3.0, 6.0, 0)), - Some(Led(4.0, 6.0, 0)), - Some(Led(5.0, 6.0, 0)), - Some(Led(6.0, 6.0, 0)), - Some(Led(7.0, 6.0, 0)), - Some(Led(8.0, 6.0, 0)), - Some(Led(9.0, 6.0, 0)), - Some(Led(10.0, 6.0, 0)), - Some(Led(11.0, 6.0, 0)), - Some(Led(12.0, 6.0, 0)), - Some(Led(13.0, 6.0, 0)), - Some(Led(14.0, 6.0, 0)), - Some(Led(15.0, 6.0, 0)), - Some(Led(16.0, 6.0, 0)), - Some(Led(17.0, 6.0, 0)), - Some(Led(18.0, 6.0, 0)), - Some(Led(19.0, 6.0, 0)), - Some(Led(20.0, 6.0, 0)), - Some(Led(21.0, 6.0, 0)), - Some(Led(22.0, 6.0, 0)), - Some(Led(23.0, 6.0, 0)), - Some(Led(24.0, 6.0, 0)), - Some(Led(25.0, 6.0, 0)), - Some(Led(26.0, 6.0, 0)), - Some(Led(27.0, 6.0, 0)), - Some(Led(28.0, 6.0, 0)), - Some(Led(29.0, 6.0, 0)), - Some(Led(30.0, 6.0, 0)), - Some(Led(31.0, 6.0, 0)), - Some(Led(32.0, 6.0, 0)), - Some(Led(0.5, 7.0, 0)), - Some(Led(1.5, 7.0, 0)), - Some(Led(2.5, 7.0, 0)), - Some(Led(3.5, 7.0, 0)), - Some(Led(4.5, 7.0, 0)), - Some(Led(5.5, 7.0, 0)), - Some(Led(6.5, 7.0, 0)), - Some(Led(7.5, 7.0, 0)), - Some(Led(8.5, 7.0, 0)), - Some(Led(9.5, 7.0, 0)), - Some(Led(10.5, 7.0, 0)), - Some(Led(11.5, 7.0, 0)), - Some(Led(12.5, 7.0, 0)), - Some(Led(13.5, 7.0, 0)), - Some(Led(14.5, 7.0, 0)), - Some(Led(15.5, 7.0, 0)), - Some(Led(16.5, 7.0, 0)), - Some(Led(17.5, 7.0, 0)), - Some(Led(18.5, 7.0, 0)), - Some(Led(19.5, 7.0, 0)), - Some(Led(20.5, 7.0, 0)), - Some(Led(21.5, 7.0, 0)), - Some(Led(22.5, 7.0, 0)), - Some(Led(23.5, 7.0, 0)), - Some(Led(24.5, 7.0, 0)), - Some(Led(25.5, 7.0, 0)), - Some(Led(26.5, 7.0, 0)), - Some(Led(27.5, 7.0, 0)), - Some(Led(28.5, 7.0, 0)), - Some(Led(29.5, 7.0, 0)), - Some(Led(30.5, 7.0, 0)), - Some(Led(31.5, 7.0, 0)), - None, - Some(Led(1.0, 8.0, 0)), - Some(Led(2.0, 8.0, 0)), - Some(Led(3.0, 8.0, 0)), - Some(Led(4.0, 8.0, 0)), - Some(Led(5.0, 8.0, 0)), - Some(Led(6.0, 8.0, 0)), - Some(Led(7.0, 8.0, 0)), - Some(Led(8.0, 8.0, 0)), - Some(Led(9.0, 8.0, 0)), - Some(Led(10.0, 8.0, 0)), - Some(Led(11.0, 8.0, 0)), - Some(Led(12.0, 8.0, 0)), - Some(Led(13.0, 8.0, 0)), - Some(Led(14.0, 8.0, 0)), - Some(Led(15.0, 8.0, 0)), - Some(Led(16.0, 8.0, 0)), - Some(Led(17.0, 8.0, 0)), - Some(Led(18.0, 8.0, 0)), - Some(Led(19.0, 8.0, 0)), - Some(Led(20.0, 8.0, 0)), - Some(Led(21.0, 8.0, 0)), - Some(Led(22.0, 8.0, 0)), - Some(Led(23.0, 8.0, 0)), - Some(Led(24.0, 8.0, 0)), - Some(Led(25.0, 8.0, 0)), - Some(Led(26.0, 8.0, 0)), - Some(Led(27.0, 8.0, 0)), - Some(Led(28.0, 8.0, 0)), - Some(Led(29.0, 8.0, 0)), - Some(Led(30.0, 8.0, 0)), - Some(Led(31.0, 8.0, 0)), - Some(Led(32.0, 8.0, 0)), - Some(Led(1.5, 9.0, 0)), - Some(Led(2.5, 9.0, 0)), - Some(Led(3.5, 9.0, 0)), - Some(Led(4.5, 9.0, 0)), - Some(Led(5.5, 9.0, 0)), - Some(Led(6.5, 9.0, 0)), - Some(Led(7.5, 9.0, 0)), - Some(Led(8.5, 9.0, 0)), - Some(Led(9.5, 9.0, 0)), - Some(Led(10.5, 9.0, 0)), - Some(Led(11.5, 9.0, 0)), - Some(Led(12.5, 9.0, 0)), - Some(Led(13.5, 9.0, 0)), - Some(Led(14.5, 9.0, 0)), - Some(Led(15.5, 9.0, 0)), - Some(Led(16.5, 9.0, 0)), - Some(Led(17.5, 9.0, 0)), - Some(Led(18.5, 9.0, 0)), - Some(Led(19.5, 9.0, 0)), - Some(Led(20.5, 9.0, 0)), - Some(Led(21.5, 9.0, 0)), - Some(Led(22.5, 9.0, 0)), - Some(Led(23.5, 9.0, 0)), - Some(Led(24.5, 9.0, 0)), - Some(Led(25.5, 9.0, 0)), - Some(Led(26.5, 9.0, 0)), - Some(Led(27.5, 9.0, 0)), - Some(Led(28.5, 9.0, 0)), - Some(Led(29.5, 9.0, 0)), - Some(Led(30.5, 9.0, 0)), - Some(Led(31.5, 9.0, 0)), - None, - Some(Led(2.0, 10.0, 0)), - Some(Led(3.0, 10.0, 0)), - Some(Led(4.0, 10.0, 0)), - Some(Led(5.0, 10.0, 0)), - Some(Led(6.0, 10.0, 0)), - Some(Led(7.0, 10.0, 0)), - Some(Led(8.0, 10.0, 0)), - Some(Led(9.0, 10.0, 0)), - Some(Led(10.0, 10.0, 0)), - Some(Led(11.0, 10.0, 0)), - Some(Led(12.0, 10.0, 0)), - Some(Led(13.0, 10.0, 0)), - Some(Led(14.0, 10.0, 0)), - Some(Led(15.0, 10.0, 0)), - Some(Led(16.0, 10.0, 0)), - Some(Led(17.0, 10.0, 0)), - Some(Led(18.0, 10.0, 0)), - Some(Led(19.0, 10.0, 0)), - Some(Led(20.0, 10.0, 0)), - Some(Led(21.0, 10.0, 0)), - Some(Led(22.0, 10.0, 0)), - Some(Led(23.0, 10.0, 0)), - Some(Led(24.0, 10.0, 0)), - Some(Led(25.0, 10.0, 0)), - Some(Led(26.0, 10.0, 0)), - Some(Led(27.0, 10.0, 0)), - Some(Led(28.0, 10.0, 0)), - Some(Led(29.0, 10.0, 0)), - Some(Led(30.0, 10.0, 0)), - Some(Led(31.0, 10.0, 0)), - Some(Led(32.0, 10.0, 0)), - Some(Led(2.5, 11.0, 0)), - Some(Led(3.5, 11.0, 0)), - Some(Led(4.5, 11.0, 0)), - Some(Led(5.5, 11.0, 0)), - Some(Led(6.5, 11.0, 0)), - Some(Led(7.5, 11.0, 0)), - Some(Led(8.5, 11.0, 0)), - Some(Led(9.5, 11.0, 0)), - Some(Led(10.5, 11.0, 0)), - Some(Led(11.5, 11.0, 0)), - Some(Led(12.5, 11.0, 0)), - Some(Led(13.5, 11.0, 0)), - Some(Led(14.5, 11.0, 0)), - Some(Led(15.5, 11.0, 0)), - Some(Led(16.5, 11.0, 0)), - Some(Led(17.5, 11.0, 0)), - Some(Led(18.5, 11.0, 0)), - Some(Led(19.5, 11.0, 0)), - Some(Led(20.5, 11.0, 0)), - Some(Led(21.5, 11.0, 0)), - Some(Led(22.5, 11.0, 0)), - Some(Led(23.5, 11.0, 0)), - Some(Led(24.5, 11.0, 0)), - Some(Led(25.5, 11.0, 0)), - Some(Led(26.5, 11.0, 0)), - Some(Led(27.5, 11.0, 0)), - Some(Led(28.5, 11.0, 0)), - Some(Led(29.5, 11.0, 0)), - Some(Led(30.5, 11.0, 0)), - Some(Led(31.5, 11.0, 0)), - None, - Some(Led(3.0, 12.0, 0)), - Some(Led(4.0, 12.0, 0)), - Some(Led(5.0, 12.0, 0)), - Some(Led(6.0, 12.0, 0)), - Some(Led(7.0, 12.0, 0)), - Some(Led(8.0, 12.0, 0)), - Some(Led(9.0, 12.0, 0)), - Some(Led(10.0, 12.0, 0)), - Some(Led(11.0, 12.0, 0)), - Some(Led(12.0, 12.0, 0)), - Some(Led(13.0, 12.0, 0)), - Some(Led(14.0, 12.0, 0)), - Some(Led(15.0, 12.0, 0)), - Some(Led(16.0, 12.0, 0)), - Some(Led(17.0, 12.0, 0)), - Some(Led(18.0, 12.0, 0)), - Some(Led(19.0, 12.0, 0)), - Some(Led(20.0, 12.0, 0)), - Some(Led(21.0, 12.0, 0)), - Some(Led(22.0, 12.0, 0)), - Some(Led(23.0, 12.0, 0)), - Some(Led(24.0, 12.0, 0)), - Some(Led(25.0, 12.0, 0)), - Some(Led(26.0, 12.0, 0)), - Some(Led(27.0, 12.0, 0)), - Some(Led(28.0, 12.0, 0)), - Some(Led(29.0, 12.0, 0)), - Some(Led(30.0, 12.0, 0)), - Some(Led(31.0, 12.0, 0)), - Some(Led(32.0, 12.0, 0)), - Some(Led(3.5, 13.0, 0)), - Some(Led(4.5, 13.0, 0)), - Some(Led(5.5, 13.0, 0)), - Some(Led(6.5, 13.0, 0)), - Some(Led(7.5, 13.0, 0)), - Some(Led(8.5, 13.0, 0)), - Some(Led(9.5, 13.0, 0)), - Some(Led(10.5, 13.0, 0)), - Some(Led(11.5, 13.0, 0)), - Some(Led(12.5, 13.0, 0)), - Some(Led(13.5, 13.0, 0)), - Some(Led(14.5, 13.0, 0)), - Some(Led(15.5, 13.0, 0)), - Some(Led(16.5, 13.0, 0)), - Some(Led(17.5, 13.0, 0)), - Some(Led(18.5, 13.0, 0)), - Some(Led(19.5, 13.0, 0)), - Some(Led(20.5, 13.0, 0)), - Some(Led(21.5, 13.0, 0)), - Some(Led(22.5, 13.0, 0)), - Some(Led(23.5, 13.0, 0)), - Some(Led(24.5, 13.0, 0)), - Some(Led(25.5, 13.0, 0)), - Some(Led(26.5, 13.0, 0)), - Some(Led(27.5, 13.0, 0)), - Some(Led(28.5, 13.0, 0)), - Some(Led(29.5, 13.0, 0)), - Some(Led(30.5, 13.0, 0)), - Some(Led(31.5, 13.0, 0)), - None, - Some(Led(4.0, 14.0, 0)), - Some(Led(5.0, 14.0, 0)), - Some(Led(6.0, 14.0, 0)), - Some(Led(7.0, 14.0, 0)), - Some(Led(8.0, 14.0, 0)), - Some(Led(9.0, 14.0, 0)), - Some(Led(10.0, 14.0, 0)), - Some(Led(11.0, 14.0, 0)), - Some(Led(12.0, 14.0, 0)), - Some(Led(13.0, 14.0, 0)), - Some(Led(14.0, 14.0, 0)), - Some(Led(15.0, 14.0, 0)), - Some(Led(16.0, 14.0, 0)), - Some(Led(17.0, 14.0, 0)), - Some(Led(18.0, 14.0, 0)), - Some(Led(19.0, 14.0, 0)), - Some(Led(20.0, 14.0, 0)), - Some(Led(21.0, 14.0, 0)), - Some(Led(22.0, 14.0, 0)), - Some(Led(23.0, 14.0, 0)), - Some(Led(24.0, 14.0, 0)), - Some(Led(25.0, 14.0, 0)), - Some(Led(26.0, 14.0, 0)), - Some(Led(27.0, 14.0, 0)), - Some(Led(28.0, 14.0, 0)), - Some(Led(29.0, 14.0, 0)), - Some(Led(30.0, 14.0, 0)), - Some(Led(31.0, 14.0, 0)), - Some(Led(32.0, 14.0, 0)), - Some(Led(4.5, 15.0, 0)), - Some(Led(5.5, 15.0, 0)), - Some(Led(6.5, 15.0, 0)), - Some(Led(7.5, 15.0, 0)), - Some(Led(8.5, 15.0, 0)), - Some(Led(9.5, 15.0, 0)), - Some(Led(10.5, 15.0, 0)), - Some(Led(11.5, 15.0, 0)), - Some(Led(12.5, 15.0, 0)), - Some(Led(13.5, 15.0, 0)), - Some(Led(14.5, 15.0, 0)), - Some(Led(15.5, 15.0, 0)), - Some(Led(16.5, 15.0, 0)), - Some(Led(17.5, 15.0, 0)), - Some(Led(18.5, 15.0, 0)), - Some(Led(19.5, 15.0, 0)), - Some(Led(20.5, 15.0, 0)), - Some(Led(21.5, 15.0, 0)), - Some(Led(22.5, 15.0, 0)), - Some(Led(23.5, 15.0, 0)), - Some(Led(24.5, 15.0, 0)), - Some(Led(25.5, 15.0, 0)), - Some(Led(26.5, 15.0, 0)), - Some(Led(27.5, 15.0, 0)), - Some(Led(28.5, 15.0, 0)), - Some(Led(29.5, 15.0, 0)), - Some(Led(30.5, 15.0, 0)), - Some(Led(31.5, 15.0, 0)), - None, - Some(Led(5.0, 16.0, 0)), - Some(Led(6.0, 16.0, 0)), - Some(Led(7.0, 16.0, 0)), - Some(Led(8.0, 16.0, 0)), - Some(Led(9.0, 16.0, 0)), - Some(Led(10.0, 16.0, 0)), - Some(Led(11.0, 16.0, 0)), - Some(Led(12.0, 16.0, 0)), - Some(Led(13.0, 16.0, 0)), - Some(Led(14.0, 16.0, 0)), - Some(Led(15.0, 16.0, 0)), - Some(Led(16.0, 16.0, 0)), - Some(Led(17.0, 16.0, 0)), - Some(Led(18.0, 16.0, 0)), - Some(Led(19.0, 16.0, 0)), - Some(Led(20.0, 16.0, 0)), - Some(Led(21.0, 16.0, 0)), - Some(Led(22.0, 16.0, 0)), - Some(Led(23.0, 16.0, 0)), - Some(Led(24.0, 16.0, 0)), - Some(Led(25.0, 16.0, 0)), - Some(Led(26.0, 16.0, 0)), - Some(Led(27.0, 16.0, 0)), - Some(Led(28.0, 16.0, 0)), - Some(Led(29.0, 16.0, 0)), - Some(Led(30.0, 16.0, 0)), - Some(Led(31.0, 16.0, 0)), - Some(Led(32.0, 16.0, 0)), - Some(Led(5.5, 17.0, 0)), - Some(Led(6.5, 17.0, 0)), - Some(Led(7.5, 17.0, 0)), - Some(Led(8.5, 17.0, 0)), - Some(Led(9.5, 17.0, 0)), - Some(Led(10.5, 17.0, 0)), - Some(Led(11.5, 17.0, 0)), - Some(Led(12.5, 17.0, 0)), - Some(Led(13.5, 17.0, 0)), - Some(Led(14.5, 17.0, 0)), - Some(Led(15.5, 17.0, 0)), - Some(Led(16.5, 17.0, 0)), - Some(Led(17.5, 17.0, 0)), - Some(Led(18.5, 17.0, 0)), - Some(Led(19.5, 17.0, 0)), - Some(Led(20.5, 17.0, 0)), - Some(Led(21.5, 17.0, 0)), - Some(Led(22.5, 17.0, 0)), - Some(Led(23.5, 17.0, 0)), - Some(Led(24.5, 17.0, 0)), - Some(Led(25.5, 17.0, 0)), - Some(Led(26.5, 17.0, 0)), - Some(Led(27.5, 17.0, 0)), - Some(Led(28.5, 17.0, 0)), - Some(Led(29.5, 17.0, 0)), - Some(Led(30.5, 17.0, 0)), - Some(Led(31.5, 17.0, 0)), - None, - Some(Led(6.0, 18.0, 0)), - Some(Led(7.0, 18.0, 0)), - Some(Led(8.0, 18.0, 0)), - Some(Led(9.0, 18.0, 0)), - Some(Led(10.0, 18.0, 0)), - Some(Led(11.0, 18.0, 0)), - Some(Led(12.0, 18.0, 0)), - Some(Led(13.0, 18.0, 0)), - Some(Led(14.0, 18.0, 0)), - Some(Led(15.0, 18.0, 0)), - Some(Led(16.0, 18.0, 0)), - Some(Led(17.0, 18.0, 0)), - Some(Led(18.0, 18.0, 0)), - Some(Led(19.0, 18.0, 0)), - Some(Led(20.0, 18.0, 0)), - Some(Led(21.0, 18.0, 0)), - Some(Led(22.0, 18.0, 0)), - Some(Led(23.0, 18.0, 0)), - Some(Led(24.0, 18.0, 0)), - Some(Led(25.0, 18.0, 0)), - Some(Led(26.0, 18.0, 0)), - Some(Led(27.0, 18.0, 0)), - Some(Led(28.0, 18.0, 0)), - Some(Led(29.0, 18.0, 0)), - Some(Led(30.0, 18.0, 0)), - Some(Led(31.0, 18.0, 0)), - Some(Led(32.0, 18.0, 0)), - Some(Led(6.5, 19.0, 0)), - Some(Led(7.5, 19.0, 0)), - Some(Led(8.5, 19.0, 0)), - Some(Led(9.5, 19.0, 0)), - Some(Led(10.5, 19.0, 0)), - Some(Led(11.5, 19.0, 0)), - Some(Led(12.5, 19.0, 0)), - Some(Led(13.5, 19.0, 0)), - Some(Led(14.5, 19.0, 0)), - Some(Led(15.5, 19.0, 0)), - Some(Led(16.5, 19.0, 0)), - Some(Led(17.5, 19.0, 0)), - Some(Led(18.5, 19.0, 0)), - Some(Led(19.5, 19.0, 0)), - Some(Led(20.5, 19.0, 0)), - Some(Led(21.5, 19.0, 0)), - Some(Led(22.5, 19.0, 0)), - Some(Led(23.5, 19.0, 0)), - Some(Led(24.5, 19.0, 0)), - Some(Led(25.5, 19.0, 0)), - Some(Led(26.5, 19.0, 0)), - Some(Led(27.5, 19.0, 0)), - Some(Led(28.5, 19.0, 0)), - Some(Led(29.5, 19.0, 0)), - Some(Led(30.5, 19.0, 0)), - Some(Led(31.5, 19.0, 0)), - None, - Some(Led(7.0, 20.0, 0)), - Some(Led(8.0, 20.0, 0)), - Some(Led(9.0, 20.0, 0)), - Some(Led(10.0, 20.0, 0)), - Some(Led(11.0, 20.0, 0)), - Some(Led(12.0, 20.0, 0)), - Some(Led(13.0, 20.0, 0)), - Some(Led(14.0, 20.0, 0)), - Some(Led(15.0, 20.0, 0)), - Some(Led(16.0, 20.0, 0)), - Some(Led(17.0, 20.0, 0)), - Some(Led(18.0, 20.0, 0)), - Some(Led(19.0, 20.0, 0)), - Some(Led(20.0, 20.0, 0)), - Some(Led(21.0, 20.0, 0)), - Some(Led(22.0, 20.0, 0)), - Some(Led(23.0, 20.0, 0)), - Some(Led(24.0, 20.0, 0)), - Some(Led(25.0, 20.0, 0)), - Some(Led(26.0, 20.0, 0)), - Some(Led(27.0, 20.0, 0)), - Some(Led(28.0, 20.0, 0)), - Some(Led(29.0, 20.0, 0)), - Some(Led(30.0, 20.0, 0)), - Some(Led(31.0, 20.0, 0)), - Some(Led(32.0, 20.0, 0)), - Some(Led(7.5, 21.0, 0)), - Some(Led(8.5, 21.0, 0)), - Some(Led(9.5, 21.0, 0)), - Some(Led(10.5, 21.0, 0)), - Some(Led(11.5, 21.0, 0)), - Some(Led(12.5, 21.0, 0)), - Some(Led(13.5, 21.0, 0)), - Some(Led(14.5, 21.0, 0)), - Some(Led(15.5, 21.0, 0)), - Some(Led(16.5, 21.0, 0)), - Some(Led(17.5, 21.0, 0)), - Some(Led(18.5, 21.0, 0)), - Some(Led(19.5, 21.0, 0)), - Some(Led(20.5, 21.0, 0)), - Some(Led(21.5, 21.0, 0)), - Some(Led(22.5, 21.0, 0)), - Some(Led(23.5, 21.0, 0)), - Some(Led(24.5, 21.0, 0)), - Some(Led(25.5, 21.0, 0)), - Some(Led(26.5, 21.0, 0)), - Some(Led(27.5, 21.0, 0)), - Some(Led(28.5, 21.0, 0)), - Some(Led(29.5, 21.0, 0)), - Some(Led(30.5, 21.0, 0)), - Some(Led(31.5, 21.0, 0)), - None, - Some(Led(8.0, 22.0, 0)), - Some(Led(9.0, 22.0, 0)), - Some(Led(10.0, 22.0, 0)), - Some(Led(11.0, 22.0, 0)), - Some(Led(12.0, 22.0, 0)), - Some(Led(13.0, 22.0, 0)), - Some(Led(14.0, 22.0, 0)), - Some(Led(15.0, 22.0, 0)), - Some(Led(16.0, 22.0, 0)), - Some(Led(17.0, 22.0, 0)), - Some(Led(18.0, 22.0, 0)), - Some(Led(19.0, 22.0, 0)), - Some(Led(20.0, 22.0, 0)), - Some(Led(21.0, 22.0, 0)), - Some(Led(22.0, 22.0, 0)), - Some(Led(23.0, 22.0, 0)), - Some(Led(24.0, 22.0, 0)), - Some(Led(25.0, 22.0, 0)), - Some(Led(26.0, 22.0, 0)), - Some(Led(27.0, 22.0, 0)), - Some(Led(28.0, 22.0, 0)), - Some(Led(29.0, 22.0, 0)), - Some(Led(30.0, 22.0, 0)), - Some(Led(31.0, 22.0, 0)), - Some(Led(32.0, 22.0, 0)), - Some(Led(8.5, 23.0, 0)), - Some(Led(9.5, 23.0, 0)), - Some(Led(10.5, 23.0, 0)), - Some(Led(11.5, 23.0, 0)), - Some(Led(12.5, 23.0, 0)), - Some(Led(13.5, 23.0, 0)), - Some(Led(14.5, 23.0, 0)), - Some(Led(15.5, 23.0, 0)), - Some(Led(16.5, 23.0, 0)), - Some(Led(17.5, 23.0, 0)), - Some(Led(18.5, 23.0, 0)), - Some(Led(19.5, 23.0, 0)), - Some(Led(20.5, 23.0, 0)), - Some(Led(21.5, 23.0, 0)), - Some(Led(22.5, 23.0, 0)), - Some(Led(23.5, 23.0, 0)), - Some(Led(24.5, 23.0, 0)), - Some(Led(25.5, 23.0, 0)), - Some(Led(26.5, 23.0, 0)), - Some(Led(27.5, 23.0, 0)), - Some(Led(28.5, 23.0, 0)), - Some(Led(29.5, 23.0, 0)), - Some(Led(30.5, 23.0, 0)), - Some(Led(31.5, 23.0, 0)), - None, - Some(Led(9.0, 24.0, 0)), - Some(Led(10.0, 24.0, 0)), - Some(Led(11.0, 24.0, 0)), - Some(Led(12.0, 24.0, 0)), - Some(Led(13.0, 24.0, 0)), - Some(Led(14.0, 24.0, 0)), - Some(Led(15.0, 24.0, 0)), - Some(Led(16.0, 24.0, 0)), - Some(Led(17.0, 24.0, 0)), - Some(Led(18.0, 24.0, 0)), - Some(Led(19.0, 24.0, 0)), - Some(Led(20.0, 24.0, 0)), - Some(Led(21.0, 24.0, 0)), - Some(Led(22.0, 24.0, 0)), - Some(Led(23.0, 24.0, 0)), - Some(Led(24.0, 24.0, 0)), - Some(Led(25.0, 24.0, 0)), - Some(Led(26.0, 24.0, 0)), - Some(Led(27.0, 24.0, 0)), - Some(Led(28.0, 24.0, 0)), - Some(Led(29.0, 24.0, 0)), - Some(Led(30.0, 24.0, 0)), - Some(Led(31.0, 24.0, 0)), - Some(Led(32.0, 24.0, 0)), - Some(Led(9.5, 25.0, 0)), - Some(Led(10.5, 25.0, 0)), - Some(Led(11.5, 25.0, 0)), - Some(Led(12.5, 25.0, 0)), - Some(Led(13.5, 25.0, 0)), - Some(Led(14.5, 25.0, 0)), - Some(Led(15.5, 25.0, 0)), - Some(Led(16.5, 25.0, 0)), - Some(Led(17.5, 25.0, 0)), - Some(Led(18.5, 25.0, 0)), - Some(Led(19.5, 25.0, 0)), - Some(Led(20.5, 25.0, 0)), - Some(Led(21.5, 25.0, 0)), - Some(Led(22.5, 25.0, 0)), - Some(Led(23.5, 25.0, 0)), - Some(Led(24.5, 25.0, 0)), - Some(Led(25.5, 25.0, 0)), - Some(Led(26.5, 25.0, 0)), - Some(Led(27.5, 25.0, 0)), - Some(Led(28.5, 25.0, 0)), - Some(Led(29.5, 25.0, 0)), - Some(Led(30.5, 25.0, 0)), - Some(Led(31.5, 25.0, 0)), - None, - Some(Led(10.0, 26.0, 0)), - Some(Led(11.0, 26.0, 0)), - Some(Led(12.0, 26.0, 0)), - Some(Led(13.0, 26.0, 0)), - Some(Led(14.0, 26.0, 0)), - Some(Led(15.0, 26.0, 0)), - Some(Led(16.0, 26.0, 0)), - Some(Led(17.0, 26.0, 0)), - Some(Led(18.0, 26.0, 0)), - Some(Led(19.0, 26.0, 0)), - Some(Led(20.0, 26.0, 0)), - Some(Led(21.0, 26.0, 0)), - Some(Led(22.0, 26.0, 0)), - Some(Led(23.0, 26.0, 0)), - Some(Led(24.0, 26.0, 0)), - Some(Led(25.0, 26.0, 0)), - Some(Led(26.0, 26.0, 0)), - Some(Led(27.0, 26.0, 0)), - Some(Led(28.0, 26.0, 0)), - Some(Led(29.0, 26.0, 0)), - Some(Led(30.0, 26.0, 0)), - Some(Led(31.0, 26.0, 0)), - Some(Led(32.0, 26.0, 0)), - Some(Led(10.5, 27.0, 0)), - Some(Led(11.5, 27.0, 0)), - Some(Led(12.5, 27.0, 0)), - Some(Led(13.5, 27.0, 0)), - Some(Led(14.5, 27.0, 0)), - Some(Led(15.5, 27.0, 0)), - Some(Led(16.5, 27.0, 0)), - Some(Led(17.5, 27.0, 0)), - Some(Led(18.5, 27.0, 0)), - Some(Led(19.5, 27.0, 0)), - Some(Led(20.5, 27.0, 0)), - Some(Led(21.5, 27.0, 0)), - Some(Led(22.5, 27.0, 0)), - Some(Led(23.5, 27.0, 0)), - Some(Led(24.5, 27.0, 0)), - Some(Led(25.5, 27.0, 0)), - Some(Led(26.5, 27.0, 0)), - Some(Led(27.5, 27.0, 0)), - Some(Led(28.5, 27.0, 0)), - Some(Led(29.5, 27.0, 0)), - Some(Led(30.5, 27.0, 0)), - Some(Led(31.5, 27.0, 0)), - None, - Some(Led(11.0, 28.0, 0)), - Some(Led(12.0, 28.0, 0)), - Some(Led(13.0, 28.0, 0)), - Some(Led(14.0, 28.0, 0)), - Some(Led(15.0, 28.0, 0)), - Some(Led(16.0, 28.0, 0)), - Some(Led(17.0, 28.0, 0)), - Some(Led(18.0, 28.0, 0)), - Some(Led(19.0, 28.0, 0)), - Some(Led(20.0, 28.0, 0)), - Some(Led(21.0, 28.0, 0)), - Some(Led(22.0, 28.0, 0)), - Some(Led(23.0, 28.0, 0)), - Some(Led(24.0, 28.0, 0)), - Some(Led(25.0, 28.0, 0)), - Some(Led(26.0, 28.0, 0)), - Some(Led(27.0, 28.0, 0)), - Some(Led(28.0, 28.0, 0)), - Some(Led(29.0, 28.0, 0)), - Some(Led(30.0, 28.0, 0)), - Some(Led(31.0, 28.0, 0)), - Some(Led(32.0, 28.0, 0)), - Some(Led(11.5, 29.0, 0)), - Some(Led(12.5, 29.0, 0)), - Some(Led(13.5, 29.0, 0)), - Some(Led(14.5, 29.0, 0)), - Some(Led(15.5, 29.0, 0)), - Some(Led(16.5, 29.0, 0)), - Some(Led(17.5, 29.0, 0)), - Some(Led(18.5, 29.0, 0)), - Some(Led(19.5, 29.0, 0)), - Some(Led(20.5, 29.0, 0)), - Some(Led(21.5, 29.0, 0)), - Some(Led(22.5, 29.0, 0)), - Some(Led(23.5, 29.0, 0)), - Some(Led(24.5, 29.0, 0)), - Some(Led(25.5, 29.0, 0)), - Some(Led(26.5, 29.0, 0)), - Some(Led(27.5, 29.0, 0)), - Some(Led(28.5, 29.0, 0)), - Some(Led(29.5, 29.0, 0)), - Some(Led(30.5, 29.0, 0)), - Some(Led(31.5, 29.0, 0)), - None, - Some(Led(12.0, 30.0, 0)), - Some(Led(13.0, 30.0, 0)), - Some(Led(14.0, 30.0, 0)), - Some(Led(15.0, 30.0, 0)), - Some(Led(16.0, 30.0, 0)), - Some(Led(17.0, 30.0, 0)), - Some(Led(18.0, 30.0, 0)), - Some(Led(19.0, 30.0, 0)), - Some(Led(20.0, 30.0, 0)), - Some(Led(21.0, 30.0, 0)), - Some(Led(22.0, 30.0, 0)), - Some(Led(23.0, 30.0, 0)), - Some(Led(24.0, 30.0, 0)), - Some(Led(25.0, 30.0, 0)), - Some(Led(26.0, 30.0, 0)), - Some(Led(27.0, 30.0, 0)), - Some(Led(28.0, 30.0, 0)), - Some(Led(29.0, 30.0, 0)), - Some(Led(30.0, 30.0, 0)), - Some(Led(31.0, 30.0, 0)), - Some(Led(32.0, 30.0, 0)), - Some(Led(12.5, 31.0, 0)), - Some(Led(13.5, 31.0, 0)), - Some(Led(14.5, 31.0, 0)), - Some(Led(15.5, 31.0, 0)), - Some(Led(16.5, 31.0, 0)), - Some(Led(17.5, 31.0, 0)), - Some(Led(18.5, 31.0, 0)), - Some(Led(19.5, 31.0, 0)), - Some(Led(20.5, 31.0, 0)), - Some(Led(21.5, 31.0, 0)), - Some(Led(22.5, 31.0, 0)), - Some(Led(23.5, 31.0, 0)), - Some(Led(24.5, 31.0, 0)), - Some(Led(25.5, 31.0, 0)), - Some(Led(26.5, 31.0, 0)), - Some(Led(27.5, 31.0, 0)), - Some(Led(28.5, 31.0, 0)), - Some(Led(29.5, 31.0, 0)), - Some(Led(30.5, 31.0, 0)), - Some(Led(31.5, 31.0, 0)), - None, - Some(Led(13.0, 32.0, 0)), - Some(Led(14.0, 32.0, 0)), - Some(Led(15.0, 32.0, 0)), - Some(Led(16.0, 32.0, 0)), - Some(Led(17.0, 32.0, 0)), - Some(Led(18.0, 32.0, 0)), - Some(Led(19.0, 32.0, 0)), - Some(Led(20.0, 32.0, 0)), - Some(Led(21.0, 32.0, 0)), - Some(Led(22.0, 32.0, 0)), - Some(Led(23.0, 32.0, 0)), - Some(Led(24.0, 32.0, 0)), - Some(Led(25.0, 32.0, 0)), - Some(Led(26.0, 32.0, 0)), - Some(Led(27.0, 32.0, 0)), - Some(Led(28.0, 32.0, 0)), - Some(Led(29.0, 32.0, 0)), - Some(Led(30.0, 32.0, 0)), - Some(Led(31.0, 32.0, 0)), - Some(Led(32.0, 32.0, 0)), - Some(Led(13.5, 33.0, 0)), - Some(Led(14.5, 33.0, 0)), - Some(Led(15.5, 33.0, 0)), - Some(Led(16.5, 33.0, 0)), - Some(Led(17.5, 33.0, 0)), - Some(Led(18.5, 33.0, 0)), - Some(Led(19.5, 33.0, 0)), - Some(Led(20.5, 33.0, 0)), - Some(Led(21.5, 33.0, 0)), - Some(Led(22.5, 33.0, 0)), - Some(Led(23.5, 33.0, 0)), - Some(Led(24.5, 33.0, 0)), - Some(Led(25.5, 33.0, 0)), - Some(Led(26.5, 33.0, 0)), - Some(Led(27.5, 33.0, 0)), - Some(Led(28.5, 33.0, 0)), - Some(Led(29.5, 33.0, 0)), - Some(Led(30.5, 33.0, 0)), - Some(Led(31.5, 33.0, 0)), - None, - Some(Led(14.0, 34.0, 0)), - Some(Led(15.0, 34.0, 0)), - Some(Led(16.0, 34.0, 0)), - Some(Led(17.0, 34.0, 0)), - Some(Led(18.0, 34.0, 0)), - Some(Led(19.0, 34.0, 0)), - Some(Led(20.0, 34.0, 0)), - Some(Led(21.0, 34.0, 0)), - Some(Led(22.0, 34.0, 0)), - Some(Led(23.0, 34.0, 0)), - Some(Led(24.0, 34.0, 0)), - Some(Led(25.0, 34.0, 0)), - Some(Led(26.0, 34.0, 0)), - Some(Led(27.0, 34.0, 0)), - Some(Led(28.0, 34.0, 0)), - Some(Led(29.0, 34.0, 0)), - Some(Led(30.0, 34.0, 0)), - Some(Led(31.0, 34.0, 0)), - Some(Led(32.0, 34.0, 0)), - Some(Led(14.5, 35.0, 0)), - Some(Led(15.5, 35.0, 0)), - Some(Led(16.5, 35.0, 0)), - Some(Led(17.5, 35.0, 0)), - Some(Led(18.5, 35.0, 0)), - Some(Led(19.5, 35.0, 0)), - Some(Led(20.5, 35.0, 0)), - Some(Led(21.5, 35.0, 0)), - Some(Led(22.5, 35.0, 0)), - Some(Led(23.5, 35.0, 0)), - Some(Led(24.5, 35.0, 0)), - Some(Led(25.5, 35.0, 0)), - Some(Led(26.5, 35.0, 0)), - Some(Led(27.5, 35.0, 0)), - Some(Led(28.5, 35.0, 0)), - Some(Led(29.5, 35.0, 0)), - Some(Led(30.5, 35.0, 0)), - Some(Led(31.5, 35.0, 0)), - None, - Some(Led(15.0, 36.0, 0)), - Some(Led(16.0, 36.0, 0)), - Some(Led(17.0, 36.0, 0)), - Some(Led(18.0, 36.0, 0)), - Some(Led(19.0, 36.0, 0)), - Some(Led(20.0, 36.0, 0)), - Some(Led(21.0, 36.0, 0)), - Some(Led(22.0, 36.0, 0)), - Some(Led(23.0, 36.0, 0)), - Some(Led(24.0, 36.0, 0)), - Some(Led(25.0, 36.0, 0)), - Some(Led(26.0, 36.0, 0)), - Some(Led(27.0, 36.0, 0)), - Some(Led(28.0, 36.0, 0)), - Some(Led(29.0, 36.0, 0)), - Some(Led(30.0, 36.0, 0)), - Some(Led(31.0, 36.0, 0)), - Some(Led(32.0, 36.0, 0)), - Some(Led(15.5, 37.0, 0)), - Some(Led(16.5, 37.0, 0)), - Some(Led(17.5, 37.0, 0)), - Some(Led(18.5, 37.0, 0)), - Some(Led(19.5, 37.0, 0)), - Some(Led(20.5, 37.0, 0)), - Some(Led(21.5, 37.0, 0)), - Some(Led(22.5, 37.0, 0)), - Some(Led(23.5, 37.0, 0)), - Some(Led(24.5, 37.0, 0)), - Some(Led(25.5, 37.0, 0)), - Some(Led(26.5, 37.0, 0)), - Some(Led(27.5, 37.0, 0)), - Some(Led(28.5, 37.0, 0)), - Some(Led(29.5, 37.0, 0)), - Some(Led(30.5, 37.0, 0)), - Some(Led(31.5, 37.0, 0)), - None, - Some(Led(16.0, 38.0, 0)), - Some(Led(17.0, 38.0, 0)), - Some(Led(18.0, 38.0, 0)), - Some(Led(19.0, 38.0, 0)), - Some(Led(20.0, 38.0, 0)), - Some(Led(21.0, 38.0, 0)), - Some(Led(22.0, 38.0, 0)), - Some(Led(23.0, 38.0, 0)), - Some(Led(24.0, 38.0, 0)), - Some(Led(25.0, 38.0, 0)), - Some(Led(26.0, 38.0, 0)), - Some(Led(27.0, 38.0, 0)), - Some(Led(28.0, 38.0, 0)), - Some(Led(29.0, 38.0, 0)), - Some(Led(30.0, 38.0, 0)), - Some(Led(31.0, 38.0, 0)), - Some(Led(32.0, 38.0, 0)), - Some(Led(16.5, 39.0, 0)), - Some(Led(17.5, 39.0, 0)), - Some(Led(18.5, 39.0, 0)), - Some(Led(19.5, 39.0, 0)), - Some(Led(20.5, 39.0, 0)), - Some(Led(21.5, 39.0, 0)), - Some(Led(22.5, 39.0, 0)), - Some(Led(23.5, 39.0, 0)), - Some(Led(24.5, 39.0, 0)), - Some(Led(25.5, 39.0, 0)), - Some(Led(26.5, 39.0, 0)), - Some(Led(27.5, 39.0, 0)), - Some(Led(28.5, 39.0, 0)), - Some(Led(29.5, 39.0, 0)), - Some(Led(30.5, 39.0, 0)), - Some(Led(31.5, 39.0, 0)), - None, - Some(Led(17.0, 40.0, 0)), - Some(Led(18.0, 40.0, 0)), - Some(Led(19.0, 40.0, 0)), - Some(Led(20.0, 40.0, 0)), - Some(Led(21.0, 40.0, 0)), - Some(Led(22.0, 40.0, 0)), - Some(Led(23.0, 40.0, 0)), - Some(Led(24.0, 40.0, 0)), - Some(Led(25.0, 40.0, 0)), - Some(Led(26.0, 40.0, 0)), - Some(Led(27.0, 40.0, 0)), - Some(Led(28.0, 40.0, 0)), - Some(Led(29.0, 40.0, 0)), - Some(Led(30.0, 40.0, 0)), - Some(Led(31.0, 40.0, 0)), - Some(Led(32.0, 40.0, 0)), - Some(Led(17.5, 41.0, 0)), - Some(Led(18.5, 41.0, 0)), - Some(Led(19.5, 41.0, 0)), - Some(Led(20.5, 41.0, 0)), - Some(Led(21.5, 41.0, 0)), - Some(Led(22.5, 41.0, 0)), - Some(Led(23.5, 41.0, 0)), - Some(Led(24.5, 41.0, 0)), - Some(Led(25.5, 41.0, 0)), - Some(Led(26.5, 41.0, 0)), - Some(Led(27.5, 41.0, 0)), - Some(Led(28.5, 41.0, 0)), - Some(Led(29.5, 41.0, 0)), - Some(Led(30.5, 41.0, 0)), - Some(Led(31.5, 41.0, 0)), - None, - Some(Led(18.0, 42.0, 0)), - Some(Led(19.0, 42.0, 0)), - Some(Led(20.0, 42.0, 0)), - Some(Led(21.0, 42.0, 0)), - Some(Led(22.0, 42.0, 0)), - Some(Led(23.0, 42.0, 0)), - Some(Led(24.0, 42.0, 0)), - Some(Led(25.0, 42.0, 0)), - Some(Led(26.0, 42.0, 0)), - Some(Led(27.0, 42.0, 0)), - Some(Led(28.0, 42.0, 0)), - Some(Led(29.0, 42.0, 0)), - Some(Led(30.0, 42.0, 0)), - Some(Led(31.0, 42.0, 0)), - Some(Led(32.0, 42.0, 0)), - Some(Led(18.5, 43.0, 0)), - Some(Led(19.5, 43.0, 0)), - Some(Led(20.5, 43.0, 0)), - Some(Led(21.5, 43.0, 0)), - Some(Led(22.5, 43.0, 0)), - Some(Led(23.5, 43.0, 0)), - Some(Led(24.5, 43.0, 0)), - Some(Led(25.5, 43.0, 0)), - Some(Led(26.5, 43.0, 0)), - Some(Led(27.5, 43.0, 0)), - Some(Led(28.5, 43.0, 0)), - Some(Led(29.5, 43.0, 0)), - Some(Led(30.5, 43.0, 0)), - Some(Led(31.5, 43.0, 0)), - None, - Some(Led(19.0, 44.0, 0)), - Some(Led(20.0, 44.0, 0)), - Some(Led(21.0, 44.0, 0)), - Some(Led(22.0, 44.0, 0)), - Some(Led(23.0, 44.0, 0)), - Some(Led(24.0, 44.0, 0)), - Some(Led(25.0, 44.0, 0)), - Some(Led(26.0, 44.0, 0)), - Some(Led(27.0, 44.0, 0)), - Some(Led(28.0, 44.0, 0)), - Some(Led(29.0, 44.0, 0)), - Some(Led(30.0, 44.0, 0)), - Some(Led(31.0, 44.0, 0)), - Some(Led(32.0, 44.0, 0)), - Some(Led(19.5, 45.0, 0)), - Some(Led(20.5, 45.0, 0)), - Some(Led(21.5, 45.0, 0)), - Some(Led(22.5, 45.0, 0)), - Some(Led(23.5, 45.0, 0)), - Some(Led(24.5, 45.0, 0)), - Some(Led(25.5, 45.0, 0)), - Some(Led(26.5, 45.0, 0)), - Some(Led(27.5, 45.0, 0)), - Some(Led(28.5, 45.0, 0)), - Some(Led(29.5, 45.0, 0)), - Some(Led(30.5, 45.0, 0)), - Some(Led(31.5, 45.0, 0)), - None, - Some(Led(20.0, 46.0, 0)), - Some(Led(21.0, 46.0, 0)), - Some(Led(22.0, 46.0, 0)), - Some(Led(23.0, 46.0, 0)), - Some(Led(24.0, 46.0, 0)), - Some(Led(25.0, 46.0, 0)), - Some(Led(26.0, 46.0, 0)), - Some(Led(27.0, 46.0, 0)), - Some(Led(28.0, 46.0, 0)), - Some(Led(29.0, 46.0, 0)), - Some(Led(30.0, 46.0, 0)), - Some(Led(31.0, 46.0, 0)), - Some(Led(32.0, 46.0, 0)), - Some(Led(20.5, 47.0, 0)), - Some(Led(21.5, 47.0, 0)), - Some(Led(22.5, 47.0, 0)), - Some(Led(23.5, 47.0, 0)), - Some(Led(24.5, 47.0, 0)), - Some(Led(25.5, 47.0, 0)), - Some(Led(26.5, 47.0, 0)), - Some(Led(27.5, 47.0, 0)), - Some(Led(28.5, 47.0, 0)), - Some(Led(29.5, 47.0, 0)), - Some(Led(30.5, 47.0, 0)), - Some(Led(31.5, 47.0, 0)), - None, - Some(Led(21.0, 48.0, 0)), - Some(Led(22.0, 48.0, 0)), - Some(Led(23.0, 48.0, 0)), - Some(Led(24.0, 48.0, 0)), - Some(Led(25.0, 48.0, 0)), - Some(Led(26.0, 48.0, 0)), - Some(Led(27.0, 48.0, 0)), - Some(Led(28.0, 48.0, 0)), - Some(Led(29.0, 48.0, 0)), - Some(Led(30.0, 48.0, 0)), - Some(Led(31.0, 48.0, 0)), - Some(Led(32.0, 48.0, 0)), - Some(Led(21.5, 49.0, 0)), - Some(Led(22.5, 49.0, 0)), - Some(Led(23.5, 49.0, 0)), - Some(Led(24.5, 49.0, 0)), - Some(Led(25.5, 49.0, 0)), - Some(Led(26.5, 49.0, 0)), - Some(Led(27.5, 49.0, 0)), - Some(Led(28.5, 49.0, 0)), - Some(Led(29.5, 49.0, 0)), - Some(Led(30.5, 49.0, 0)), - Some(Led(31.5, 49.0, 0)), - None, - Some(Led(22.0, 50.0, 0)), - Some(Led(23.0, 50.0, 0)), - Some(Led(24.0, 50.0, 0)), - Some(Led(25.0, 50.0, 0)), - Some(Led(26.0, 50.0, 0)), - Some(Led(27.0, 50.0, 0)), - Some(Led(28.0, 50.0, 0)), - Some(Led(29.0, 50.0, 0)), - Some(Led(30.0, 50.0, 0)), - Some(Led(31.0, 50.0, 0)), - Some(Led(32.0, 50.0, 0)), - Some(Led(22.5, 51.0, 0)), - Some(Led(23.5, 51.0, 0)), - Some(Led(24.5, 51.0, 0)), - Some(Led(25.5, 51.0, 0)), - Some(Led(26.5, 51.0, 0)), - Some(Led(27.5, 51.0, 0)), - Some(Led(28.5, 51.0, 0)), - Some(Led(29.5, 51.0, 0)), - Some(Led(30.5, 51.0, 0)), - Some(Led(31.5, 51.0, 0)), - None, - Some(Led(23.0, 52.0, 0)), - Some(Led(24.0, 52.0, 0)), - Some(Led(25.0, 52.0, 0)), - Some(Led(26.0, 52.0, 0)), - Some(Led(27.0, 52.0, 0)), - Some(Led(28.0, 52.0, 0)), - Some(Led(29.0, 52.0, 0)), - Some(Led(30.0, 52.0, 0)), - Some(Led(31.0, 52.0, 0)), - Some(Led(32.0, 52.0, 0)), - Some(Led(23.5, 53.0, 0)), - Some(Led(24.5, 53.0, 0)), - Some(Led(25.5, 53.0, 0)), - Some(Led(26.5, 53.0, 0)), - Some(Led(27.5, 53.0, 0)), - Some(Led(28.5, 53.0, 0)), - Some(Led(29.5, 53.0, 0)), - Some(Led(30.5, 53.0, 0)), - Some(Led(31.5, 53.0, 0)), - None, - Some(Led(24.0, 54.0, 0)), - Some(Led(25.0, 54.0, 0)), - Some(Led(26.0, 54.0, 0)), - Some(Led(27.0, 54.0, 0)), - Some(Led(28.0, 54.0, 0)), - Some(Led(29.0, 54.0, 0)), - Some(Led(30.0, 54.0, 0)), - Some(Led(31.0, 54.0, 0)), - Some(Led(32.0, 54.0, 0)), -]; - #[cfg(test)] mod tests { - use crate::image::*; + use std::path::PathBuf; + + use crate::{image::*, AnimePacketType, AnimeGif, AnimTime}; #[test] fn led_positions() { - let leds = AnimeImage::generate(); + let leds = AnimeImage::generate_image_positioning(AnimeType::GA401); assert_eq!(leds[0], Some(Led(0.0, 0.0, 0))); assert_eq!(leds[1], Some(Led(1.0, 0.0, 0))); assert_eq!(leds[2], Some(Led(2.0, 0.0, 0))); @@ -1645,60 +534,216 @@ mod tests { assert_eq!(leds[673], Some(Led(31.5, 21.0, 0))); // end } - #[test] - fn led_positions_const() { - let leds = AnimeImage::generate(); - assert_eq!(leds[1], LED_IMAGE_POSITIONS[1]); - assert_eq!(leds[34], LED_IMAGE_POSITIONS[34]); - assert_eq!(leds[69], LED_IMAGE_POSITIONS[69]); - assert_eq!(leds[137], LED_IMAGE_POSITIONS[137]); - assert_eq!(leds[169], LED_IMAGE_POSITIONS[169]); - assert_eq!(leds[170], LED_IMAGE_POSITIONS[170]); - assert_eq!(leds[236], LED_IMAGE_POSITIONS[236]); - assert_eq!(leds[649], LED_IMAGE_POSITIONS[649]); - assert_eq!(leds[674], LED_IMAGE_POSITIONS[674]); - } + // #[test] + // fn led_positions_const() { + // let leds = AnimeImage::generate(); + // assert_eq!(leds[1], LED_IMAGE_POSITIONS[1]); + // assert_eq!(leds[34], LED_IMAGE_POSITIONS[34]); + // assert_eq!(leds[69], LED_IMAGE_POSITIONS[69]); + // assert_eq!(leds[137], LED_IMAGE_POSITIONS[137]); + // assert_eq!(leds[169], LED_IMAGE_POSITIONS[169]); + // assert_eq!(leds[170], LED_IMAGE_POSITIONS[170]); + // assert_eq!(leds[236], LED_IMAGE_POSITIONS[236]); + // assert_eq!(leds[649], LED_IMAGE_POSITIONS[649]); + // assert_eq!(leds[674], LED_IMAGE_POSITIONS[674]); + // } #[test] fn row_starts() { - assert_eq!(AnimeImage::first_x(5), 0); - assert_eq!(AnimeImage::first_x(6), 0); - assert_eq!(AnimeImage::first_x(7), 1); - assert_eq!(AnimeImage::first_x(8), 1); - assert_eq!(AnimeImage::first_x(9), 2); - assert_eq!(AnimeImage::first_x(10), 2); - assert_eq!(AnimeImage::first_x(11), 3); + let a = AnimeType::GA401; + assert_eq!(AnimeImage::first_x(a, 5), 0); + assert_eq!(AnimeImage::first_x(a, 6), 0); + assert_eq!(AnimeImage::first_x(a, 7), 1); + assert_eq!(AnimeImage::first_x(a, 8), 1); + assert_eq!(AnimeImage::first_x(a, 9), 2); + assert_eq!(AnimeImage::first_x(a, 10), 2); + assert_eq!(AnimeImage::first_x(a, 11), 3); } #[test] fn row_widths() { - assert_eq!(AnimeImage::width(5), 33); - assert_eq!(AnimeImage::width(6), 33); - assert_eq!(AnimeImage::width(7), 32); - assert_eq!(AnimeImage::width(8), 32); - assert_eq!(AnimeImage::width(9), 31); - assert_eq!(AnimeImage::width(10), 31); - assert_eq!(AnimeImage::width(11), 30); - assert_eq!(AnimeImage::width(12), 30); - assert_eq!(AnimeImage::width(13), 29); - assert_eq!(AnimeImage::width(14), 29); - assert_eq!(AnimeImage::width(15), 28); - assert_eq!(AnimeImage::width(16), 28); - assert_eq!(AnimeImage::width(17), 27); - assert_eq!(AnimeImage::width(18), 27); + let a = AnimeType::GA401; + assert_eq!(AnimeImage::width(a, 5), 33); + assert_eq!(AnimeImage::width(a, 6), 33); + assert_eq!(AnimeImage::width(a, 7), 32); + assert_eq!(AnimeImage::width(a, 8), 32); + assert_eq!(AnimeImage::width(a, 9), 31); + assert_eq!(AnimeImage::width(a, 10), 31); + assert_eq!(AnimeImage::width(a, 11), 30); + assert_eq!(AnimeImage::width(a, 12), 30); + assert_eq!(AnimeImage::width(a, 13), 29); + assert_eq!(AnimeImage::width(a, 14), 29); + assert_eq!(AnimeImage::width(a, 15), 28); + assert_eq!(AnimeImage::width(a, 16), 28); + assert_eq!(AnimeImage::width(a, 17), 27); + assert_eq!(AnimeImage::width(a, 18), 27); } #[test] fn row_pitch() { - assert_eq!(AnimeImage::pitch(5), 34); - assert_eq!(AnimeImage::pitch(6), 33); - assert_eq!(AnimeImage::pitch(7), 33); - assert_eq!(AnimeImage::pitch(8), 32); - assert_eq!(AnimeImage::pitch(9), 32); - assert_eq!(AnimeImage::pitch(10), 31); - assert_eq!(AnimeImage::pitch(11), 31); - assert_eq!(AnimeImage::pitch(12), 30); - assert_eq!(AnimeImage::pitch(13), 30); - assert_eq!(AnimeImage::pitch(14), 29); + let a = AnimeType::GA401; + assert_eq!(AnimeImage::pitch(a, 5), 34); + assert_eq!(AnimeImage::pitch(a, 6), 33); + assert_eq!(AnimeImage::pitch(a, 7), 33); + assert_eq!(AnimeImage::pitch(a, 8), 32); + assert_eq!(AnimeImage::pitch(a, 9), 32); + assert_eq!(AnimeImage::pitch(a, 10), 31); + assert_eq!(AnimeImage::pitch(a, 11), 31); + assert_eq!(AnimeImage::pitch(a, 12), 30); + assert_eq!(AnimeImage::pitch(a, 13), 30); + assert_eq!(AnimeImage::pitch(a, 14), 29); + } + + #[test] + fn ga402_image_edge_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x2, 0x1, 0x0, 0x73, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x2, 0x74, 0x2, 0x73, 0x2, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + let pkt2_check = [ + 0x5e, 0xc0, 0x2, 0xe7, 0x4, 0x73, 0x2, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut matrix = AnimeImage::new( + Vec2::new(1.0, 1.0), + 0.0, + Vec2::default(), + 0.0, + vec![Pixel::default(); 1000], + 100, + AnimeType::GA402, + ); + matrix.edge_outline(); + let data = AnimeDataBuffer::from(&matrix); + let pkt = AnimePacketType::from(data); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + assert_eq!(pkt[2], pkt2_check); + } + + #[test] + #[ignore = "Just to inspect image packet"] + fn ga402_image_packet_check() { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("data/anime/custom/sonic-run.gif"); + + let matrix = AnimeGif::from_gif(&path, 1.0, 0.0, Vec2::default(), AnimTime::Infinite, 1.0, AnimeType::GA402).unwrap(); + matrix.frames()[0].frame(); + let _pkt = AnimePacketType::from(matrix.frames()[0].frame().clone()); } } diff --git a/rog-anime/src/sequencer.rs b/rog-anime/src/sequencer.rs index 5db29882..fa30b3ae 100644 --- a/rog-anime/src/sequencer.rs +++ b/rog-anime/src/sequencer.rs @@ -3,7 +3,9 @@ use std::{path::PathBuf, time::Duration}; use glam::Vec2; use serde_derive::{Deserialize, Serialize}; -use crate::{error::AnimeError, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage}; +use crate::{ + error::AnimeError, AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, AnimeType, +}; /// All the possible AniMe actions that can be used. This enum is intended to be /// a helper for loading up `ActionData`. @@ -63,24 +65,37 @@ pub enum ActionData { } impl ActionData { - pub fn from_anime_action(action: &ActionLoader) -> Result { + pub fn from_anime_action( + anime_type: AnimeType, + action: &ActionLoader, + ) -> Result { let a = match action { ActionLoader::AsusAnimation { file, time, brightness, - } => ActionData::Animation(AnimeGif::from_diagonal_gif(file, *time, *brightness)?), + } => ActionData::Animation(AnimeGif::from_diagonal_gif( + file, + *time, + *brightness, + anime_type, + )?), ActionLoader::AsusImage { file, time, brightness, } => match time { AnimTime::Infinite => { - let image = AnimeDiagonal::from_png(file, None, *brightness)?; - let data = ::from(&image); + let image = AnimeDiagonal::from_png(file, None, *brightness, anime_type)?; + let data = image.into_data_buffer(anime_type); ActionData::Image(Box::new(data)) } - _ => ActionData::Animation(AnimeGif::from_diagonal_png(file, *time, *brightness)?), + _ => ActionData::Animation(AnimeGif::from_diagonal_png( + file, + anime_type, + *time, + *brightness, + )?), }, ActionLoader::ImageAnimation { file, @@ -99,6 +114,7 @@ impl ActionData { *translation, *time, *brightness, + anime_type, )?)); } } @@ -109,6 +125,7 @@ impl ActionData { *translation, *time, *brightness, + anime_type, )?) } ActionLoader::Image { @@ -122,8 +139,14 @@ impl ActionData { match time { AnimTime::Infinite => { // If no time then create a plain static image - let image = - AnimeImage::from_png(file, *scale, *angle, *translation, *brightness)?; + let image = AnimeImage::from_png( + file, + *scale, + *angle, + *translation, + *brightness, + anime_type, + )?; let data = ::from(&image); ActionData::Image(Box::new(data)) } @@ -134,6 +157,7 @@ impl ActionData { *translation, *time, *brightness, + anime_type, )?), } } @@ -144,20 +168,21 @@ impl ActionData { } /// An optimised precomputed set of actions that the user can cycle through -#[derive(Debug, Deserialize, Serialize, Default)] -pub struct Sequences(Vec); +#[derive(Debug, Deserialize, Serialize)] +pub struct Sequences(Vec, AnimeType); impl Sequences { #[inline] - pub fn new() -> Self { - Self(Vec::new()) + pub fn new(anime_type: AnimeType) -> Self { + Self(Vec::new(), anime_type) } /// Use a base `AnimeAction` to generate the precomputed data and insert in to /// the run buffer #[inline] pub fn insert(&mut self, index: usize, action: &ActionLoader) -> Result<(), AnimeError> { - self.0.insert(index, ActionData::from_anime_action(action)?); + self.0 + .insert(index, ActionData::from_anime_action(self.1, action)?); Ok(()) } diff --git a/rog-anime/src/usb.rs b/rog-anime/src/usb.rs index 622b160a..c6507ec2 100644 --- a/rog-anime/src/usb.rs +++ b/rog-anime/src/usb.rs @@ -7,6 +7,8 @@ //! //! Step 1 need to applied only on fresh system boot. +use crate::{error::AnimeError, AnimeType}; + const INIT_STR: [u8; 15] = [ 0x5e, b'A', b'S', b'U', b'S', b' ', b'T', b'e', b'c', b'h', b'.', b'I', b'n', b'c', b'.', ]; @@ -15,6 +17,47 @@ const DEV_PAGE: u8 = 0x5e; pub const VENDOR_ID: u16 = 0x0b05; pub const PROD_ID: u16 = 0x193b; +/// `get_anime_type` is very broad, matching on part of the laptop board name only. For this +/// reason `find_node()` must be used also to verify if the USB device is available. +/// +/// The currently known USB device is `19b6`. +#[inline] +pub fn get_anime_type() -> Result { + let dmi = sysfs_class::DmiId::default(); + let board_name = dmi.board_name()?; + + if board_name.contains("GA401Q") { + return Ok(AnimeType::GA401); + } else if board_name.contains("GA402R") { + return Ok(AnimeType::GA402); + } + Err(AnimeError::UnsupportedDevice) +} + +/// Find the USB device node - known devices so far: `19b6` +#[inline] +pub fn find_node(id_product: &str) -> Result { + let mut enumerator = + udev::Enumerator::new().map_err(|err| AnimeError::Udev("enumerator failed".into(), err))?; + enumerator + .match_subsystem("usb") + .map_err(|err| AnimeError::Udev("match_subsystem failed".into(), err))?; + + for device in enumerator + .scan_devices() + .map_err(|err| AnimeError::Udev("scan_devices failed".into(), err))? + { + if let Some(attr) = device.attribute_value("idProduct") { + if attr == id_product { + if let Some(dev_node) = device.devnode() { + return Ok(dev_node.to_string_lossy().to_string()); + } + } + } + } + Err(AnimeError::NoDevice) +} + /// Get the two device initialization packets. These are required for device start /// after the laptop boots. #[inline] diff --git a/rog-anime/test/ga401-diagonal.gif b/rog-anime/test/ga401-diagonal.gif new file mode 100644 index 00000000..79091dc7 Binary files /dev/null and b/rog-anime/test/ga401-diagonal.gif differ diff --git a/rog-anime/test/ga401-diagonal.png b/rog-anime/test/ga401-diagonal.png new file mode 100644 index 00000000..c0d562cd Binary files /dev/null and b/rog-anime/test/ga401-diagonal.png differ diff --git a/rog-anime/test/ga402-diagonal-fullbright.png b/rog-anime/test/ga402-diagonal-fullbright.png new file mode 100644 index 00000000..2a3c0af8 Binary files /dev/null and b/rog-anime/test/ga402-diagonal-fullbright.png differ diff --git a/rog-anime/test/ga402-diagonal.gif b/rog-anime/test/ga402-diagonal.gif new file mode 100644 index 00000000..7e793741 Binary files /dev/null and b/rog-anime/test/ga402-diagonal.gif differ diff --git a/rog-anime/test/ga402-diagonal.png b/rog-anime/test/ga402-diagonal.png new file mode 100644 index 00000000..5e4e90d2 Binary files /dev/null and b/rog-anime/test/ga402-diagonal.png differ diff --git a/asusctl/examples/aura-rgb-ball.rs b/tmp-aura-examples/aura-rgb-ball.rs similarity index 96% rename from asusctl/examples/aura-rgb-ball.rs rename to tmp-aura-examples/aura-rgb-ball.rs index d7c21235..883c3ee7 100644 --- a/asusctl/examples/aura-rgb-ball.rs +++ b/tmp-aura-examples/aura-rgb-ball.rs @@ -1,5 +1,5 @@ use rog_aura::{GX502Layout, Key, KeyColourArray, KeyLayout}; -use rog_dbus::RogDbusClient; +use rog_dbus::RogDbusClientBlocking; use std::collections::LinkedList; #[derive(Debug, Clone)] @@ -52,7 +52,7 @@ impl Ball { } fn main() -> Result<(), Box> { - let (dbus, _) = RogDbusClient::new()?; + let (dbus, _) = RogDbusClientBlocking::new()?; let mut colours = KeyColourArray::new(); @@ -60,8 +60,6 @@ fn main() -> Result<(), Box> { let mut balls = [Ball::new(2, 1, 12), Ball::new(4, 6, 12)]; - dbus.proxies().led().init_effect()?; - let rows = layout.get_rows(); loop { for (n, ball) in balls.iter_mut().enumerate() { diff --git a/asusctl/examples/aura-rgb-comet.rs b/tmp-aura-examples/aura-rgb-comet.rs similarity index 100% rename from asusctl/examples/aura-rgb-comet.rs rename to tmp-aura-examples/aura-rgb-comet.rs diff --git a/asusctl/examples/aura-rgb-iterate-keys.rs b/tmp-aura-examples/aura-rgb-iterate-keys.rs similarity index 100% rename from asusctl/examples/aura-rgb-iterate-keys.rs rename to tmp-aura-examples/aura-rgb-iterate-keys.rs diff --git a/asusctl/examples/aura-rgb-per-key-effect-2.rs b/tmp-aura-examples/aura-rgb-per-key-effect-2.rs similarity index 100% rename from asusctl/examples/aura-rgb-per-key-effect-2.rs rename to tmp-aura-examples/aura-rgb-per-key-effect-2.rs diff --git a/asusctl/examples/aura-rgb-pulser.rs b/tmp-aura-examples/aura-rgb-pulser.rs similarity index 100% rename from asusctl/examples/aura-rgb-pulser.rs rename to tmp-aura-examples/aura-rgb-pulser.rs