From c78db0c81aadeb9723d42a1a191925dac63b82e7 Mon Sep 17 00:00:00 2001 From: Sofia Date: Sat, 13 Sep 2025 18:43:57 +0300 Subject: [PATCH] Store alphabet in progmem data --- src/display.rs | 11 ++ src/font.rs | 291 +++++++++++++++++++++++++++++-------------------- src/main.rs | 24 ++-- 3 files changed, 196 insertions(+), 130 deletions(-) diff --git a/src/display.rs b/src/display.rs index 43fd0ba..56464a9 100644 --- a/src/display.rs +++ b/src/display.rs @@ -74,6 +74,17 @@ pub struct Vec2 { pub y: u16, } +impl Mul for Vec2 { + type Output = Vec2; + + fn mul(self, rhs: u16) -> Self::Output { + Vec2 { + x: self.x * rhs, + y: self.y * rhs, + } + } +} + #[derive(Default, Clone, Copy)] pub struct Color { pub bytes: [u8; 2], diff --git a/src/font.rs b/src/font.rs index 2c4ee4c..d0ab594 100644 --- a/src/font.rs +++ b/src/font.rs @@ -1,3 +1,8 @@ +use core::{ + arch::asm, + ptr::{addr_of, null}, +}; + use atmega_hal::port::PinOps; use embedded_hal::delay::DelayNs; @@ -6,121 +11,154 @@ use crate::{ graphics::draw_stream, }; -fn letter(character: char) -> [u8; 8] { +#[unsafe(link_section = ".progmem.data")] +pub static A: [u8; 8] = [ + 0b01111110, 0b01000010, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001, 0b10000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static B: [u8; 8] = [ + 0b11111100, 0b10000010, 0b10000010, 0b10001100, 0b10000010, 0b10000001, 0b10000001, 0b11111110, +]; +#[unsafe(link_section = ".progmem.data")] +pub static C: [u8; 8] = [ + 0b11111110, 0b10000001, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000001, 0b11111110, +]; +#[unsafe(link_section = ".progmem.data")] +pub static D: [u8; 8] = [ + 0b11111100, 0b10000010, 0b10000010, 0b10000001, 0b10000001, 0b10000010, 0b10000010, 0b11111100, +]; +#[unsafe(link_section = ".progmem.data")] +pub static E: [u8; 8] = [ + 0b11111111, 0b10000000, 0b10000000, 0b11111000, 0b10000000, 0b10000000, 0b10000000, 0b11111111, +]; +#[unsafe(link_section = ".progmem.data")] +pub static F: [u8; 8] = [ + 0b11111111, 0b10000000, 0b10000000, 0b11111000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static G: [u8; 8] = [ + 0b11111110, 0b10000001, 0b10000000, 0b10000000, 0b10011111, 0b10010001, 0b01000010, 0b00111100, +]; +#[unsafe(link_section = ".progmem.data")] +pub static H: [u8; 8] = [ + 0b10000001, 0b10000001, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001, 0b10000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static I: [u8; 8] = [ + 0b00111100, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00111100, +]; +#[unsafe(link_section = ".progmem.data")] +pub static J: [u8; 8] = [ + 0b00001110, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b10000010, 0b10000010, 0b01111100, +]; +#[unsafe(link_section = ".progmem.data")] +pub static K: [u8; 8] = [ + 0b01000010, 0b01000100, 0b01001000, 0b01110000, 0b01001000, 0b01000100, 0b01000010, 0b01000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static L: [u8; 8] = [ + 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b11111111, +]; +#[unsafe(link_section = ".progmem.data")] +pub static M: [u8; 8] = [ + 0b00100100, 0b11011011, 0b10011001, 0b10011001, 0b10011001, 0b10000001, 0b10000001, 0b10000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static N: [u8; 8] = [ + 0b11000001, 0b10100001, 0b10010001, 0b10001001, 0b10001001, 0b10000101, 0b10000111, 0b10000011, +]; +#[unsafe(link_section = ".progmem.data")] +pub static O: [u8; 8] = [ + 0b11111111, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b11111111, +]; +#[unsafe(link_section = ".progmem.data")] +pub static P: [u8; 8] = [ + 0b11111111, 0b10000001, 0b10000001, 0b11111111, 0b10000000, 0b10000000, 0b10000000, 0b00000000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static Q: [u8; 8] = [ + 0b01111110, 0b10000001, 0b10000001, 0b10000001, 0b10001001, 0b10000101, 0b10000011, 0b01111111, +]; +#[unsafe(link_section = ".progmem.data")] +pub static R: [u8; 8] = [ + 0b11111111, 0b10000001, 0b10000001, 0b11111111, 0b11111100, 0b10000010, 0b10000001, 0b10000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static S: [u8; 8] = [ + 0b01111111, 0b10000000, 0b10000000, 0b01111110, 0b00000001, 0b00000001, 0b00000001, 0b11111110, +]; +#[unsafe(link_section = ".progmem.data")] +pub static T: [u8; 8] = [ + 0b11111111, 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static U: [u8; 8] = [ + 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b01111110, +]; +#[unsafe(link_section = ".progmem.data")] +pub static V: [u8; 8] = [ + 0b10000001, 0b10000001, 0b01000010, 0b01000010, 0b00100100, 0b00100100, 0b00100100, 0b00011000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static W: [u8; 8] = [ + 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10011001, 0b01011010, 0b00100100, 0b00100100, +]; +#[unsafe(link_section = ".progmem.data")] +pub static X: [u8; 8] = [ + 0b10000001, 0b01000010, 0b00100100, 0b00011000, 0b00011000, 0b00100100, 0b01000010, 0b10000001, +]; +#[unsafe(link_section = ".progmem.data")] +pub static Y: [u8; 8] = [ + 0b10000001, 0b01000010, 0b00100100, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static Z: [u8; 8] = [ + 0b11111111, 0b00000111, 0b00001100, 0b00011000, 0b00110000, 0b01100000, 0b11000000, 0b11111111, +]; +#[unsafe(link_section = ".progmem.data")] +pub static EXCLAMATION: [u8; 8] = [ + 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b00000000, 0b01000000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static COMMA: [u8; 8] = [ + 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b10000000, +]; +#[unsafe(link_section = ".progmem.data")] +pub static EMPTY: [u8; 8] = [ + 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, +]; + +fn letter(character: char) -> *const [u8; 8] { match character { - 'a' => [ - 0b01111110, 0b01000010, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001, - 0b10000001, - ], - 'b' => [ - 0b11111100, 0b10000010, 0b10000010, 0b10001100, 0b10000010, 0b10000001, 0b10000001, - 0b11111110, - ], - 'c' => [ - 0b11111110, 0b10000001, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000001, - 0b11111110, - ], - 'd' => [ - 0b11111100, 0b10000010, 0b10000010, 0b10000001, 0b10000001, 0b10000010, 0b10000010, - 0b11111100, - ], - 'e' => [ - 0b11111111, 0b10000000, 0b10000000, 0b11111000, 0b10000000, 0b10000000, 0b10000000, - 0b11111111, - ], - 'f' => [ - 0b11111111, 0b10000000, 0b10000000, 0b11111000, 0b10000000, 0b10000000, 0b10000000, - 0b10000000, - ], - 'g' => [ - 0b11111110, 0b10000001, 0b10000000, 0b10000000, 0b10011111, 0b10010001, 0b01000010, - 0b00111100, - ], - 'h' => [ - 0b10000001, 0b10000001, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001, - 0b10000001, - ], - 'i' => [ - 0b00111100, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, - 0b00111100, - ], - 'j' => [ - 0b00001110, 0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b10000010, 0b10000010, - 0b01111100, - ], - 'k' => [ - 0b01000010, 0b01000100, 0b01001000, 0b01110000, 0b01001000, 0b01000100, 0b01000010, - 0b01000001, - ], - 'l' => [ - 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, 0b10000000, - 0b11111111, - ], - 'm' => [ - 0b00100100, 0b11011011, 0b10011001, 0b10011001, 0b10011001, 0b10000001, 0b10000001, - 0b10000001, - ], - 'n' => [ - 0b11000001, 0b10100001, 0b10010001, 0b10001001, 0b10001001, 0b10000101, 0b10000111, - 0b10000011, - ], - 'o' => [ - 0b11111111, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, - 0b11111111, - ], - 'p' => [ - 0b11111111, 0b10000001, 0b10000001, 0b11111111, 0b10000000, 0b10000000, 0b10000000, - 0b00000000, - ], - 'q' => [ - 0b01111110, 0b10000001, 0b10000001, 0b10000001, 0b10001001, 0b10000101, 0b10000011, - 0b01111111, - ], - 'r' => [ - 0b11111111, 0b10000001, 0b10000001, 0b11111111, 0b11111100, 0b10000010, 0b10000001, - 0b10000001, - ], - 's' => [ - 0b01111111, 0b10000000, 0b10000000, 0b01111110, 0b00000001, 0b00000001, 0b00000001, - 0b11111110, - ], - 't' => [ - 0b11111111, 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000, - 0b00010000, - ], - 'u' => [ - 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, - 0b01111110, - ], - 'v' => [ - 0b10000001, 0b10000001, 0b01000010, 0b01000010, 0b00100100, 0b00100100, 0b00100100, - 0b00011000, - ], - 'w' => [ - 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10011001, 0b01011010, 0b00100100, - 0b00100100, - ], - 'x' => [ - 0b10000001, 0b01000010, 0b00100100, 0b00011000, 0b00011000, 0b00100100, 0b01000010, - 0b10000001, - ], - 'y' => [ - 0b10000001, 0b01000010, 0b00100100, 0b00011000, 0b00011000, 0b00011000, 0b00011000, - 0b00011000, - ], - 'z' => [ - 0b11111111, 0b00000111, 0b00001100, 0b00011000, 0b00110000, 0b01100000, 0b11000000, - 0b11111111, - ], - '!' => [ - 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b00000000, - 0b01000000, - ], - ',' => [ - 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000, - 0b10000000, - ], - _ => [0; 8], + 'a' => addr_of!(A), + 'b' => addr_of!(B), + 'c' => addr_of!(C), + 'd' => addr_of!(D), + 'e' => addr_of!(E), + 'f' => addr_of!(F), + 'g' => addr_of!(G), + 'h' => addr_of!(H), + 'i' => addr_of!(I), + 'j' => addr_of!(J), + 'k' => addr_of!(K), + 'l' => addr_of!(L), + 'm' => addr_of!(M), + 'n' => addr_of!(N), + 'o' => addr_of!(O), + 'p' => addr_of!(P), + 'q' => addr_of!(Q), + 'r' => addr_of!(R), + 's' => addr_of!(S), + 't' => addr_of!(T), + 'u' => addr_of!(U), + 'v' => addr_of!(V), + 'w' => addr_of!(W), + 'x' => addr_of!(X), + 'y' => addr_of!(Y), + 'z' => addr_of!(Z), + '!' => addr_of!(EXCLAMATION), + ',' => addr_of!(COMMA), + _ => addr_of!(EMPTY), } } @@ -174,11 +212,28 @@ pub struct Letter { impl Letter { pub fn from(character: char, fg: Rgb565, bg: Rgb565) -> Letter { - Letter { - base: letter(character), - fg, - bg, + let mut out = [0u8; 8]; + let out_ptr = out.as_mut_ptr(); + let ptr_addr = letter(character); + + unsafe { + asm!( + // Load value of Z to temporary register $1 and post-increment Z + "lpm {1}, Z+", + // Store value from register $1 to X and post-increment X + "st X+, {1}", + // Subtract loop counter at register $0 + "subi {0}, 1", + // If equality failed, jump back 8 bytes (or 4 instructions) + "brne -8", + inout(reg) 8u8 => _, + out(reg) _, + inout("Z") ptr_addr => _, + inout("X") out_ptr => _ + ) } + + Letter { base: out, fg, bg } } pub fn iter<'a>(&'a self) -> LetterIter<'a> { diff --git a/src/main.rs b/src/main.rs index b6e66e9..656a178 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,18 +82,7 @@ fn main() -> ! { let images = [Image::from(addr_of!(LARGE_CAT_UNSAFE))]; let len = images.len(); - // match draw_image( - // &mut serial, - // &mut Image::from(addr_of!(PRESS_BTN_UNSAFE)).iter(), - // &mut display, - // Vec2 { x: 0, y: 0 }, - // ) { - // Ok(_) => ufmt::uwriteln!(serial, "Successfully read QOI").unwrap(), - // Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(), - // } - - let letter = Letter::from('h', Rgb565::white(), Rgb565::black()); - + ufmt::uwriteln!(serial, "Drawing text").unwrap(); draw_text( &mut display, "hi,my name is adafruit!nice to meet you!", @@ -103,6 +92,8 @@ fn main() -> ! { 3, ); + ufmt::uwriteln!(serial, "Text drawn!").unwrap(); + loop { if button.poll() { match draw_image( @@ -115,6 +106,15 @@ fn main() -> ! { Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(), } + draw_text( + &mut display, + "you just lost the game!", + Rgb565::white(), + Rgb565::black(), + Vec2 { x: 10, y: 10 }, + 3, + ); + idx = (idx + 1) % len; } }