Compare commits
No commits in common. "8643aa6fcc6411cda4965d938c7ca9b4d0935387" and "e6a712bb96282c62923af8033f609e47a3aa85a5" have entirely different histories.
8643aa6fcc
...
e6a712bb96
14
README.md
14
README.md
@ -1,16 +1,10 @@
|
|||||||
# Dice game
|
# Slideshow
|
||||||
|
|
||||||
This project is a simple dice-game running on the Adafruit Feather 328P (an
|
This project is a relatively simple slideshow running on the Adafruit Feather
|
||||||
ATmega328p-microcontroller) using a simple button and a 240x240 LCD display with
|
328P (an ATmega328p-microcontroller) using a simple button and a 240x240 LCD
|
||||||
the ST7789-driver over
|
display with the ST7789-driver over
|
||||||
[SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface).
|
[SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface).
|
||||||
|
|
||||||
In the game you roll a number between 1 and 10, and if you get a 10, you are
|
|
||||||
awarded a picture of a high-quality cat stored in program-memory!
|
|
||||||
|
|
||||||
This project is a direct continuation of my earlier
|
|
||||||
[slideshow](https://git.teascade.net/teascade/slideshow)
|
|
||||||
|
|
||||||
This project is written on Rust and uses a very minimal amount of libraries with
|
This project is written on Rust and uses a very minimal amount of libraries with
|
||||||
the most significant being [`atmega-hal`](https://github.com/Rahix/avr-hal), a
|
the most significant being [`atmega-hal`](https://github.com/Rahix/avr-hal), a
|
||||||
hardware abstraction layer for ATmega-microcontrollers. Images are stored in the
|
hardware abstraction layer for ATmega-microcontrollers. Images are stored in the
|
||||||
|
Binary file not shown.
@ -43,14 +43,6 @@ impl Rgb565 {
|
|||||||
Rgb565(0, 255, 255)
|
Rgb565(0, 255, 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn black() -> Rgb565 {
|
|
||||||
Rgb565(0, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn white() -> Rgb565 {
|
|
||||||
Rgb565(255, 255, 255)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn qoi_hash(&self) -> usize {
|
pub fn qoi_hash(&self) -> usize {
|
||||||
((self.0 as u32 * 3 + self.1 as u32 * 5 + self.2 as u32 * 7 + 255 * 11) % 64) as usize
|
((self.0 as u32 * 3 + self.1 as u32 * 5 + self.2 as u32 * 7 + 255 * 11) % 64) as usize
|
||||||
}
|
}
|
||||||
@ -74,17 +66,6 @@ pub struct Vec2 {
|
|||||||
pub y: u16,
|
pub y: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<u16> 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)]
|
#[derive(Default, Clone, Copy)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
pub bytes: [u8; 2],
|
pub bytes: [u8; 2],
|
||||||
|
378
src/font.rs
378
src/font.rs
@ -1,375 +1,9 @@
|
|||||||
use core::{
|
fn letter(character: char) -> [u8; 8] {
|
||||||
arch::asm,
|
|
||||||
ptr::{addr_of, null},
|
|
||||||
};
|
|
||||||
|
|
||||||
use atmega_hal::port::PinOps;
|
|
||||||
use embedded_hal::delay::DelayNs;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
display::{Display, Rgb565, Vec2},
|
|
||||||
graphics::draw_stream,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[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 COLON: [u8; 8] = [
|
|
||||||
0b01100000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000, 0b01100000,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static EMPTY: [u8; 8] = [
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_1: [u8; 8] = [
|
|
||||||
0b00011000, 0b00111000, 0b01111000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_2: [u8; 8] = [
|
|
||||||
0b11111110, 0b11110110, 0b00001100, 0b00011000, 0b00110000, 0b01100000, 0b11111111, 0b11111111,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_3: [u8; 8] = [
|
|
||||||
0b01111110, 0b10000001, 0b00011110, 0b00011110, 0b00000001, 0b10000001, 0b11111111, 0b01111110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_4: [u8; 8] = [
|
|
||||||
0b11000110, 0b11000110, 0b11000110, 0b11111111, 0b11111110, 0b00000110, 0b00000110, 0b00000110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_5: [u8; 8] = [
|
|
||||||
0b11111111, 0b11111111, 0b11000000, 0b11111100, 0b00000110, 0b11000011, 0b11111111, 0b01111110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_6: [u8; 8] = [
|
|
||||||
0b01111110, 0b11000011, 0b11000000, 0b11111110, 0b11000011, 0b11000011, 0b11000011, 0b01111110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_7: [u8; 8] = [
|
|
||||||
0b11111111, 0b11111111, 0b00000110, 0b00001100, 0b00011000, 0b00110000, 0b01100000, 0b11000000,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_8: [u8; 8] = [
|
|
||||||
0b01111110, 0b11111111, 0b11000011, 0b01111110, 0b11000011, 0b11000011, 0b11111111, 0b01111110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_9: [u8; 8] = [
|
|
||||||
0b01111110, 0b11000011, 0b11000011, 0b01111111, 0b00000011, 0b11000011, 0b11000011, 0b01111110,
|
|
||||||
];
|
|
||||||
#[unsafe(link_section = ".progmem.data")]
|
|
||||||
pub static NUM_0: [u8; 8] = [
|
|
||||||
0b01111110, 0b11000111, 0b11001011, 0b11001011, 0b11010011, 0b11010011, 0b11100011, 0b01111110,
|
|
||||||
];
|
|
||||||
|
|
||||||
fn letter(character: char) -> *const [u8; 8] {
|
|
||||||
match character {
|
match character {
|
||||||
'a' => addr_of!(A),
|
'a' => [
|
||||||
'b' => addr_of!(B),
|
0b01111110, 0b01000010, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001,
|
||||||
'c' => addr_of!(C),
|
0b10000001,
|
||||||
'd' => addr_of!(D),
|
],
|
||||||
'e' => addr_of!(E),
|
_ => [0; 8],
|
||||||
'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),
|
|
||||||
'0' => addr_of!(NUM_0),
|
|
||||||
'1' => addr_of!(NUM_1),
|
|
||||||
'2' => addr_of!(NUM_2),
|
|
||||||
'3' => addr_of!(NUM_3),
|
|
||||||
'4' => addr_of!(NUM_4),
|
|
||||||
'5' => addr_of!(NUM_5),
|
|
||||||
'6' => addr_of!(NUM_6),
|
|
||||||
'7' => addr_of!(NUM_7),
|
|
||||||
'8' => addr_of!(NUM_8),
|
|
||||||
'9' => addr_of!(NUM_9),
|
|
||||||
'!' => addr_of!(EXCLAMATION),
|
|
||||||
',' => addr_of!(COMMA),
|
|
||||||
':' => addr_of!(COLON),
|
|
||||||
_ => addr_of!(EMPTY),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_text<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|
||||||
display: &mut Display<T, DCPin, RSTPin>,
|
|
||||||
text: &str,
|
|
||||||
fg: Rgb565,
|
|
||||||
bg: Rgb565,
|
|
||||||
position: &mut Vec2,
|
|
||||||
scale: u16,
|
|
||||||
) {
|
|
||||||
let kerning = 9 * scale;
|
|
||||||
let original_x = position.x;
|
|
||||||
|
|
||||||
for line in text.split('\n') {
|
|
||||||
for word in line.split(' ') {
|
|
||||||
let word_length = word.len() as u16 * kerning;
|
|
||||||
if position.x + word_length > 240 {
|
|
||||||
position.x = original_x;
|
|
||||||
position.y += kerning;
|
|
||||||
}
|
|
||||||
|
|
||||||
for c in word.chars() {
|
|
||||||
draw_character(display, c, fg, bg, original_x, position, scale);
|
|
||||||
}
|
|
||||||
draw_character(display, ' ', fg, bg, original_x, position, scale);
|
|
||||||
}
|
|
||||||
position.y += kerning;
|
|
||||||
position.x = original_x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_character<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|
||||||
display: &mut Display<T, DCPin, RSTPin>,
|
|
||||||
character: char,
|
|
||||||
fg: Rgb565,
|
|
||||||
bg: Rgb565,
|
|
||||||
original_x: u16,
|
|
||||||
position: &mut Vec2,
|
|
||||||
scale: u16,
|
|
||||||
) {
|
|
||||||
let kerning = 9 * scale;
|
|
||||||
|
|
||||||
if position.x + kerning > 240 {
|
|
||||||
position.x = original_x;
|
|
||||||
position.y += kerning;
|
|
||||||
}
|
|
||||||
if position.y + kerning > 240 {
|
|
||||||
position.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Letter::from(character, fg, bg)
|
|
||||||
.iter()
|
|
||||||
.draw(display, *position, scale);
|
|
||||||
position.x += kerning;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_number<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|
||||||
display: &mut Display<T, DCPin, RSTPin>,
|
|
||||||
number: u32,
|
|
||||||
fg: Rgb565,
|
|
||||||
bg: Rgb565,
|
|
||||||
position: &mut Vec2,
|
|
||||||
scale: u16,
|
|
||||||
) {
|
|
||||||
if number >= 10 {
|
|
||||||
draw_number(display, number / 10, fg, bg, position, scale);
|
|
||||||
}
|
|
||||||
let character = match number % 10 {
|
|
||||||
0 => '0',
|
|
||||||
1 => '1',
|
|
||||||
2 => '2',
|
|
||||||
3 => '3',
|
|
||||||
4 => '4',
|
|
||||||
5 => '5',
|
|
||||||
6 => '6',
|
|
||||||
7 => '7',
|
|
||||||
8 => '8',
|
|
||||||
9 => '9',
|
|
||||||
_ => 'X',
|
|
||||||
};
|
|
||||||
draw_character(display, character, fg, bg, position.x, position, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Letter {
|
|
||||||
base: [u8; 8],
|
|
||||||
pub fg: Rgb565,
|
|
||||||
pub bg: Rgb565,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Letter {
|
|
||||||
pub fn from(character: char, fg: Rgb565, bg: Rgb565) -> Letter {
|
|
||||||
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> {
|
|
||||||
LetterIter {
|
|
||||||
letter: &self,
|
|
||||||
idx: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LetterIter<'a> {
|
|
||||||
letter: &'a Letter,
|
|
||||||
idx: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> LetterIter<'a> {
|
|
||||||
pub fn draw<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|
||||||
mut self,
|
|
||||||
display: &mut Display<T, DCPin, RSTPin>,
|
|
||||||
position: Vec2,
|
|
||||||
scale: u16,
|
|
||||||
) {
|
|
||||||
draw_stream(&mut self, display, position, Vec2 { x: 8, y: 8 }, scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for LetterIter<'a> {
|
|
||||||
type Item = Rgb565;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let byte_idx = self.idx / 8;
|
|
||||||
let bit_idx = 7 - (self.idx % 8);
|
|
||||||
if byte_idx >= 8 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
self.idx += 1;
|
|
||||||
let flag = (self.letter.base[byte_idx] & (1 << bit_idx)) >> bit_idx;
|
|
||||||
if flag == 1 {
|
|
||||||
Some(self.letter.fg)
|
|
||||||
} else {
|
|
||||||
Some(self.letter.bg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,7 @@ pub fn draw_image<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|||||||
y: height,
|
y: height,
|
||||||
},
|
},
|
||||||
scale_factor,
|
scale_factor,
|
||||||
);
|
)
|
||||||
Ok(())
|
|
||||||
} else {
|
} else {
|
||||||
Err(QoiErr::InvalidMagicNumber)
|
Err(QoiErr::InvalidMagicNumber)
|
||||||
}
|
}
|
||||||
@ -121,7 +120,7 @@ pub fn draw_stream<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|||||||
position: Vec2,
|
position: Vec2,
|
||||||
scale: Vec2,
|
scale: Vec2,
|
||||||
scale_factor: u16,
|
scale_factor: u16,
|
||||||
) {
|
) -> Result<(), QoiErr> {
|
||||||
let scale_iter = ScaleIterator {
|
let scale_iter = ScaleIterator {
|
||||||
iter: stream,
|
iter: stream,
|
||||||
last_row: [Rgb565::yellow(); 120],
|
last_row: [Rgb565::yellow(); 120],
|
||||||
@ -143,6 +142,8 @@ pub fn draw_stream<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
|||||||
let [c1, c2] = pixel.as_color().bytes;
|
let [c1, c2] = pixel.as_color().bytes;
|
||||||
display.write(Writeable::Data(&[c1, c2]));
|
display.write(Writeable::Data(&[c1, c2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
struct ScaleIterator<'a> {
|
struct ScaleIterator<'a> {
|
||||||
iter: &'a mut dyn Iterator<Item = Rgb565>,
|
iter: &'a mut dyn Iterator<Item = Rgb565>,
|
||||||
|
124
src/main.rs
124
src/main.rs
@ -11,21 +11,16 @@
|
|||||||
use core::ptr::addr_of;
|
use core::ptr::addr_of;
|
||||||
|
|
||||||
use atmega_hal::{
|
use atmega_hal::{
|
||||||
Adc, Usart, Wdt,
|
Usart,
|
||||||
adc::AdcSettings,
|
|
||||||
delay,
|
|
||||||
spi::{self, Settings},
|
spi::{self, Settings},
|
||||||
usart::{Baudrate, UsartOps},
|
usart::Baudrate,
|
||||||
wdt::WdtOps,
|
|
||||||
};
|
};
|
||||||
use embedded_hal::delay::DelayNs;
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{Display, Rgb565, Vec2},
|
display::{Display, Vec2},
|
||||||
font::{draw_number, draw_text},
|
graphics::{Image, LARGE_CAT_UNSAFE, PRESS_BTN_UNSAFE, draw_image},
|
||||||
graphics::{Image, LARGE_CAT_UNSAFE, draw_image},
|
peripherals::Button,
|
||||||
peripherals::{Button, Knob},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
@ -80,108 +75,35 @@ fn main() -> ! {
|
|||||||
|
|
||||||
display.init();
|
display.init();
|
||||||
|
|
||||||
let mut adc = Adc::new(dp.ADC, AdcSettings::default());
|
|
||||||
let mut button = Button::from(pins.pd5.into_pull_up_input());
|
let mut button = Button::from(pins.pd5.into_pull_up_input());
|
||||||
let mut knob = Knob {
|
|
||||||
pin: pins.pc1.into_analog_input(&mut adc),
|
|
||||||
adc,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let mut idx = 0;
|
||||||
let images = [Image::from(addr_of!(LARGE_CAT_UNSAFE))];
|
let images = [Image::from(addr_of!(LARGE_CAT_UNSAFE))];
|
||||||
|
let len = images.len();
|
||||||
|
|
||||||
let mut delay = atmega_hal::delay::Delay::<CoreClock>::new();
|
match draw_image(
|
||||||
|
&mut serial,
|
||||||
let mut position = Vec2 { x: 10, y: 10 };
|
&mut Image::from(addr_of!(PRESS_BTN_UNSAFE)).iter(),
|
||||||
let original_position = position.clone();
|
|
||||||
draw_text(
|
|
||||||
&mut display,
|
&mut display,
|
||||||
"dice:\n",
|
Vec2 { x: 0, y: 0 },
|
||||||
Rgb565::white(),
|
) {
|
||||||
Rgb565::black(),
|
Ok(_) => ufmt::uwriteln!(serial, "Successfully read QOI").unwrap(),
|
||||||
&mut position,
|
Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(),
|
||||||
3,
|
}
|
||||||
);
|
|
||||||
let number_pos = position.clone();
|
|
||||||
draw_number(
|
|
||||||
&mut display,
|
|
||||||
0,
|
|
||||||
Rgb565::white(),
|
|
||||||
Rgb565::black(),
|
|
||||||
&mut number_pos.clone(),
|
|
||||||
3,
|
|
||||||
);
|
|
||||||
let mut clock = 0u32;
|
|
||||||
let mut animation = 0;
|
|
||||||
let mut animation_reached = true;
|
|
||||||
let mut cat_received = false;
|
|
||||||
let max_number = 10;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
clock += 1;
|
|
||||||
if button.poll() {
|
if button.poll() {
|
||||||
animation = 50;
|
match draw_image(
|
||||||
animation_reached = false;
|
|
||||||
if cat_received {
|
|
||||||
display.draw_rect(
|
|
||||||
Vec2 { x: 0, y: 0 },
|
|
||||||
Vec2 { x: 240, y: 240 },
|
|
||||||
Rgb565::black().as_color(),
|
|
||||||
);
|
|
||||||
draw_text(
|
|
||||||
&mut display,
|
|
||||||
"dice:\n",
|
|
||||||
Rgb565::white(),
|
|
||||||
Rgb565::black(),
|
|
||||||
&mut original_position.clone(),
|
|
||||||
3,
|
|
||||||
);
|
|
||||||
cat_received = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if animation > 0 {
|
|
||||||
let modulo = match animation {
|
|
||||||
50..100 => 5,
|
|
||||||
20..50 => 10,
|
|
||||||
0..20 => 20,
|
|
||||||
_ => 10,
|
|
||||||
};
|
|
||||||
animation -= 1;
|
|
||||||
if animation % modulo == 0 {
|
|
||||||
let random = (((clock * 543_128) ^ 7_643_125) & 0b11111111) as f32 / 255f32;
|
|
||||||
let dice = (random * max_number as f32) as u32;
|
|
||||||
draw_number(
|
|
||||||
&mut display,
|
|
||||||
dice,
|
|
||||||
Rgb565::white(),
|
|
||||||
Rgb565::black(),
|
|
||||||
&mut number_pos.clone(),
|
|
||||||
3,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if !animation_reached {
|
|
||||||
animation_reached = true;
|
|
||||||
let random = (((clock * 543_128) ^ 7_643_125) & 0b11111111) as f32 / 255f32;
|
|
||||||
let dice = (random * max_number as f32 + 1f32) as u32;
|
|
||||||
draw_number(
|
|
||||||
&mut display,
|
|
||||||
dice,
|
|
||||||
Rgb565::white(),
|
|
||||||
Rgb565::black(),
|
|
||||||
&mut number_pos.clone(),
|
|
||||||
3,
|
|
||||||
);
|
|
||||||
|
|
||||||
if dice == max_number {
|
|
||||||
delay.delay_ms(1000);
|
|
||||||
draw_image(
|
|
||||||
&mut serial,
|
&mut serial,
|
||||||
&mut Image::from(addr_of!(LARGE_CAT_UNSAFE)).iter(),
|
&mut images[idx].iter(),
|
||||||
&mut display,
|
&mut display,
|
||||||
Vec2 { x: 0, y: 0 },
|
Vec2 { x: 0, y: 0 },
|
||||||
)
|
) {
|
||||||
.unwrap();
|
Ok(_) => ufmt::uwriteln!(serial, "Successfully read QOI").unwrap(),
|
||||||
cat_received = true;
|
Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
idx = (idx + 1) % len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,7 @@ where
|
|||||||
Pin<mode::Analog, T>: AdcChannel<Atmega, ADC>,
|
Pin<mode::Analog, T>: AdcChannel<Atmega, ADC>,
|
||||||
{
|
{
|
||||||
pub fn poll(&mut self) -> f32 {
|
pub fn poll(&mut self) -> f32 {
|
||||||
self.raw() as f32 / 1024f32
|
let read = self.pin.analog_read(&mut self.adc);
|
||||||
}
|
read as f32 / 1024f32
|
||||||
|
|
||||||
pub fn raw(&mut self) -> u16 {
|
|
||||||
self.pin.analog_read(&mut self.adc)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user