From caef94b023698dd6614754a020fd6d6b8280dd01 Mon Sep 17 00:00:00 2001 From: Sebastian Holzapfel Date: Wed, 15 Nov 2023 18:01:54 +0100 Subject: [PATCH] add unit test for drawing to fake image --- firmware/litex-fw/Cargo.lock | 290 ++++++++++++++++++++++++++++++++++ firmware/litex-fw/Cargo.toml | 12 ++ firmware/litex-fw/src/draw.rs | 57 +++++++ firmware/litex-fw/src/lib.rs | 5 + firmware/litex-fw/src/log.rs | 1 + firmware/litex-fw/src/main.rs | 24 +-- 6 files changed, 378 insertions(+), 11 deletions(-) create mode 100644 firmware/litex-fw/src/lib.rs diff --git a/firmware/litex-fw/Cargo.lock b/firmware/litex-fw/Cargo.lock index 50afba1..4ec92e8 100644 --- a/firmware/litex-fw/Cargo.lock +++ b/firmware/litex-fw/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.0.3" @@ -53,18 +59,84 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "critical-section" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "defmt" version = "0.3.5" @@ -146,6 +218,41 @@ dependencies = [ "nb 1.1.0", ] +[[package]] +name = "exr" +version = "1.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "float-cmp" version = "0.9.0" @@ -155,6 +262,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin 0.9.8", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -165,6 +281,25 @@ dependencies = [ "version_check", ] +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + [[package]] name = "hash32" version = "0.2.1" @@ -194,6 +329,25 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "image" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", + "qoi", + "tiff", +] + [[package]] name = "irq" version = "0.2.3" @@ -209,6 +363,15 @@ dependencies = [ "either", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +dependencies = [ + "rayon", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -218,6 +381,12 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "litex-fw" version = "0.1.0" @@ -227,6 +396,7 @@ dependencies = [ "embedded-graphics", "embedded-midi", "heapless", + "image", "irq", "lazy_static", "litex-hal", @@ -282,6 +452,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "micromath" version = "2.0.0" @@ -303,6 +482,16 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef0bbe5256e5c434947d790788426bb65773502784aed7b23408f7e7fb4d8eb5" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + [[package]] name = "nb" version = "0.1.3" @@ -318,6 +507,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -333,6 +543,19 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "png" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -366,6 +589,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + [[package]] name = "quote" version = "1.0.32" @@ -381,6 +613,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211" +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "regex" version = "1.9.3" @@ -481,6 +733,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + [[package]] name = "spin" version = "0.5.2" @@ -576,6 +840,17 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "tiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "typenum" version = "1.17.0" @@ -638,3 +913,18 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/firmware/litex-fw/Cargo.toml b/firmware/litex-fw/Cargo.toml index 5e4ac7a..42db155 100644 --- a/firmware/litex-fw/Cargo.toml +++ b/firmware/litex-fw/Cargo.toml @@ -3,6 +3,14 @@ name = "litex-fw" version = "0.1.0" edition = "2021" +[lib] +name = "polyvec_lib" +path = "src/lib.rs" + +[[bin]] +name = "polyvec_main" +path = "src/main.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -27,6 +35,10 @@ critical-section = "1.1.2" strum_macros = "0.25.3" strum = {version = "0.25.0", features = ["derive"], default-features=false} +[dev-dependencies] +critical-section = { version = "1.1.2", features = ["std"] } +image = "0.24.7" + [profile.release] lto = true opt-level = 3 diff --git a/firmware/litex-fw/src/draw.rs b/firmware/litex-fw/src/draw.rs index 674bc83..9023a14 100644 --- a/firmware/litex-fw/src/draw.rs +++ b/firmware/litex-fw/src/draw.rs @@ -233,3 +233,60 @@ where Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + + use image::{ImageBuffer, RgbImage, Rgb}; + use image::imageops::{rotate90, resize, FilterType}; + + struct FakeDisplay { + img: RgbImage, + } + + impl DrawTarget for FakeDisplay { + type Color = Gray4; + type Error = core::convert::Infallible; + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for Pixel(coord, color) in pixels.into_iter() { + if let Ok((x @ 0..=63, y @ 0..=255)) = coord.try_into() { + *self.img.get_pixel_mut(y, 63-x) = Rgb([ + color.luma()<<5, + color.luma()<<5, + 0 + ]); + } + } + + Ok(()) + } + } + + impl OriginDimensions for FakeDisplay { + fn size(&self) -> Size { + Size::new(64, 64) + } + } + + #[test] + fn draw_screen() { + let mut disp = FakeDisplay { + img: ImageBuffer::new(256, 64) + }; + let opts = opt::Options::new(); + let voices = VoiceManager::new().voices; + let scope_samples = [0i16; 64]; + + draw_main(&mut disp, opts, voices, &scope_samples, 1, 2).unwrap(); + + let rot = rotate90(&disp.img); + let rz = resize(&rot, 64*4, 256*4, FilterType::Nearest); + + rz.save("test.png").unwrap(); + } +} diff --git a/firmware/litex-fw/src/lib.rs b/firmware/litex-fw/src/lib.rs new file mode 100644 index 0000000..4f77616 --- /dev/null +++ b/firmware/litex-fw/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +pub mod voice; +pub mod opt; +pub mod draw; diff --git a/firmware/litex-fw/src/log.rs b/firmware/litex-fw/src/log.rs index 72eee68..4f9aead 100644 --- a/firmware/litex-fw/src/log.rs +++ b/firmware/litex-fw/src/log.rs @@ -12,6 +12,7 @@ litex_hal::uart! { static mut UART_WRITER: Option = None; +#[cfg(not(test))] #[panic_handler] fn panic(panic_info: &PanicInfo) -> ! { if let Some(location) = panic_info.location() { diff --git a/firmware/litex-fw/src/main.rs b/firmware/litex-fw/src/main.rs index 49c1a2c..0d3cdf6 100644 --- a/firmware/litex-fw/src/main.rs +++ b/firmware/litex-fw/src/main.rs @@ -18,15 +18,14 @@ use litex_interrupt::return_as_is; use ssd1322 as oled; -mod log; -mod voice; -mod gw; -mod opt; -mod draw; +use polyvec_lib::voice::*; +use polyvec_lib::draw; +use polyvec_lib::opt; -use voice::*; -use gw::*; -use log::*; +mod gw; +mod log; +use crate::gw::*; +use crate::log::*; const N_VOICES: usize = 4; const SCOPE_SAMPLES: usize = 256; @@ -251,9 +250,12 @@ impl State { } fn fence() { - unsafe { - asm!("fence iorw, iorw"); - asm!(".word(0x500F)"); + #[cfg(not(test))] + { + unsafe { + asm!("fence iorw, iorw"); + asm!(".word(0x500F)"); + } } }