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
|
||||
ATmega328p-microcontroller) using a simple button and a 240x240 LCD display with
|
||||
the ST7789-driver over
|
||||
This project is a relatively simple slideshow running on the Adafruit Feather
|
||||
328P (an ATmega328p-microcontroller) using a simple button and a 240x240 LCD
|
||||
display with the ST7789-driver over
|
||||
[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
|
||||
the most significant being [`atmega-hal`](https://github.com/Rahix/avr-hal), a
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn black() -> Rgb565 {
|
||||
Rgb565(0, 0, 0)
|
||||
}
|
||||
|
||||
pub fn white() -> Rgb565 {
|
||||
Rgb565(255, 255, 255)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -74,17 +66,6 @@ pub struct Vec2 {
|
||||
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)]
|
||||
pub struct Color {
|
||||
pub bytes: [u8; 2],
|
||||
|
378
src/font.rs
378
src/font.rs
@ -1,375 +1,9 @@
|
||||
use core::{
|
||||
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] {
|
||||
fn letter(character: char) -> [u8; 8] {
|
||||
match character {
|
||||
'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),
|
||||
'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)
|
||||
}
|
||||
}
|
||||
'a' => [
|
||||
0b01111110, 0b01000010, 0b10000001, 0b11111111, 0b10000001, 0b10000001, 0b10000001,
|
||||
0b10000001,
|
||||
],
|
||||
_ => [0; 8],
|
||||
}
|
||||
}
|
||||
|
@ -108,8 +108,7 @@ pub fn draw_image<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
||||
y: height,
|
||||
},
|
||||
scale_factor,
|
||||
);
|
||||
Ok(())
|
||||
)
|
||||
} else {
|
||||
Err(QoiErr::InvalidMagicNumber)
|
||||
}
|
||||
@ -121,7 +120,7 @@ pub fn draw_stream<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
|
||||
position: Vec2,
|
||||
scale: Vec2,
|
||||
scale_factor: u16,
|
||||
) {
|
||||
) -> Result<(), QoiErr> {
|
||||
let scale_iter = ScaleIterator {
|
||||
iter: stream,
|
||||
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;
|
||||
display.write(Writeable::Data(&[c1, c2]));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
struct ScaleIterator<'a> {
|
||||
iter: &'a mut dyn Iterator<Item = Rgb565>,
|
||||
|
126
src/main.rs
126
src/main.rs
@ -11,21 +11,16 @@
|
||||
use core::ptr::addr_of;
|
||||
|
||||
use atmega_hal::{
|
||||
Adc, Usart, Wdt,
|
||||
adc::AdcSettings,
|
||||
delay,
|
||||
Usart,
|
||||
spi::{self, Settings},
|
||||
usart::{Baudrate, UsartOps},
|
||||
wdt::WdtOps,
|
||||
usart::Baudrate,
|
||||
};
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use panic_halt as _;
|
||||
|
||||
use crate::{
|
||||
display::{Display, Rgb565, Vec2},
|
||||
font::{draw_number, draw_text},
|
||||
graphics::{Image, LARGE_CAT_UNSAFE, draw_image},
|
||||
peripherals::{Button, Knob},
|
||||
display::{Display, Vec2},
|
||||
graphics::{Image, LARGE_CAT_UNSAFE, PRESS_BTN_UNSAFE, draw_image},
|
||||
peripherals::Button,
|
||||
};
|
||||
|
||||
mod display;
|
||||
@ -80,108 +75,35 @@ fn main() -> ! {
|
||||
|
||||
display.init();
|
||||
|
||||
let mut adc = Adc::new(dp.ADC, AdcSettings::default());
|
||||
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 len = images.len();
|
||||
|
||||
let mut delay = atmega_hal::delay::Delay::<CoreClock>::new();
|
||||
|
||||
let mut position = Vec2 { x: 10, y: 10 };
|
||||
let original_position = position.clone();
|
||||
draw_text(
|
||||
match draw_image(
|
||||
&mut serial,
|
||||
&mut Image::from(addr_of!(PRESS_BTN_UNSAFE)).iter(),
|
||||
&mut display,
|
||||
"dice:\n",
|
||||
Rgb565::white(),
|
||||
Rgb565::black(),
|
||||
&mut position,
|
||||
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;
|
||||
Vec2 { x: 0, y: 0 },
|
||||
) {
|
||||
Ok(_) => ufmt::uwriteln!(serial, "Successfully read QOI").unwrap(),
|
||||
Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(),
|
||||
}
|
||||
|
||||
loop {
|
||||
clock += 1;
|
||||
if button.poll() {
|
||||
animation = 50;
|
||||
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(
|
||||
match draw_image(
|
||||
&mut serial,
|
||||
&mut images[idx].iter(),
|
||||
&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 Image::from(addr_of!(LARGE_CAT_UNSAFE)).iter(),
|
||||
&mut display,
|
||||
Vec2 { x: 0, y: 0 },
|
||||
)
|
||||
.unwrap();
|
||||
cat_received = true;
|
||||
Vec2 { x: 0, y: 0 },
|
||||
) {
|
||||
Ok(_) => ufmt::uwriteln!(serial, "Successfully read QOI").unwrap(),
|
||||
Err(e) => ufmt::uwriteln!(serial, "Error: {:?}", e).unwrap(),
|
||||
}
|
||||
|
||||
idx = (idx + 1) % len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,10 +51,7 @@ where
|
||||
Pin<mode::Analog, T>: AdcChannel<Atmega, ADC>,
|
||||
{
|
||||
pub fn poll(&mut self) -> f32 {
|
||||
self.raw() as f32 / 1024f32
|
||||
}
|
||||
|
||||
pub fn raw(&mut self) -> u16 {
|
||||
self.pin.analog_read(&mut self.adc)
|
||||
let read = self.pin.analog_read(&mut self.adc);
|
||||
read as f32 / 1024f32
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user