diff --git a/Cargo.lock b/Cargo.lock index 31989d87..8b72a25e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -680,6 +680,8 @@ dependencies = [ "serde", "serde_derive", "thiserror", + "tinybmp", + "yansi-term", ] [[package]] @@ -885,6 +887,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tinybmp" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781e52493917138f60c3b98b95e39967eafd28d3c470d0d35ae020b47f011b5d" +dependencies = [ + "nom", +] + [[package]] name = "tokio" version = "0.2.20" @@ -1042,3 +1053,12 @@ checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" dependencies = [ "libc", ] + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi 0.3.8", +] diff --git a/aura/Cargo.toml b/aura/Cargo.toml index 95f418e8..cc8dedd5 100644 --- a/aura/Cargo.toml +++ b/aura/Cargo.toml @@ -15,3 +15,7 @@ dbus = { version = "^0.8.2" } serde = "1.0" serde_derive = "1.0" thiserror = "^1.0.15" +yansi-term = "0.1.2" + +[dev-dependencies] +tinybmp = "0.2.3" \ No newline at end of file diff --git a/aura/examples/animatrix.rs b/aura/examples/animatrix.rs index daa15451..fdcac245 100644 --- a/aura/examples/animatrix.rs +++ b/aura/examples/animatrix.rs @@ -1,34 +1,39 @@ -use rog_aura::{AniMeDbusWriter, AniMeMatrix, AniMePacketType}; +use rog_aura::{AniMeDbusWriter, AniMeMatrix, AniMePacketType, HEIGHT, WIDTH}; +use tinybmp::{Bmp, Pixel}; fn main() { let mut writer = AniMeDbusWriter::new().unwrap(); - // loop { - // for brightness in 0xFE..0xFF { - // let mut matrix = AniMeMatrix::new(); - // matrix.fill_with(brightness); - - // let mut matrix: AniMePacketType = AniMePacketType::from(matrix); - // // println!("{:?}", matrix[0].to_vec()); - // // println!("{:?}", matrix[1].to_vec()); - - // writer.write_image(&mut matrix).unwrap(); - // } - // break; - // } + let bmp = Bmp::from_slice(include_bytes!("test.bmp")).expect("Failed to parse BMP image"); + let pixels: Vec = bmp.into_iter().collect(); + //assert_eq!(pixels.len(), 56 * 56); // Try an outline, top and right let mut matrix = AniMeMatrix::new(); - { - let tmp = matrix.get_mut(); - for row in tmp.iter_mut() { - row[row.len() - 1] = 0xff; + + // Aligned left + for px in pixels { + if (px.x as usize) < WIDTH { + matrix.get_mut()[px.y as usize][px.x as usize] = px.color as u8; } } + // Throw an alignment border up + // { + // let tmp = matrix.get_mut(); + // for x in tmp[0].iter_mut() { + // *x = 0xff; + // } + // for row in tmp.iter_mut() { + // row[row.len() - 1] = 0xff; + // } + // } + + matrix.debug_print(); + let mut matrix: AniMePacketType = AniMePacketType::from(matrix); - println!("{:?}", matrix[0].to_vec()); - println!("{:?}", matrix[1].to_vec()); + // println!("{:?}", matrix[0].to_vec()); + // println!("{:?}", matrix[1].to_vec()); writer.write_image(&mut matrix).unwrap(); } diff --git a/aura/examples/rust.bmp b/aura/examples/rust.bmp new file mode 100644 index 00000000..a079736b Binary files /dev/null and b/aura/examples/rust.bmp differ diff --git a/aura/examples/test-skinny-45deg.bmp b/aura/examples/test-skinny-45deg.bmp new file mode 100644 index 00000000..4e6cf9f3 Binary files /dev/null and b/aura/examples/test-skinny-45deg.bmp differ diff --git a/aura/examples/test.bmp b/aura/examples/test.bmp new file mode 100644 index 00000000..1d5824d6 Binary files /dev/null and b/aura/examples/test.bmp differ diff --git a/aura/src/anime_matrix.rs b/aura/src/anime_matrix.rs index 5f34359c..de4ecabf 100644 --- a/aura/src/anime_matrix.rs +++ b/aura/src/anime_matrix.rs @@ -4,6 +4,7 @@ pub type AniMeBufferType = [[u8; WIDTH]; HEIGHT]; pub type AniMePacketType = [[u8; 640]; 2]; const BLOCK_START: usize = 7; const BLOCK_END: usize = 634; +use yansi_term::Colour::RGB; pub struct AniMeMatrix(AniMeBufferType); @@ -27,6 +28,60 @@ impl AniMeMatrix { } } } + + pub fn debug_print(&self) { + // this is the index from right. It is used to progressively shorten rows + let mut prog_row_len = WIDTH - 2; + + for (count, row) in self.0.iter().enumerate() { + // Write the top block of LEDs (first 7 rows) + if count < 6 { + if count % 2 != 0 { + print!(" "); + } else if count == 0 { + print!(" "); + } else { + print!(" "); + } + let tmp = if count == 0 || count == 1 || count == 3 || count == 5 { + row[1..].iter() + } else { + row.iter() + }; + for x in tmp { + print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x))); + } + + print!("\n"); + } else { + // Switch to next block (looks like ) + if count % 2 != 0 { + // Row after 6 is only 1 less, then rows after 7 follow pattern + if count == 7 { + prog_row_len -= 1; + } else { + prog_row_len -= 2; + } + } else { + prog_row_len += 1; // if count 6, 0 + } + + let index = row.len() - prog_row_len; + + if count % 2 == 0 { + print!(" "); + } + for (i, x) in row.iter().enumerate() { + if i >= index { + print!(" {}", RGB(*x, *x, *x).paint(&format!("{:#04X}", x))); + } else { + print!(" "); + } + } + print!("\n"); + } + } + } } impl From for AniMePacketType { @@ -39,32 +94,38 @@ impl From for AniMePacketType { let mut write_index = BLOCK_START; let mut write_block = &mut buffers[0]; let mut block1_done = false; - let mut phys_row_len = WIDTH - 1; // not taking in to account starting at 0 + + // this is the index from right. It is used to progressively shorten rows + let mut prog_row_len = WIDTH - 2; for (count, row) in anime.0.iter().enumerate() { // Write the top block of LEDs (first 7 rows) if count < 6 { - for x in row.iter() { - write_block[write_index] = *x; + for (i, x) in row.iter().enumerate() { + // Rows 0, 1, 3, 5 are short and misaligned + if count == 0 || count == 1 || count == 3 || count == 5 { + if i > 0 { + write_block[write_index - 1] = *x; + } + } else { + write_block[write_index] = *x; + } write_index += 1; } } else { - // Two offsets to correct the below with - if count == 6 { - phys_row_len -= 1; - } - if count == 7 { - phys_row_len += 1; - } - // Switch to next block (looks like ) if count % 2 != 0 { - phys_row_len -= 2; // if count 7, -= 1 + // Row after 6 is only 1 less, then rows after 7 follow pattern + if count == 7 { + prog_row_len -= 1; + } else { + prog_row_len -= 2; + } } else { - phys_row_len += 1; // if count 6, 0 + prog_row_len += 1; // if count 6, 0 } - let index = row.len() - phys_row_len; + let index = row.len() - prog_row_len; for n in index..row.len() { // Require a special case to catch the correct end-of-packet which is // 6 bytes from the end @@ -83,3 +144,87 @@ impl From for AniMePacketType { buffers } } + +#[cfg(test)] +mod tests { + use crate::{AniMeMatrix, AniMePacketType}; + + #[test] + fn check_data_alignment() { + let mut matrix = AniMeMatrix::new(); + { + let tmp = matrix.get_mut(); + for row in tmp.iter_mut() { + row[row.len() - 1] = 0xff; + } + } + + let matrix: AniMePacketType = AniMePacketType::from(matrix); + + // The bytes at the right of the initial AniMeMatrix should always end up aligned in the + // same place after conversion to data packets + + // Check against manually worked out right align + assert_eq!( + matrix[0].to_vec(), + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + .to_vec() + ); + assert_eq!( + matrix[1].to_vec(), + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 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, 0, 0, 0, + 255, 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, 255, 0, 0, 0, + 0, 0, 0, 0 + ] + .to_vec() + ); + } +}