diff --git a/.gitignore b/.gitignore index e5209aae..65253858 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ desktop-extensions/gnome*/@types/gir-generated desktop-extensions/gnome*/node_modules desktop-extensions/gnome*/schemas/gschemas.compiled desktop-extensions/gnome*/*.zip + +# agents and reference +CLAUDE.md +AGENTS.md +/reference diff --git a/asusctl/examples/anime-led-scan.rs b/asusctl/examples/anime-led-scan.rs new file mode 100644 index 00000000..c4ff9b94 --- /dev/null +++ b/asusctl/examples/anime-led-scan.rs @@ -0,0 +1,547 @@ +//! LED scanning tool for discovering AniMe Matrix buffer-to-LED mappings. +//! +//! This tool lights up one buffer index at a time, allowing you to observe +//! which physical LED corresponds to each buffer position. This is essential +//! for mapping new device types like G835L where the exact layout is unknown. +//! +//! You might want to use it slowly, as it sometimes doesn't work properly. +//! Maybe there's better ways to make this reliable but for now it works for my use case. +//! +//! # Usage +//! ``` +//! cargo run --example anime-led-scan -- [options] +//! ``` +//! +//! # Controls +//! - `n` or `Enter`: Next index +//! - `p` or `Backspace`: Previous index +//! - `j` followed by number: Jump to specific index +//! - `+` / `-`: Adjust step size (default 1) +//! - `s`: Save current index to notes file +//! - `r`: Mark current index as row start +//! - `q` or `Ctrl+C`: Quit +//! +//! # Output +//! Creates a `led-scan-notes.txt` file with recorded observations. + +use std::env; +use std::fs::OpenOptions; +use std::io::{self, BufRead, Write}; + +use rog_anime::usb::{get_anime_type, Brightness}; +use rog_anime::{AnimeDataBuffer, AnimeType}; +use rog_dbus::zbus_anime::AnimeProxyBlocking; +use zbus::blocking::Connection; + +/// Saved device state for restoration on exit +struct SavedState { + builtins_enabled: bool, + brightness: Brightness, + display_enabled: bool, +} + +fn print_help(scan_len: usize, buffer_len: usize) { + println!("\n=== LED Scan Tool ==="); + println!( + "Scan range: 0-{} (buffer size: {})", + scan_len - 1, + buffer_len + ); + println!("Commands:"); + println!(" n, Enter - Next index"); + println!(" p, Backspace - Previous index"); + println!(" j - Jump to index"); + println!(" + / - - Increase/decrease step size"); + println!(" s - Save note for current index"); + println!(" r - Mark as row start"); + println!(" a - Auto-scan (runs through all indices)"); + println!(" f - Fill all buffer bytes"); + println!(" f - Fill range (inclusive)"); + println!(" p1/p2/p3 - Fill pane 1/2/3 only (each is 627 bytes)"); + println!(" hold - Hold current LED (press Enter to release)"); + println!(" hold - Hold range (press Enter to release)"); + println!(" c - Clear display"); + println!(" row - Step through rows (G835L, provisional)"); + println!(" row - Show specific row (G835L, provisional)"); + println!(" allrows - Light all rows sequentially (G835L)"); + println!(" rowmap - Print the full row mapping (G835L)"); + println!(" h - Show this help"); + println!(" q - Quit and restore state"); + println!(); +} + +fn save_note(index: usize, note: &str) -> io::Result<()> { + let mut file = OpenOptions::new() + .create(true) + .append(true) + .open("led-scan-notes.txt")?; + writeln!(file, "Index {}: {}", index, note)?; + Ok(()) +} + +fn write_single_led( + proxy: &AnimeProxyBlocking, + anime_type: AnimeType, + index: usize, + brightness: u8, +) { + let mut buffer = AnimeDataBuffer::new(anime_type); + let data = buffer.data_mut(); + if index < data.len() { + data[index] = brightness; + } + if let Err(e) = proxy.write(buffer) { + eprintln!("Error writing to device: {}", e); + } +} + +fn clear_display(proxy: &AnimeProxyBlocking, anime_type: AnimeType) { + let buffer = AnimeDataBuffer::new(anime_type); + let _ = proxy.write(buffer); +} + +fn fill_display(proxy: &AnimeProxyBlocking, anime_type: AnimeType, brightness: u8) { + let mut buffer = AnimeDataBuffer::new(anime_type); + let data = buffer.data_mut(); + for byte in data.iter_mut() { + *byte = brightness; + } + if let Err(e) = proxy.write(buffer) { + eprintln!("Error writing to device: {}", e); + } +} + +/// Fill a range of LEDs. Both start and end are INCLUSIVE. +fn fill_range( + proxy: &AnimeProxyBlocking, + anime_type: AnimeType, + start: usize, + end: usize, + brightness: u8, +) { + let mut buffer = AnimeDataBuffer::new(anime_type); + let data = buffer.data_mut(); + for i in start..=end.min(data.len().saturating_sub(1)) { + data[i] = brightness; + } + if let Err(e) = proxy.write(buffer) { + eprintln!("Error writing to device: {}", e); + } +} + +fn fill_pane(proxy: &AnimeProxyBlocking, anime_type: AnimeType, pane: usize, brightness: u8) { + const PANE_LEN: usize = 627; + let start = pane * PANE_LEN; + let end = start + PANE_LEN - 1; + fill_range(proxy, anime_type, start, end, brightness); +} + +/// G835L row pattern (PROVISIONAL - needs hardware verification): +/// - Rows 0-1: 1 LED each +/// - Rows 2-3: 2 LEDs each +/// - ... (pairs of rows with same length) +/// - Rows 26-27: 14 LEDs each +/// - Rows 28+: 15 LEDs each (constant) +/// +/// Returns (start_index, end_index_inclusive, row_length) +fn g835l_row_bounds(row: usize) -> (usize, usize, usize) { + let triangle_rows = 28; + let triangle_leds = 210; + + if row < triangle_rows { + let length = row / 2 + 1; + let mut start = 0usize; + for r in 0..row { + start += r / 2 + 1; + } + (start, start + length - 1, length) + } else { + let rows_after_triangle = row - triangle_rows; + let start = triangle_leds + rows_after_triangle * 15; + (start, start + 14, 15) + } +} + +fn g835l_total_rows() -> usize { + 28 + 40 +} + +fn save_state(proxy: &AnimeProxyBlocking) -> SavedState { + SavedState { + builtins_enabled: proxy.builtins_enabled().unwrap_or(false), + brightness: proxy.brightness().unwrap_or(Brightness::Med), + display_enabled: proxy.enable_display().unwrap_or(true), + } +} + +fn restore_state(proxy: &AnimeProxyBlocking, state: &SavedState) { + let _ = proxy.set_builtins_enabled(state.builtins_enabled); + let _ = proxy.set_brightness(state.brightness); + let _ = proxy.set_enable_display(state.display_enabled); + let _ = proxy.run_main_loop(true); +} + +fn main() { + let args: Vec = env::args().collect(); + + let mut start_index = 0usize; + let mut brightness = 200u8; + let mut scan_limit: Option = None; + + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--start" | "-s" => { + if i + 1 < args.len() { + start_index = args[i + 1].parse().unwrap_or(0); + i += 1; + } + } + "--brightness" | "-b" => { + if i + 1 < args.len() { + brightness = args[i + 1].parse().unwrap_or(200); + i += 1; + } + } + "--limit" | "-l" => { + if i + 1 < args.len() { + scan_limit = args[i + 1].parse().ok(); + i += 1; + } + } + "--help" | "-h" => { + println!("LED Scan Tool for AniMe Matrix"); + println!(); + println!("Usage: anime-led-scan [options]"); + println!(); + println!("Options:"); + println!(" -s, --start Start at index N (default: 0)"); + println!(" -b, --brightness LED brightness 0-255 (default: 200)"); + println!(" -l, --limit Cap scan range to N indices (e.g. 810 for G835L)"); + println!(" -h, --help Show this help"); + return; + } + _ => {} + } + i += 1; + } + + let conn = match Connection::system() { + Ok(c) => c, + Err(e) => { + eprintln!("Failed to connect to D-Bus: {}", e); + eprintln!("Make sure asusd is running."); + return; + } + }; + + let proxy = match AnimeProxyBlocking::new(&conn) { + Ok(p) => p, + Err(e) => { + eprintln!("Failed to create Anime proxy: {}", e); + eprintln!("Make sure asusd supports your device."); + return; + } + }; + + let anime_type = get_anime_type(); + let buffer_len = anime_type.data_length(); + let scan_len = scan_limit.unwrap_or(buffer_len).min(buffer_len); + + println!("=== LED Scan Tool ==="); + println!("Device type: {:?}", anime_type); + println!("Buffer length: {} bytes", buffer_len); + println!("Scan range: 0-{}", scan_len - 1); + println!("Brightness: {}", brightness); + println!(); + + // Save current state for restoration + let saved_state = save_state(&proxy); + println!("Saved device state for restoration on exit."); + + // Stop system animations + if let Err(e) = proxy.run_main_loop(false) { + eprintln!("Warning: Could not stop main loop: {}", e); + } + println!("Stopped system animations."); + + print_help(scan_len, buffer_len); + + let mut current_index = start_index.min(scan_len - 1); + let mut step = 1usize; + + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + + let stdin = io::stdin(); + let mut input = String::new(); + + loop { + input.clear(); + print!("> "); + io::stdout().flush().unwrap(); + + if stdin.lock().read_line(&mut input).is_err() { + break; + } + + let cmd = input.trim(); + + match cmd { + "q" | "quit" | "exit" => { + clear_display(&proxy, anime_type); + restore_state(&proxy, &saved_state); + println!("Restored device state. Goodbye!"); + break; + } + "n" | "" => { + current_index = (current_index + step).min(scan_len - 1); + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + } + "p" => { + current_index = current_index.saturating_sub(step); + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + } + "+" => { + step = step.saturating_mul(2).max(1); + println!("Step size: {}", step); + } + "-" => { + step = step.saturating_div(2).max(1); + println!("Step size: {}", step); + } + "r" => { + if let Err(e) = save_note(current_index, "ROW START") { + eprintln!("Error saving note: {}", e); + } else { + println!("Saved: Index {} marked as ROW START", current_index); + } + } + "h" | "help" | "?" => { + print_help(scan_len, buffer_len); + } + cmd if cmd.starts_with('j') => { + let num_str = cmd.trim_start_matches('j').trim(); + if let Ok(idx) = num_str.parse::() { + if idx < scan_len { + current_index = idx; + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + } else { + println!("Index {} out of range (max: {})", idx, scan_len - 1); + } + } else { + println!("Usage: j "); + } + } + cmd if cmd.starts_with('s') && !cmd.starts_with("show") => { + let note = cmd.trim_start_matches('s').trim(); + let note = if note.is_empty() { "observed" } else { note }; + if let Err(e) = save_note(current_index, note) { + eprintln!("Error saving note: {}", e); + } else { + println!("Saved note for index {}", current_index); + } + } + "a" => { + println!("Auto-scan mode (0 to {})...", scan_len - 1); + let delay = std::time::Duration::from_millis(10); + for idx in current_index..scan_len { + write_single_led(&proxy, anime_type, idx, brightness); + print!("\rIndex: {} / {} ", idx, scan_len - 1); + io::stdout().flush().unwrap(); + std::thread::sleep(delay); + current_index = idx; + } + println!(); + println!("Auto-scan complete. Current index: {}", current_index); + } + "c" => { + clear_display(&proxy, anime_type); + println!("Display cleared"); + } + "f" => { + fill_display(&proxy, anime_type, brightness); + println!("All buffer bytes filled at brightness {}", brightness); + } + "p1" => { + fill_pane(&proxy, anime_type, 0, brightness); + println!("Pane 1 (indices 0-626) filled"); + } + "p2" => { + fill_pane(&proxy, anime_type, 1, brightness); + println!("Pane 2 (indices 627-1253) filled"); + } + "p3" => { + fill_pane(&proxy, anime_type, 2, brightness); + println!("Pane 3 (indices 1254-1880) filled"); + } + cmd if cmd.starts_with("f ") => { + let parts: Vec<&str> = cmd.split_whitespace().collect(); + if parts.len() == 3 { + if let (Ok(start), Ok(end)) = + (parts[1].parse::(), parts[2].parse::()) + { + fill_range(&proxy, anime_type, start, end, brightness); + println!("Filled indices {} to {}", start, end); + } else { + println!("Usage: f "); + } + } else { + println!("Usage: f "); + } + } + "show" => { + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + } + "row" => { + if anime_type != AnimeType::G835L { + println!("Warning: Row commands use G835L mapping (provisional). You can add to this code to support other types. `examples/anime-led-scan.rs[402:425]`"); + } + println!("Row stepping mode. Press Enter for next row, 'q' to quit."); + let total = g835l_total_rows(); + for row_num in 0..total { + let (start, end, len) = g835l_row_bounds(row_num); + if end >= scan_len { + println!("Row {} exceeds scan limit, stopping.", row_num); + break; + } + println!("Row {}: indices {}-{} ({} LEDs)", row_num, start, end, len); + fill_range(&proxy, anime_type, start, end, brightness); + input.clear(); + print!("(Enter=next, q=quit) > "); + io::stdout().flush().unwrap(); + if stdin.lock().read_line(&mut input).is_err() { + break; + } + if input.trim() == "q" { + break; + } + clear_display(&proxy, anime_type); + } + println!("Row stepping done."); + } + cmd if cmd.starts_with("row ") => { + if anime_type != AnimeType::G835L { + println!("Warning: Row commands use G835L mapping (provisional)."); + } + let row_str = cmd.trim_start_matches("row ").trim(); + if let Ok(row_num) = row_str.parse::() { + let total = g835l_total_rows(); + if row_num < total { + let (start, end, len) = g835l_row_bounds(row_num); + if end < scan_len { + println!("Row {}: indices {}-{} ({} LEDs)", row_num, start, end, len); + fill_range(&proxy, anime_type, start, end, brightness); + } else { + println!("Row {} exceeds scan limit", row_num); + } + } else { + println!("Row {} out of range (max: {})", row_num, total - 1); + } + } else { + println!("Usage: row "); + } + } + "allrows" => { + if anime_type != AnimeType::G835L { + println!("Warning: Row commands use G835L mapping (provisional)."); + } + println!("Lighting all rows sequentially (200ms each)..."); + let total = g835l_total_rows(); + let delay = std::time::Duration::from_millis(200); + for row_num in 0..total { + let (start, end, len) = g835l_row_bounds(row_num); + if end >= scan_len { + println!("\nRow {} exceeds scan limit, stopping.", row_num); + break; + } + print!( + "\rRow {}/{}: indices {}-{} ({} LEDs) ", + row_num, + total - 1, + start, + end, + len + ); + io::stdout().flush().unwrap(); + fill_range(&proxy, anime_type, start, end, brightness); + std::thread::sleep(delay); + clear_display(&proxy, anime_type); + } + println!("\nDone."); + } + "rowmap" => { + if anime_type != AnimeType::G835L { + println!("Warning: Row map is for G835L (provisional)."); + } + println!("G835L Row Map:"); + let total = g835l_total_rows(); + for row_num in 0..total { + let (start, end, len) = g835l_row_bounds(row_num); + let marker = if end >= scan_len { + " (exceeds limit)" + } else { + "" + }; + println!( + " Row {:2}: indices {:4}-{:4} ({:2} LEDs){}", + row_num, start, end, len, marker + ); + } + } + "hold" => { + // Single write, wait for Enter to release + println!("Holding index {}. Press Enter to release...", current_index); + write_single_led(&proxy, anime_type, current_index, brightness); + input.clear(); + let _ = stdin.lock().read_line(&mut input); + clear_display(&proxy, anime_type); + println!("Released."); + } + cmd if cmd.starts_with("hold ") => { + let arg = cmd.trim_start_matches("hold ").trim(); + let (start, end): (usize, usize) = match arg { + "p1" | "1" => (0, 626), + "p2" | "2" => (627, 1253), + _ => { + let parts: Vec<&str> = arg.split_whitespace().collect(); + if parts.len() == 2 { + if let (Ok(s), Ok(e)) = (parts[0].parse(), parts[1].parse()) { + (s, e) + } else { + println!("Usage: hold p1, hold p2, or hold "); + continue; + } + } else { + println!("Usage: hold p1, hold p2, or hold "); + continue; + } + } + }; + println!("Holding range {}-{}. Press Enter to release...", start, end); + fill_range(&proxy, anime_type, start, end, brightness); + input.clear(); + let _ = stdin.lock().read_line(&mut input); + clear_display(&proxy, anime_type); + println!("Released."); + } + _ => { + if let Ok(idx) = cmd.parse::() { + if idx < scan_len { + current_index = idx; + write_single_led(&proxy, anime_type, current_index, brightness); + println!(">>> Index: {} (step: {})", current_index, step); + } else { + println!("Index {} out of range (max: {})", idx, scan_len - 1); + } + } else { + println!("Unknown command: '{}'. Type 'h' for help.", cmd); + } + } + } + } +} diff --git a/asusctl/src/anime_cli.rs b/asusctl/src/anime_cli.rs index 57065b0b..ea1dfa68 100644 --- a/asusctl/src/anime_cli.rs +++ b/asusctl/src/anime_cli.rs @@ -125,7 +125,7 @@ pub struct AnimeGif { pub bright: f32, #[argh( option, - default = "1", + default = "0", description = "how many loops to play - 0 is infinite" )] pub loops: u32, @@ -144,7 +144,7 @@ pub struct AnimeGifDiagonal { pub bright: f32, #[argh( option, - default = "1", + default = "0", description = "how many loops to play - 0 is infinite" )] pub loops: u32, diff --git a/rog-anime/data/g835l/images/.gitkeep b/rog-anime/data/g835l/images/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rog-anime/data/g835l/templates/custom-image-template.png b/rog-anime/data/g835l/templates/custom-image-template.png new file mode 100644 index 00000000..f5c56ec9 Binary files /dev/null and b/rog-anime/data/g835l/templates/custom-image-template.png differ diff --git a/rog-anime/src/data.rs b/rog-anime/src/data.rs index d20a9b55..8e560097 100644 --- a/rog-anime/src/data.rs +++ b/rog-anime/src/data.rs @@ -103,8 +103,10 @@ impl AnimeType { AnimeType::GA402 } else if board_name.contains("GU604V") { AnimeType::GU604 - } else if board_name.contains("G635L") || board_name.contains("G635L") { + } else if board_name.contains("G635L") { AnimeType::G635L + } else if board_name.contains("G835L") { + AnimeType::G835L } else { AnimeType::Unsupported } @@ -114,7 +116,9 @@ impl AnimeType { pub fn width(&self) -> usize { match self { AnimeType::GU604 => 70, - AnimeType::G835L => 74, + // TODO: Find G635L W*H + AnimeType::G635L => 68, + AnimeType::G835L => 68, _ => 74, } } @@ -124,7 +128,8 @@ impl AnimeType { match self { AnimeType::GA401 => 36, AnimeType::GU604 => 43, - AnimeType::G835L => 39, + AnimeType::G635L => 34, + AnimeType::G835L => 34, _ => 39, } } @@ -133,8 +138,9 @@ impl AnimeType { pub fn data_length(&self) -> usize { match self { AnimeType::GA401 => PANE_LEN * 2, - AnimeType::GU604 => PANE_LEN * 3, - AnimeType::G835L => PANE_LEN * 3, + // G835L has 810 LEDs: 210 (triangle) + 600 (staggered rectangle) + AnimeType::G635L => 810, // TODO: This is provisional until we have a G635L to test on + AnimeType::G835L => 810, _ => PANE_LEN * 3, } } @@ -198,29 +204,35 @@ impl TryFrom for AnimePacketType { } let mut buffers = match anime.anime { - AnimeType::GA401 => vec![[0; 640]; 2], - AnimeType::GA402 - | AnimeType::GU604 - | AnimeType::G635L - | AnimeType::G835L - | AnimeType::Unsupported => { + AnimeType::GA401 | AnimeType::G635L | AnimeType::G835L => vec![[0; 640]; 2], + AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported => { 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); + // G835L has different packing: 627 bytes in pane 1, 183 bytes in pane 2 + if anime.anime == AnimeType::G835L || anime.anime == AnimeType::G635L { + let data = anime.data.as_slice(); + // Pane 1: first 627 bytes + let pane1_len = PANE_LEN.min(data.len()); + buffers[0][BLOCK_START..BLOCK_START + pane1_len].copy_from_slice(&data[..pane1_len]); + // Pane 2: remaining bytes (183) + if data.len() > PANE_LEN { + let pane2_len = data.len() - PANE_LEN; + buffers[1][BLOCK_START..BLOCK_START + pane2_len].copy_from_slice(&data[PANE_LEN..]); + } + } else { + for (idx, chunk) in anime.data.as_slice().chunks(PANE_LEN).enumerate() { + buffers[idx][BLOCK_START..BLOCK_START + chunk.len()].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 - | AnimeType::GU604 - | AnimeType::G635L - | AnimeType::G835L - | AnimeType::Unsupported + AnimeType::GA402 | AnimeType::GU604 | AnimeType::Unsupported ) { buffers[2][..7].copy_from_slice(&USB_PREFIX3); } diff --git a/rog-anime/src/diagonal.rs b/rog-anime/src/diagonal.rs index a71f9f99..1d6d10ef 100644 --- a/rog-anime/src/diagonal.rs +++ b/rog-anime/src/diagonal.rs @@ -146,6 +146,8 @@ impl AnimeDiagonal { match anime_type { AnimeType::GA401 => self.to_ga401_packets(), AnimeType::GU604 => self.to_gu604_packets(), + AnimeType::G635L => self.to_g835l_packets(), // TODO: Verify with G635L model + AnimeType::G835L => self.to_g835l_packets(), _ => self.to_ga402_packets(), } } @@ -381,4 +383,80 @@ impl AnimeDiagonal { AnimeDataBuffer::from_vec(crate::AnimeType::GA402, buf) } + + /// G835L diagonal packing - inverted geometry (rows grow then constant) + /// Triangle (rows 0-27): pairs grow from 1→14 LEDs + /// Rectangle (rows 28-67): constant 15 LEDs + /// + /// Diagonal PNG layout for G835L: + /// - Image height = 34 (row pairs) + /// - Image width = 68 (half-step X grid) + /// - Even/odd rows are interleaved in X (staggered by 0.5 LED = 1 px) + fn to_g835l_packets(&self) -> Result { + use log::debug; + + let mut buf = vec![0u8; AnimeType::G835L.data_length()]; + let mut buf_idx = 0usize; + + debug!( + "G835L packing: image dimensions {}x{}, buffer size {}", + self.1.first().map(|r| r.len()).unwrap_or(0), + self.1.len(), + buf.len() + ); + + // Helper: get row length for G835L + fn row_length(row: usize) -> usize { + if row < 28 { + row / 2 + 1 + } else { + 15 + } + } + + // Helper: starting X (in LED units) for the row + fn first_x(row: usize) -> usize { + if row < 28 { + 0 + } else { + (row - 28) / 2 + } + } + + // Process all 68 rows + for row in 0..68 { + let len = row_length(row); + let img_y = row / 2; + let base_x = first_x(row); + let stagger = row % 2; + + for i in 0..len { + // Half-step X grid: even rows on even pixels, odd rows on odd pixels. + let img_x = (base_x + i) * 2 + stagger; + + // Read from image, clamp to bounds + let val = if img_y < self.1.len() && img_x < self.1[img_y].len() { + self.1[img_y][img_x] + } else { + 0 + }; + + // Log first LED of each row for debugging + if i == 0 { + debug!( + "Row {}: len={}, first LED at img[{}][{}] = {}", + row, len, img_y, img_x, val + ); + } + + if buf_idx < buf.len() { + buf[buf_idx] = val; + } + buf_idx += 1; + } + } + + debug!("G835L packing complete: {} bytes written", buf_idx); + AnimeDataBuffer::from_vec(AnimeType::G835L, buf) + } } diff --git a/rog-anime/src/image.rs b/rog-anime/src/image.rs index fee51da7..0f5aec91 100644 --- a/rog-anime/src/image.rs +++ b/rog-anime/src/image.rs @@ -137,8 +137,8 @@ impl AnimeImage { fn scale_y(anime_type: AnimeType) -> f32 { match anime_type { AnimeType::GA401 => 0.3, - AnimeType::GU604 => 0.28, - _ => 0.283, + AnimeType::GA402 => 0.283, + _ => 0.28, } } @@ -149,6 +149,7 @@ impl AnimeImage { /// square grid, so `first_x` is the x position on that grid where the /// LED is actually positioned in relation to the Y. /// + /// For GA401/GA402/GU604 (shrinking pattern - diagonal cuts in from left): /// ```text /// +------------+ /// | | @@ -162,6 +163,19 @@ impl AnimeImage { /// ^ ------+ /// first_x /// ``` + /// + /// For G835L/G635L (inverted pattern - triangle grows then rectangle shifts): + /// ```text + /// ● <- Row 0: first_x = 0, width = 1 + /// ● <- Row 1: first_x = 0 (stagger), width = 1 + /// ● ● <- Row 2: first_x = 0, width = 2 + /// ● ● <- Row 3: first_x = 0 (stagger), width = 2 + /// ... <- Triangle continues, first_x = 0 for rows 0-27 + /// ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● <- Row 28+: first_x grows + /// ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● <- Rectangle shifts right + /// ``` + /// Triangle (rows 0-27): first_x = 0 (no cumulative shift) + /// Rectangle (rows 28-67): first_x = (y - 28) / 2 (shifts right) fn first_x(anime_type: AnimeType, y: u32) -> u32 { match anime_type { AnimeType::GA401 => { @@ -179,6 +193,16 @@ impl AnimeImage { // and then their offset grows by one every two rows (y - 9) / 2 } + AnimeType::G635L | AnimeType::G835L => { + // G835L/G635L have inverted geometry - triangle at top-left, rectangle shifts right + // Triangle (rows 0-27): no cumulative shift, just alternating stagger + // Rectangle (rows 28-67): shifts right by ~0.5px per row + if y < 28 { + 0 + } else { + (y - 28) / 2 + } + } _ => { // first 11 rows start at zero if y <= 11 { @@ -221,6 +245,16 @@ impl AnimeImage { } 38 - Self::first_x(anime_type, y) + y % 2 } + AnimeType::G635L | AnimeType::G835L => { + // G835L/G635L rows GROW then stay constant (inverted from other devices) + // Triangle (rows 0-27): pairs of rows with same length, 1→14 + // Rectangle (rows 28-67): constant 15 LEDs + if y < 28 { + y / 2 + 1 + } else { + 15 + } + } _ => { if y <= 11 { return 34; @@ -235,8 +269,9 @@ impl AnimeImage { 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::GU604 => (38.0 + 0.5) * Self::scale_x(anime_type), + AnimeType::G635L => (33.0 + 0.5) * Self::scale_x(anime_type), + AnimeType::G835L => (33.0 + 0.5) * Self::scale_x(anime_type), _ => (35.0 + 0.5) * Self::scale_x(anime_type), } } @@ -246,6 +281,8 @@ impl AnimeImage { match anime_type { AnimeType::GA401 => 55, AnimeType::GU604 => 62, + AnimeType::G635L => 68, + AnimeType::G835L => 68, _ => 61, } } @@ -256,6 +293,8 @@ impl AnimeImage { // 54.0 = End column LED count (physical) plus one dead pixel AnimeType::GA401 => (54.0 + 1.0) * Self::scale_y(anime_type), AnimeType::GU604 => 62.0 * Self::scale_y(anime_type), + AnimeType::G635L => 68.0 * Self::scale_y(anime_type), + AnimeType::G835L => 68.0 * Self::scale_y(anime_type), // GA402 may not have dead pixels and require only the physical LED count _ => 61.0 * Self::scale_y(anime_type), } @@ -269,8 +308,8 @@ impl AnimeImage { 1 | 3 => 35, // Some rows are padded _ => 36 - y / 2, }, - AnimeType::GU604 => AnimeImage::width(anime_type, y), - // GA402 does not have padding, equivalent to width + + // Other devices don't have dead pixels _ => AnimeImage::width(anime_type, y), } } @@ -405,13 +444,35 @@ impl AnimeImage { let transform = Mat3::from_scale_angle_translation(self.scale, self.angle, self.translation); - let pos_in_leds = Mat3::from_translation(Vec2::new(20.0, 20.0)); + let pos_in_leds = Mat3::from_translation(self.led_center()); // Get LED-to-image coords let led_from_px = pos_in_leds * led_from_cm * transform * cm_from_px * center; led_from_px.inverse() } + fn led_center(&self) -> Vec2 { + if !matches!(self.anime_type, AnimeType::G635L | AnimeType::G835L) { + return Vec2::new(20.0, 20.0); + } + + let mut min = Vec2::splat(f32::INFINITY); + let mut max = Vec2::splat(f32::NEG_INFINITY); + for led in self.led_pos.iter().flatten() { + let pos = Vec2::new(led.x(), led.y()); + min = min.min(pos); + max = max.max(pos); + } + + if min.x.is_finite() { + let mut center = (min + max) * 0.5; + center.y += 1.0; + center + } else { + Vec2::new(20.0, 20.0) + } + } + /// Generate the base image from inputs. The result can be displayed as is /// or updated via scale, position, or angle then displayed again after /// `update()`. diff --git a/rog-anime/tests/data/g835l-diagonal-fullbright.png b/rog-anime/tests/data/g835l-diagonal-fullbright.png new file mode 100644 index 00000000..a308f141 Binary files /dev/null and b/rog-anime/tests/data/g835l-diagonal-fullbright.png differ diff --git a/rog-anime/tests/data/g835l-diagonal.gif b/rog-anime/tests/data/g835l-diagonal.gif new file mode 100644 index 00000000..c2105f59 Binary files /dev/null and b/rog-anime/tests/data/g835l-diagonal.gif differ diff --git a/rog-anime/tests/data/g835l-diagonal.png b/rog-anime/tests/data/g835l-diagonal.png new file mode 100644 index 00000000..e36be75f Binary files /dev/null and b/rog-anime/tests/data/g835l-diagonal.png differ diff --git a/rog-anime/tests/g835l.rs b/rog-anime/tests/g835l.rs new file mode 100644 index 00000000..97ce4049 --- /dev/null +++ b/rog-anime/tests/g835l.rs @@ -0,0 +1,556 @@ +// TODO: This is a provisional copy paste of GA401 + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use rog_anime::*; + + #[test] + fn g835l_image_edge_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let mut matrix = AnimeImage::new( + Vec2::new(1.0, 1.0), + 0.0, + Vec2::default(), + 0.0, + vec![Pixel::default(); 1000], + 100, + AnimeType::G835L, + ) + .unwrap(); + matrix.edge_outline(); + let data = AnimeDataBuffer::try_from(&matrix).unwrap(); + let pkt = AnimePacketType::try_from(data).unwrap(); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + } + + #[test] + fn g835l_diagonal_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/g835l-diagonal.png"); + + let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::G835L).unwrap(); + let data = matrix.into_data_buffer(AnimeType::G835L).unwrap(); + let pkt = AnimePacketType::try_from(data).unwrap(); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + } + + #[test] + fn g835l_diagonal_fullbright_packet_check() { + let pkt0_check = [ + 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt1_check = [ + 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/g835l-diagonal-fullbright.png"); + + let matrix = AnimeDiagonal::from_png(&path, None, 255.0, AnimeType::G835L).unwrap(); + let data = matrix.into_data_buffer(AnimeType::G835L).unwrap(); + let pkt = AnimePacketType::try_from(data).unwrap(); + + assert_eq!(pkt[0], pkt0_check); + assert_eq!(pkt[1], pkt1_check); + } + + #[test] + fn g835l_diagonal_gif_wave_packet_check() { + let pkt0_frame0_check = [ + 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x7f, 0x92, 0x84, 0xa2, 0x95, 0xac, 0x8a, + 0xa0, 0xaf, 0x97, 0xa4, 0xa8, 0x91, 0x9c, 0x9e, 0x99, 0x98, 0x98, 0x91, 0x82, 0x99, + 0x97, 0x8d, 0x7c, 0x67, 0x99, 0x8d, 0x7a, 0x63, 0x4a, 0xa0, 0x92, 0x7d, 0x63, 0x48, + 0x2e, 0x9a, 0x83, 0x67, 0x4a, 0x2e, 0x17, 0xa6, 0x8d, 0x70, 0x50, 0x32, 0x19, 0x08, + 0x9a, 0x7b, 0x5a, 0x3b, 0x20, 0x0c, 0x02, 0xa8, 0x89, 0x67, 0x46, 0x2a, 0x15, 0x09, + 0x07, 0x97, 0x75, 0x54, 0x37, 0x21, 0x13, 0x10, 0x16, 0xa6, 0x84, 0x63, 0x45, 0x2e, + 0x20, 0x1c, 0x21, 0x2e, 0x91, 0x71, 0x54, 0x3d, 0x2f, 0x2a, 0x2e, 0x3a, 0x4c, 0x9d, + 0x7d, 0x61, 0x4c, 0x3e, 0x39, 0x3d, 0x49, 0x5a, 0x6d, 0x87, 0x6d, 0x58, 0x4c, 0x48, + 0x4c, 0x58, 0x69, 0x7c, 0x8e, 0x8e, 0x75, 0x63, 0x58, 0x55, 0x5a, 0x67, 0x78, 0x8b, + 0x9d, 0xab, 0x7a, 0x69, 0x60, 0x5f, 0x66, 0x74, 0x86, 0x9a, 0xac, 0xba, 0xc1, 0x7a, + 0x6c, 0x65, 0x66, 0x6f, 0x7f, 0x93, 0xa7, 0xba, 0xc9, 0xd0, 0xce, 0x6a, 0x65, 0x69, + 0x74, 0x86, 0x9c, 0xb2, 0xc7, 0xd6, 0xde, 0xdd, 0xd2, 0x63, 0x61, 0x67, 0x75, 0x89, + 0xa1, 0xba, 0xd0, 0xe1, 0xea, 0xea, 0xe0, 0xcc, 0x59, 0x61, 0x71, 0x88, 0xa2, 0xbd, + 0xd5, 0xe8, 0xf3, 0xf4, 0xec, 0xd9, 0xbf, 0x4e, 0x58, 0x6a, 0x82, 0x9e, 0xbc, 0xd6, + 0xeb, 0xf8, 0xfc, 0xf4, 0xe4, 0xca, 0xac, 0x4b, 0x5f, 0x79, 0x97, 0xb6, 0xd3, 0xea, + 0xf9, 0xfe, 0xf9, 0xea, 0xd3, 0xb6, 0x96, 0x3d, 0x51, 0x6c, 0x8c, 0xad, 0xcb, 0xe4, + 0xf6, 0xfd, 0xfa, 0xed, 0xd8, 0xbd, 0x9f, 0x82, 0x43, 0x5e, 0x7f, 0xa1, 0xc0, 0xdb, + 0xee, 0xf7, 0xf6, 0xeb, 0xd8, 0xc0, 0xa4, 0x89, 0x71, 0x50, 0x70, 0x92, 0xb3, 0xcf, + 0xe3, 0xee, 0xee, 0xe6, 0xd5, 0xbe, 0xa4, 0x8c, 0x76, 0x67, 0x62, 0x84, 0xa5, 0xc1, + 0xd5, 0xe1, 0xe3, 0xdc, 0xcd, 0xb8, 0xa1, 0x8a, 0x77, 0x6a, 0x64, 0x76, 0x96, 0xb2, + 0xc7, 0xd3, 0xd5, 0xcf, 0xc1, 0xae, 0x99, 0x84, 0x73, 0x68, 0x65, 0x6a, 0x89, 0xa4, + 0xb8, 0xc4, 0xc6, 0xc0, 0xb3, 0xa1, 0x8d, 0x7a, 0x6b, 0x63, 0x62, 0x69, 0x78, 0x98, + 0xab, 0xb5, 0xb8, 0xb1, 0xa4, 0x93, 0x7f, 0x6e, 0x60, 0x59, 0x5b, 0x64, 0x75, 0x8c, + 0xa0, 0xa9, 0xaa, 0xa3, 0x95, 0x83, 0x70, 0x5f, 0x53, 0x4d, 0x50, 0x5b, 0x6e, 0x87, + 0xa4, 0xa0, 0x9f, 0x96, 0x87, 0x74, 0x61, 0x50, 0x44, 0x3f, 0x42, 0x4f, 0x64, 0x7e, + 0x9d, 0xbc, 0x97, 0x8c, 0x7c, 0x68, 0x53, 0x41, 0x34, 0x2f, 0x33, 0x41, 0x56, 0x73, + 0x93, 0xb3, 0xd1, 0x86, 0x74, 0x5e, 0x47, 0x34, 0x27, 0x21, 0x25, 0x32, 0x48, 0x65, + 0x86, 0xa7, 0xc6, 0xe0, 0x70, 0x57, 0x3f, 0x2a, 0x1b, 0x14, 0x17, 0x24, 0x39, 0x56, + 0x77, 0x99, 0xb9, 0xd4, 0xe6, 0x56, 0x3b, 0x24, 0x13, 0x0a, 0x0c, 0x17, 0x2c, 0x48, + 0x69, 0x8b, 0xab, 0xc6, 0xd9, 0xe3, 0x3b, 0x22, 0x0f, 0x04, 0x04, 0x0e, 0x21, 0x3c, + 0x5b, 0x7d, 0x9c, 0xb7, 0xca, 0xd5, 0xd6, 0x25, 0x0f, 0x03, 0x00, 0x08, 0x19, 0x32, + 0x50, 0x70, 0x8f, 0xa9, 0xbc, 0xc6, 0xc7, 0xc0, 0x14, 0x05, 0x01, 0x06, 0x15, 0x2c, + 0x49, 0x67, 0x84, 0x9c, 0xae, 0xb7, 0xb8, 0xb0, 0xa2, 0x0c, 0x05, 0x09, 0x16, 0x2b, + 0x45, 0x61, 0x7c, 0x93, 0xa3, 0xab, 0xaa, 0xa2, 0x93, 0x81, 0x0e, 0x10, 0x1b, 0x2e, + 0x46, 0x60, 0x78, 0x8d, 0x9b, 0xa1, 0x9e, 0x94, 0x85, 0x72, 0x5f, 0x1b, 0x24, 0x35, + 0x4b, 0x62, 0x79, 0x8b, 0x96, 0x9a, 0x96, 0x8a, 0x79, 0x65, 0x50, 0x3f, 0x30, 0x40, + 0x54, 0x6a, 0x7e, 0x8d, 0x97, 0x98, 0x91, 0x84, 0x70, 0x5a, 0x44, 0x32, 0x26, 0x4d, + 0x60, 0x74, 0x87, 0x94, 0x9b, 0x9a, 0x91, 0x81, 0x6c, 0x53, 0x3c, 0x28, 0x1a, 0x15, + 0x6e, 0x82, 0x93, 0x9f, 0xa4, 0xa1, 0x96, 0x83, 0x6b, 0x51, 0x37, 0x21, 0x11, 0x0a, + 0x0e, 0x91, 0xa1, 0xac, 0xb0, 0xab, 0x9e, 0x89, 0x6f, 0x53, 0x37, 0x1e, 0x0d, 0x04, + 0x05, 0x11, 0xb0, 0xbb, 0xbe, 0xb8, 0xaa, 0x93, 0x77, 0x59, 0x3a, 0x20, 0x0c, 0x01, + 0x01, 0x0a, 0x1d, 0xca, 0xcd, 0xc7, 0xb7, 0xa0, 0x83, 0x62, 0x42, 0x26, 0x10, 0x03, + 0x01, 0x08, 0x19, 0x31, 0xdc, 0xd6, 0xc6, 0xae, 0x90, 0x6f, 0x4e, 0x30, 0x18, 0x0a, + 0x05, 0x0a, 0x19, 0x2f, 0x4a, 0xe4, 0xd4, 0xbd, 0x9f, 0x7d, 0x5b, 0x3c, 0x24, 0x14, + 0x0d, 0x11, 0x1e, 0x32, 0x4a, 0x64, 0xe1, 0xcb, 0xad, 0x8c, 0x6a, 0x4b, 0x31, 0x20, + 0x19, 0x1b, 0x26, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt1_frame0_check = [ + 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0x4f, 0x66, 0x7c, 0xd6, 0xba, 0x99, 0x78, + 0x59, 0x40, 0x2f, 0x27, 0x28, 0x32, 0x42, 0x57, 0x6d, 0x80, 0x8f, 0xc4, 0xa5, 0x85, + 0x67, 0x4f, 0x3e, 0x35, 0x37, 0x40, 0x4f, 0x63, 0x77, 0x89, 0x96, 0x9b, 0xad, 0x8f, + 0x73, 0x5c, 0x4c, 0x44, 0x46, 0x4f, 0x5e, 0x71, 0x84, 0x94, 0xa0, 0xa3, 0x9f, 0x96, + 0x7b, 0x66, 0x58, 0x52, 0x54, 0x5e, 0x6e, 0x80, 0x93, 0xa2, 0xac, 0xaf, 0xa9, 0x9a, + 0x80, 0x6d, 0x61, 0x5c, 0x60, 0x6c, 0x7c, 0x8f, 0xa2, 0xb2, 0xbb, 0xbd, 0xb5, 0xa5, + 0x8e, 0x70, 0x66, 0x64, 0x6a, 0x77, 0x89, 0x9d, 0xb1, 0xc1, 0xca, 0xcb, 0xc4, 0xb3, + 0x9a, 0x7c, 0x66, 0x67, 0x6f, 0x7e, 0x92, 0xa8, 0xbd, 0xce, 0xd9, 0xda, 0xd3, 0xc1, + 0xa8, 0x8a, 0x68, 0x65, 0x70, 0x82, 0x98, 0xb0, 0xc7, 0xd9, 0xe5, 0xe8, 0xe1, 0xd0, + 0xb7, 0x98, 0x76, 0x54, 0x6d, 0x81, 0x99, 0xb3, 0xcd, 0xe1, 0xee, 0xf3, 0xed, 0xdd, + 0xc5, 0xa6, 0x85, 0x63, 0x45, 0x7b, 0x96, 0xb3, 0xce, 0xe5, 0xf4, 0xfa, 0xf6, 0xe8, + 0xd1, 0xb4, 0x93, 0x71, 0x53, 0x3b, 0x8f, 0xad, 0xcb, 0xe4, 0xf5, 0xfe, 0xfc, 0xef, + 0xda, 0xbe, 0x9f, 0x7f, 0x61, 0x4a, 0x3b, 0xa5, 0xc4, 0xdf, 0xf2, 0xfd, 0xfd, 0xf2, + 0xdf, 0xc5, 0xa8, 0x89, 0x6e, 0x57, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt0_frame16_check = [ + 0x5e, 0xc0, 0x02, 0x01, 0x00, 0x73, 0x02, 0x95, 0x88, 0x92, 0x75, 0x81, 0x60, 0x8f, + 0x6d, 0x4c, 0x7c, 0x5a, 0x3c, 0x8a, 0x69, 0x4a, 0x32, 0x77, 0x59, 0x41, 0x32, 0x83, + 0x66, 0x50, 0x40, 0x3a, 0x72, 0x5c, 0x4e, 0x49, 0x4c, 0x79, 0x66, 0x59, 0x56, 0x5a, + 0x65, 0x6c, 0x61, 0x5f, 0x66, 0x72, 0x84, 0x6d, 0x66, 0x66, 0x6e, 0x7d, 0x90, 0xa5, + 0x65, 0x68, 0x72, 0x83, 0x99, 0xaf, 0xc5, 0x61, 0x65, 0x72, 0x86, 0x9d, 0xb6, 0xcd, + 0xdf, 0x5f, 0x6e, 0x84, 0x9d, 0xb9, 0xd2, 0xe6, 0xf2, 0x55, 0x66, 0x7d, 0x99, 0xb7, + 0xd2, 0xe8, 0xf7, 0xfc, 0x5a, 0x73, 0x91, 0xb1, 0xce, 0xe6, 0xf7, 0xfe, 0xfb, 0x4c, + 0x67, 0x86, 0xa7, 0xc6, 0xe0, 0xf3, 0xfc, 0xfb, 0xf0, 0x58, 0x78, 0x9a, 0xbb, 0xd6, + 0xeb, 0xf6, 0xf7, 0xed, 0xdc, 0x4a, 0x6a, 0x8c, 0xad, 0xca, 0xdf, 0xec, 0xee, 0xe7, + 0xd7, 0xc1, 0x5b, 0x7d, 0x9f, 0xbc, 0xd2, 0xdf, 0xe3, 0xdd, 0xcf, 0xbb, 0xa4, 0x4f, + 0x70, 0x90, 0xad, 0xc3, 0xd0, 0xd5, 0xd0, 0xc3, 0xb1, 0x9b, 0x87, 0x64, 0x83, 0x9f, + 0xb4, 0xc1, 0xc6, 0xc1, 0xb5, 0xa3, 0x90, 0x7c, 0x6d, 0x5c, 0x79, 0x93, 0xa7, 0xb3, + 0xb7, 0xb2, 0xa6, 0x95, 0x81, 0x6f, 0x61, 0x59, 0x73, 0x8b, 0x9d, 0xa7, 0xa9, 0xa3, + 0x97, 0x85, 0x72, 0x60, 0x53, 0x4c, 0x4e, 0x70, 0x86, 0x96, 0x9e, 0x9f, 0x97, 0x89, + 0x77, 0x63, 0x51, 0x44, 0x3e, 0x40, 0x4b, 0x86, 0x93, 0x99, 0x97, 0x8e, 0x7e, 0x6a, + 0x55, 0x43, 0x35, 0x2f, 0x31, 0x3d, 0x51, 0x8a, 0x95, 0x99, 0x94, 0x88, 0x76, 0x61, + 0x4a, 0x36, 0x27, 0x20, 0x22, 0x2e, 0x43, 0x5f, 0x9b, 0x9c, 0x96, 0x87, 0x73, 0x5b, + 0x43, 0x2d, 0x1c, 0x14, 0x15, 0x20, 0x34, 0x50, 0x71, 0xa4, 0x9b, 0x8b, 0x74, 0x5a, + 0x3f, 0x27, 0x15, 0x0b, 0x0a, 0x14, 0x27, 0x42, 0x62, 0x84, 0xa5, 0x92, 0x7a, 0x5d, + 0x40, 0x26, 0x11, 0x05, 0x03, 0x0b, 0x1d, 0x36, 0x55, 0x76, 0x96, 0x9d, 0x83, 0x64, + 0x45, 0x29, 0x12, 0x04, 0x00, 0x06, 0x15, 0x2d, 0x4b, 0x6a, 0x89, 0xa4, 0x8f, 0x6f, + 0x4e, 0x30, 0x18, 0x07, 0x01, 0x05, 0x12, 0x28, 0x44, 0x62, 0x7f, 0x98, 0xab, 0x7c, + 0x5a, 0x3b, 0x21, 0x0f, 0x06, 0x08, 0x14, 0x27, 0x41, 0x5c, 0x77, 0x8f, 0xa0, 0xa9, + 0x68, 0x48, 0x2d, 0x1a, 0x10, 0x10, 0x19, 0x2b, 0x42, 0x5c, 0x74, 0x89, 0x98, 0xa0, + 0x9e, 0x57, 0x3b, 0x27, 0x1c, 0x1b, 0x23, 0x33, 0x48, 0x5f, 0x76, 0x88, 0x95, 0x9a, + 0x97, 0x8c, 0x4a, 0x36, 0x2a, 0x28, 0x2f, 0x3e, 0x51, 0x67, 0x7b, 0x8c, 0x96, 0x99, + 0x93, 0x86, 0x73, 0x44, 0x39, 0x37, 0x3e, 0x4b, 0x5e, 0x72, 0x85, 0x93, 0x9b, 0x9c, + 0x94, 0x84, 0x6f, 0x57, 0x48, 0x46, 0x4d, 0x5b, 0x6c, 0x80, 0x91, 0x9e, 0xa4, 0xa3, + 0x99, 0x87, 0x70, 0x55, 0x3b, 0x54, 0x5c, 0x6a, 0x7c, 0x8f, 0xa0, 0xac, 0xb1, 0xad, + 0xa1, 0x8e, 0x74, 0x58, 0x3b, 0x22, 0x69, 0x78, 0x8b, 0x9e, 0xaf, 0xbb, 0xbf, 0xbb, + 0xad, 0x98, 0x7d, 0x5e, 0x40, 0x24, 0x0f, 0x84, 0x98, 0xac, 0xbe, 0xca, 0xce, 0xc9, + 0xbb, 0xa5, 0x89, 0x68, 0x48, 0x2b, 0x14, 0x05, 0xa2, 0xb8, 0xcb, 0xd8, 0xdd, 0xd8, + 0xca, 0xb3, 0x96, 0x75, 0x54, 0x35, 0x1c, 0x0c, 0x05, 0xc0, 0xd5, 0xe3, 0xea, 0xe6, + 0xd8, 0xc2, 0xa5, 0x84, 0x61, 0x42, 0x28, 0x16, 0x0e, 0x10, 0xdb, 0xec, 0xf4, 0xf1, + 0xe5, 0xd0, 0xb3, 0x92, 0x70, 0x50, 0x36, 0x23, 0x1a, 0x1b, 0x24, 0xf0, 0xfa, 0xfa, + 0xef, 0xdb, 0xc0, 0xa0, 0x7e, 0x5f, 0x45, 0x32, 0x28, 0x28, 0x31, 0x40, 0xfc, 0xfe, + 0xf5, 0xe3, 0xc9, 0xab, 0x8b, 0x6c, 0x53, 0x41, 0x37, 0x37, 0x3f, 0x4e, 0x61, 0xfd, + 0xf7, 0xe7, 0xcf, 0xb3, 0x94, 0x78, 0x60, 0x4f, 0x46, 0x46, 0x4e, 0x5d, 0x6f, 0x82, + 0xf4, 0xe7, 0xd1, 0xb7, 0x9b, 0x80, 0x6a, 0x5a, 0x53, 0x54, 0x5d, 0x6c, 0x7e, 0x91, + 0xa1, 0xe2, 0xce, 0xb6, 0x9c, 0x84, 0x70, 0x62, 0x5d, 0x60, 0x6a, 0x7a, 0x8d, 0xa0, + 0xb1, 0xbb, 0xc8, 0xb2, 0x9a, 0x84, 0x72, 0x67, 0x64, 0x69, 0x75, 0x86, 0x9b, 0xaf, + 0xbf, 0xca, 0xcd, 0xa9, 0x93, 0x7f, 0x70, 0x67, 0x66, 0x6d, 0x7c, 0x8f, 0xa5, 0xbb, + 0xcd, 0xd8, 0xdc, 0xd5, 0x89, 0x76, 0x69, 0x63, 0x64, 0x6e, 0x7e, 0x94, 0xac, 0xc4, + 0xd8, 0xe5, 0xe9, 0xe3, 0xd4, 0x6b, 0x5f, 0x5a, 0x5e, 0x6a, 0x7d, 0x95, 0xaf, 0xc9, + 0xdf, 0xed, 0xf3, 0xef, 0xe1, 0xca, 0x52, 0x4f, 0x54, 0x62, 0x77, 0x91, 0xae, 0xca, + 0xe1, 0xf2, 0xfa, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + let pkt1_frame16_check = [ + 0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02, 0xeb, 0xd6, 0xb9, 0x41, 0x47, 0x56, 0x6d, + 0x89, 0xa8, 0xc6, 0xe0, 0xf3, 0xfd, 0xfd, 0xf2, 0xde, 0xc4, 0xa4, 0x39, 0x49, 0x61, + 0x7e, 0x9f, 0xbe, 0xda, 0xef, 0xfb, 0xfd, 0xf5, 0xe3, 0xca, 0xad, 0x8f, 0x3a, 0x53, + 0x71, 0x92, 0xb3, 0xd1, 0xe7, 0xf5, 0xf9, 0xf3, 0xe3, 0xcd, 0xb2, 0x95, 0x7b, 0x44, + 0x62, 0x84, 0xa6, 0xc4, 0xdc, 0xec, 0xf1, 0xed, 0xdf, 0xcb, 0xb2, 0x98, 0x80, 0x6d, + 0x54, 0x76, 0x97, 0xb6, 0xcf, 0xdf, 0xe6, 0xe3, 0xd7, 0xc5, 0xae, 0x96, 0x80, 0x6f, + 0x66, 0x68, 0x89, 0xa7, 0xc0, 0xd1, 0xd8, 0xd6, 0xcc, 0xbb, 0xa6, 0x90, 0x7c, 0x6e, + 0x66, 0x67, 0x7c, 0x9a, 0xb2, 0xc2, 0xc9, 0xc8, 0xbe, 0xae, 0x9a, 0x86, 0x74, 0x68, + 0x63, 0x65, 0x70, 0x8e, 0xa4, 0xb4, 0xba, 0xb8, 0xaf, 0x9f, 0x8c, 0x79, 0x69, 0x5e, + 0x5b, 0x60, 0x6d, 0x81, 0x9a, 0xa8, 0xad, 0xaa, 0x9f, 0x90, 0x7d, 0x6a, 0x5b, 0x52, + 0x50, 0x57, 0x66, 0x7c, 0x96, 0x9e, 0xa2, 0x9d, 0x92, 0x81, 0x6e, 0x5b, 0x4c, 0x43, + 0x42, 0x4a, 0x5b, 0x73, 0x8f, 0xae, 0x9a, 0x94, 0x86, 0x74, 0x60, 0x4c, 0x3d, 0x34, + 0x33, 0x3c, 0x4d, 0x66, 0x85, 0xa5, 0xc4, 0x8e, 0x7f, 0x6a, 0x54, 0x40, 0x2f, 0x25, + 0x24, 0x2d, 0x3f, 0x58, 0x78, 0x99, 0xba, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/g835l-diagonal.gif"); + + let gif = + AnimeGif::from_diagonal_gif(&path, AnimTime::Count(1), 1.0, AnimeType::G835L).unwrap(); + assert_eq!(gif.frame_count(), 48); + + let pkt = AnimePacketType::try_from(gif.frames()[0].frame().clone()).unwrap(); + assert_eq!(pkt[0], pkt0_frame0_check); + assert_eq!(pkt[1], pkt1_frame0_check); + + let pkt = AnimePacketType::try_from(gif.frames()[16].frame().clone()).unwrap(); + assert_eq!(pkt[0], pkt0_frame16_check); + assert_eq!(pkt[1], pkt1_frame16_check); + } +} diff --git a/rog-dbus/src/zbus_anime.rs b/rog-dbus/src/zbus_anime.rs index ed0df009..2fdec4b4 100644 --- a/rog-dbus/src/zbus_anime.rs +++ b/rog-dbus/src/zbus_anime.rs @@ -5,7 +5,7 @@ use zbus::proxy; #[proxy( interface = "xyz.ljones.Anime", default_service = "xyz.ljones.Asusd", - default_path = "/xyz/ljones" + default_path = "/xyz/ljones/aura/anime" )] pub trait Anime { /// DeviceState method diff --git a/simulators/src/animatrix/map_g635l.rs b/simulators/src/animatrix/map_g635l.rs new file mode 100644 index 00000000..3615a79d --- /dev/null +++ b/simulators/src/animatrix/map_g635l.rs @@ -0,0 +1,70 @@ +use super::Row; + +// TODO: This is a placeholder for G635L map +pub const G635L: [Row; 63] = [ + Row(0x01, 7, 32, 0), + Row(0x01, 7 + 34, 32, 0), + Row(0x01, 7 + 68, 32, 0), + Row(0x01, 7 + 102, 32, 0), // 34 len + Row(0x01, 7 + 136, 32, 0), + Row(0x01, 7 + 170, 34, 0), + Row(0x01, 7 + 204, 34, 0), + Row(0x01, 7 + 238, 34, 0), + Row(0x01, 7 + 272, 34, 0), + Row(0x01, 7 + 306, 34, 0), + Row(0x01, 7 + 340, 34, 0), + Row(0x01, 7 + 374, 34, 0), + Row(0x01, 7 + 408, 33, 1), + Row(0x01, 7 + 441, 33, 1), + Row(0x01, 7 + 474, 32, 2), + Row(0x01, 7 + 506, 32, 2), + Row(0x01, 7 + 538, 31, 3), + Row(0x01, 7 + 569, 31, 3), + Row(0x01, 7 + 600, 28, 4), + // + Row(0x74, 7 + 1, 3, 28 + 4), // adds to end of previous + Row(0x74, 7 + 3, 30, 4), + Row(0x74, 7 + 33, 29, 5), + Row(0x74, 7 + 62, 29, 5), + Row(0x74, 7 + 91, 28, 6), + Row(0x74, 7 + 119, 28, 6), + Row(0x74, 7 + 147, 27, 7), + Row(0x74, 7 + 174, 27, 7), + Row(0x74, 7 + 202, 26, 9), + Row(0x74, 7 + 228, 26, 9), + Row(0x74, 7 + 254, 25, 10), + Row(0x74, 7 + 278, 25, 9), // WEIRD OFFSET + Row(0x74, 7 + 303, 24, 10), + Row(0x74, 7 + 327, 24, 10), + Row(0x74, 7 + 351, 23, 11), + Row(0x74, 7 + 374, 23, 11), + Row(0x74, 7 + 397, 22, 12), + Row(0x74, 7 + 419, 22, 12), + Row(0x74, 7 + 441, 21, 13), + Row(0x74, 7 + 462, 21, 13), + Row(0x74, 7 + 483, 20, 14), + Row(0x74, 7 + 503, 20, 14), + Row(0x74, 7 + 523, 19, 15), + Row(0x74, 7 + 542, 19, 15), + Row(0x74, 7 + 561, 18, 16), + Row(0x74, 7 + 579, 18, 16), + Row(0x74, 7 + 597, 17, 17), + Row(0x74, 7 + 614, 13, 17), + // + Row(0xe7, 7 + 1, 4, 13 + 18), // adds to end of previous + Row(0xe7, 7 + 4, 16, 18), + Row(0xe7, 7 + 20, 16, 18), + Row(0xe7, 7 + 36, 15, 19), + Row(0xe7, 7 + 51, 15, 19), + Row(0xe7, 7 + 66, 14, 20), + Row(0xe7, 7 + 80, 12, 20), // too long? 14 + Row(0xe7, 7 + 94, 13, 21), + Row(0xe7, 7 + 107, 13, 21), + Row(0xe7, 7 + 120, 12, 12), // Actual display end + Row(0xe7, 7 + 132, 12, 22), + Row(0xe7, 7 + 144, 11, 23), + Row(0xe7, 7 + 155, 11, 23), + Row(0xe7, 7 + 166, 10, 24), + Row(0xe7, 7 + 176, 10, 24), + Row(0xe7, 7 + 186, 9, 25), +]; diff --git a/simulators/src/animatrix/map_g835l.rs b/simulators/src/animatrix/map_g835l.rs new file mode 100644 index 00000000..e26df88f --- /dev/null +++ b/simulators/src/animatrix/map_g835l.rs @@ -0,0 +1,74 @@ +use super::Row; + +// G835L layout: 68 rows (triangle + rectangle), 2 packets +pub const G835L: [Row; 69] = [ + Row(0x01, 7, 0, 0), + Row(0x01, 8, 0, 0), + Row(0x01, 9, 1, 0), + Row(0x01, 11, 1, 0), + Row(0x01, 13, 2, 0), + Row(0x01, 16, 2, 0), + Row(0x01, 19, 3, 0), + Row(0x01, 23, 3, 0), + Row(0x01, 27, 4, 0), + Row(0x01, 32, 4, 0), + Row(0x01, 37, 5, 0), + Row(0x01, 43, 5, 0), + Row(0x01, 49, 6, 0), + Row(0x01, 56, 6, 0), + Row(0x01, 63, 7, 0), + Row(0x01, 71, 7, 0), + Row(0x01, 79, 8, 0), + Row(0x01, 88, 8, 0), + Row(0x01, 97, 9, 0), + Row(0x01, 107, 9, 0), + Row(0x01, 117, 10, 0), + Row(0x01, 128, 10, 0), + Row(0x01, 139, 11, 0), + Row(0x01, 151, 11, 0), + Row(0x01, 163, 12, 0), + Row(0x01, 176, 12, 0), + Row(0x01, 189, 13, 0), + Row(0x01, 203, 13, 0), + Row(0x01, 217, 14, 0), + Row(0x01, 232, 14, 0), + Row(0x01, 247, 14, 1), + Row(0x01, 262, 14, 1), + Row(0x01, 277, 14, 2), + Row(0x01, 292, 14, 2), + Row(0x01, 307, 14, 3), + Row(0x01, 322, 14, 3), + Row(0x01, 337, 14, 4), + Row(0x01, 352, 14, 4), + Row(0x01, 367, 14, 5), + Row(0x01, 382, 14, 5), + Row(0x01, 397, 14, 6), + Row(0x01, 412, 14, 6), + Row(0x01, 427, 14, 7), + Row(0x01, 442, 14, 7), + Row(0x01, 457, 14, 8), + Row(0x01, 472, 14, 8), + Row(0x01, 487, 14, 9), + Row(0x01, 502, 14, 9), + Row(0x01, 517, 14, 10), + Row(0x01, 532, 14, 10), + Row(0x01, 547, 14, 11), + Row(0x01, 562, 14, 11), + Row(0x01, 577, 14, 12), + Row(0x01, 592, 14, 12), + Row(0x01, 607, 14, 13), + Row(0x01, 622, 11, 13), + Row(0x74, 7, 2, 25), + Row(0x74, 10, 14, 14), + Row(0x74, 25, 14, 14), + Row(0x74, 40, 14, 15), + Row(0x74, 55, 14, 15), + Row(0x74, 70, 14, 16), + Row(0x74, 85, 14, 16), + Row(0x74, 100, 14, 17), + Row(0x74, 115, 14, 17), + Row(0x74, 130, 14, 18), + Row(0x74, 145, 14, 18), + Row(0x74, 160, 14, 19), + Row(0x74, 175, 14, 19), +]; diff --git a/simulators/src/animatrix/mod.rs b/simulators/src/animatrix/mod.rs index efc8c9b2..0317a616 100644 --- a/simulators/src/animatrix/mod.rs +++ b/simulators/src/animatrix/mod.rs @@ -1,9 +1,13 @@ use rog_anime::AnimeType; +use self::map_g635l::G635L; +use self::map_g835l::G835L; use self::map_ga401::GA401; use self::map_ga402::GA402; use self::map_gu604::GU604; +mod map_g635l; +mod map_g835l; mod map_ga401; mod map_ga402; mod map_gu604; @@ -38,30 +42,18 @@ pub struct AniMatrix { impl AniMatrix { pub fn new(model: AnimeType) -> Self { - let led_shape = match model { - AnimeType::GA401 => LedShape { - vertical: 2, - horizontal: 5, - }, - AnimeType::GA402 | AnimeType::G635L | AnimeType::G835L | AnimeType::Unsupported => { - LedShape { - vertical: 2, - horizontal: 5, - } - } - AnimeType::GU604 => LedShape { - vertical: 2, - horizontal: 5, - }, + let led_shape = LedShape { + vertical: 2, + horizontal: 5, }; // Do a hard mapping of each (derived from wireshardk captures) let rows = match model { AnimeType::GA401 => GA401.to_vec(), - AnimeType::GA402 | AnimeType::G635L | AnimeType::G835L | AnimeType::Unsupported => { - GA402.to_vec() - } + AnimeType::GA402 | AnimeType::Unsupported => GA402.to_vec(), AnimeType::GU604 => GU604.to_vec(), + AnimeType::G635L => G635L.to_vec(), + AnimeType::G835L => G835L.to_vec(), }; Self { rows, led_shape } diff --git a/simulators/src/simulator.rs b/simulators/src/simulator.rs index 03ed7fc6..2bf5ae22 100644 --- a/simulators/src/simulator.rs +++ b/simulators/src/simulator.rs @@ -2,7 +2,6 @@ use std::env; use std::error::Error; use std::str::FromStr; -use log::error; use rog_anime::usb::{PROD_ID, VENDOR_ID}; use rog_anime::{AnimeType, USB_PREFIX2}; use sdl2::event::Event; @@ -20,6 +19,7 @@ pub struct VirtAnimeMatrix { animatrix: AniMatrix, } +// TODO: This isn't working impl VirtAnimeMatrix { pub fn new(model: AnimeType) -> Self { VirtAnimeMatrix { @@ -86,8 +86,12 @@ impl VirtAnimeMatrix { ] .to_vec(), }) - .map_err(|err| error!("Could not create virtual device: {:?}", err)) - .expect("Could not create virtual device"), + .unwrap_or_else(|err| { + panic!( + "Could not create virtual device: {err:?}. \ + Try loading the uhid module and ensure you have the necessary permissions." + ) + }), } } @@ -114,7 +118,7 @@ impl VirtAnimeMatrix { fn main() -> Result<(), Box> { let args: Vec = env::args().collect(); if args.len() <= 1 { - println!("Must supply arg, one of "); + println!("Must supply arg, one of "); return Ok(()); } let anime_type = AnimeType::from_str(&args[1])?;