diff --git a/Cargo.lock b/Cargo.lock index 85d2ba5..a6e634c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,17 @@ dependencies = [ "unwrap-infallible", ] +[[package]] +name = "avr-progmem" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e93a9dd7da8f4eb57c912367e337687e06a8db6452d8c89eeb9eff1e0d2ba2d" +dependencies = [ + "cfg-if", + "derivative", + "ufmt", +] + [[package]] name = "az" version = "1.2.1" @@ -80,6 +91,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "embedded-graphics-core" version = "0.4.0" @@ -184,6 +206,7 @@ version = "0.1.0" dependencies = [ "atmega-hal", "avr-device", + "avr-progmem", "embedded-graphics-core", "embedded-hal 1.0.0", "panic-halt", diff --git a/Cargo.toml b/Cargo.toml index 100fde5..2ca442a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ atmega-hal = { git = "https://github.com/Rahix/avr-hal?tab=readme-ov-file", rev= ufmt = "0.2.0" embedded-graphics-core = "0.4.0" +avr-progmem = "0.4.0" # nb = "1.1.0" # pwm-pca9685 = "1.0.0" # infrared = "0.14.1" diff --git a/images/cat.qoi b/images/cat.qoi new file mode 100644 index 0000000..53b9534 Binary files /dev/null and b/images/cat.qoi differ diff --git a/src/main.rs b/src/main.rs index cee5a52..6588c17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ use panic_halt as _; use crate::{ display::{Display, Position, Rgb565}, peripherals::{Button, Knob}, - qoi::{MARIO, PIKA, PRESS_BTN, STEVE, draw_image}, + qoi::{MARIO, PRESS_BTN, draw_image}, }; mod display; @@ -78,12 +78,12 @@ fn main() -> ! { let mut button = Button::from(pins.pd5.into_pull_up_input()); let mut idx = 0; - let images = [&PIKA.as_slice(), &MARIO.as_slice(), &STEVE.as_slice()]; + let images = [&MARIO.as_slice()]; let len = images.len(); match draw_image( &mut serial, - &PIKA.as_slice(), + &MARIO.as_slice(), &mut display, Position { x: 0, y: 0 }, ) { diff --git a/src/qoi.rs b/src/qoi.rs index 3238c5d..ca987ed 100644 --- a/src/qoi.rs +++ b/src/qoi.rs @@ -8,20 +8,44 @@ use atmega_hal::{ pac::USART0, port::{PB3, PB5, PD0, PD1, Pin, PinOps, mode}, }; +use avr_progmem::{progmem, wrapper::ProgMem}; use embedded_hal::delay::DelayNs; use ufmt::derive::uDebug; use crate::{ CoreClock, display::{Color, Display, Position, Rgb565, Writeable}, + qoi, }; +progmem! { + /// Static byte stored in progmem! + static progmem P_BYTE: u8 = 42; + static progmem VERY_LARGE: [u8; 23731] = *include_bytes!("../images/cat.qoi"); +} + // https://qoiformat.org/qoi-specification.pdf pub static MARIO: [u8; 161] = *include_bytes!("../images/mario.qoi"); -pub static PIKA: [u8; 241] = *include_bytes!("../images/pikachu.qoi"); -pub static STEVE: [u8; 187] = *include_bytes!("../images/steve.qoi"); pub static PRESS_BTN: [u8; 174] = *include_bytes!("../images/press_btn.qoi"); +pub struct LargeIterator { + buffer: ProgMem<[u8; LENGTH]>, + index: usize, +} + +impl Iterator for LargeIterator { + type Item = u8; + + fn next(&mut self) -> Option { + if self.index >= LENGTH { + return None; + } + let item = self.buffer.load_at(self.index); + self.index += 1; + Some(item) + } +} + #[derive(Debug, uDebug)] pub enum QoiErr { InvalidMagicNumber, @@ -34,7 +58,12 @@ pub fn draw_image( display: &mut Display, position: Position, ) -> Result<(), QoiErr> { - let mut iter = buffer.iter().map(|b| *b); + // let mut iter = buffer.iter().map(|b| *b); + + let mut iter = LargeIterator { + buffer: VERY_LARGE, + index: 0, + }; if let (Some(113), Some(111), Some(105), Some(102)) = (iter.next(), iter.next(), iter.next(), iter.next()) @@ -73,7 +102,7 @@ pub fn draw_image( let qoi_iter = QoiIterator::from(&mut iter, width * height); let scale_iter = ScaleIterator { qoi: qoi_iter, - last_row: [Rgb565::yellow(); 64], + last_row: [Rgb565::yellow(); 120], scale_factor: scale_factor as usize, width: width as usize, counter: 0, @@ -96,7 +125,7 @@ pub fn draw_image( struct ScaleIterator<'a> { qoi: QoiIterator<'a>, - last_row: [Rgb565; 64], + last_row: [Rgb565; 120], width: usize, scale_factor: usize, counter: usize, @@ -107,6 +136,10 @@ impl<'a> Iterator for ScaleIterator<'a> { type Item = Rgb565; fn next(&mut self) -> Option { + if self.scale_factor == 1 { + return self.qoi.next(); + } + if self.index >= self.width * self.scale_factor { self.counter = (self.counter + 1) % self.scale_factor; self.index = 0;