From 36484f1735efb7143dfd0bb80102bb101905b894 Mon Sep 17 00:00:00 2001 From: CanadianBaconBoi Date: Sat, 10 May 2025 22:37:10 +0200 Subject: [PATCH] Major Rewrite No more blinking :D --- Cargo.toml | 7 ++- diagram.json | 44 +++++++------- src/display/screens.rs | 3 +- src/display/screens/base.rs | 60 ++++++++----------- src/display/screens/error.rs | 14 ++--- src/display/screens/home.rs | 14 ++--- src/display/screens/macros.rs | 45 ++++++-------- src/display/screens/prelude.rs | 9 --- src/display/screens/success.rs | 14 ++++- src/display/tools.rs | 59 ++++++++---------- src/main.rs | 106 ++++++++++++++++++++++++--------- 11 files changed, 198 insertions(+), 177 deletions(-) delete mode 100644 src/display/screens/prelude.rs diff --git a/Cargo.toml b/Cargo.toml index 63a6d22..125187f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,11 @@ debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" [features] -default = [] +default = [ + "mipidsi/heapless", + "embedded-graphics/defmt", + "embedded-hal/defmt-03", +] experimental = ["esp-idf-svc/experimental"] @@ -29,6 +33,7 @@ mipidsi = "0.9.0" anyhow = "1.0.98" embedded-graphics = "0.8.1" embedded-hal = "1.0.0" +defmt = "1.0.1" [build-dependencies] embuild = "0.33" diff --git a/diagram.json b/diagram.json index b9035cf..446898f 100644 --- a/diagram.json +++ b/diagram.json @@ -1,34 +1,30 @@ { "version": 1, + "author": "Justin hei Eusebio", "editor": "wokwi", - "author": "CanadianBaconBoi ", "parts": [ { "type": "board-esp32-devkit-c-v4", "id": "esp", - "top": 0.59, - "left": 0.67, - "attrs": { - "flashSize": "16" - } - } + "top": -19.38, + "left": -158.63, + "attrs": {} + }, + { "type": "wokwi-ili9341", "id": "lcd1", "top": -81, "left": 88.1, "rotate": 90, "attrs": {} } ], "connections": [ - [ - "esp:TX", - "$serialMonitor:RX", - "", - [] - ], - [ - "esp:RX", - "$serialMonitor:TX", - "", - [] - ] + [ "esp:TX", "$serialMonitor:RX", "", [] ], + [ "esp:RX", "$serialMonitor:TX", "", [] ], + [ "lcd1:VCC", "esp:5V", "red", [ "h-17.2", "v-72.2", "h-174.8", "v225.8" ] ], + [ "lcd1:GND", "esp:GND.2", "black", [ "h-38.4", "v-28.8" ] ], + [ "lcd1:MOSI", "esp:19", "Yellow", [ "h-28.8", "v172.79", "h-182.4", "v-86.4" ] ], + [ "lcd1:RST", "esp:23", "Yellow", [ "h-28.8", "v172.79", "h-182.4", "v-86.4" ] ], + [ "lcd1:LED", "esp:4", "Yellow", [ "h-28.8", "v172.79", "h-182.4", "v-86.4" ] ], + [ "lcd1:MISO", "esp:21", "Yellow", [ "h-28.8", "v172.79", "h-182.4", "v-86.4" ] ], + [ "lcd1:SCK", "esp:18", "White", [ "h-19.2", "v172.79", "h-182.4", "v-86.4" ] ], + [ "lcd1:RST", "esp:23", "Blue", [ "h-48", "v-76.8", "h-163.2", "v96" ] ], + [ "lcd1:CS", "esp:5", "Orange", [ "h-28.8", "v-76.8", "h-172.8", "v76.8" ] ], + [ "lcd1:D/C", "esp:16", "green", [ "h-57.6", "v-134.4", "h-163.2", "v163.2" ] ] ], - "serialMonitor": { - "display": "terminal", - "convertEol": true - } -} + "dependencies": {} +} \ No newline at end of file diff --git a/src/display/screens.rs b/src/display/screens.rs index 44a06b2..e47b939 100644 --- a/src/display/screens.rs +++ b/src/display/screens.rs @@ -2,5 +2,4 @@ pub mod base; pub mod home; pub mod success; pub mod error; -pub mod macros; -mod prelude; \ No newline at end of file +pub mod macros; \ No newline at end of file diff --git a/src/display/screens/base.rs b/src/display/screens/base.rs index cdab2da..a97fef4 100644 --- a/src/display/screens/base.rs +++ b/src/display/screens/base.rs @@ -1,71 +1,61 @@ +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::framebuffer::Framebuffer; use embedded_graphics::geometry::{Point, Size}; -use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::pixelcolor::{PixelColor, RgbColor}; use embedded_graphics::primitives::CornerRadii; -use embedded_hal::digital::OutputPin; -use mipidsi::interface::InterfacePixelFormat; use crate::display::tools::DrawTools; -use crate::{W, H}; use crate::display::theme::MACCHIATO; +use crate::{H_I, W_I}; -pub trait DisplayScreen +pub trait DisplayScreen where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into, Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget { - fn show(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error>; - fn input(button: ButtonPosition) -> anyhow::Result<(), DI::Error> { + fn show(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer::Raw, BO, WIDTH, HEIGHT, N>) -> anyhow::Result<(), as DrawTarget>::Error>; + fn input(button: ButtonPosition) -> anyhow::Result<(), as embedded_graphics::draw_target::DrawTarget>::Error> { Ok(()) } } pub struct StandardBase; -impl DisplayScreen for StandardBase +impl DisplayScreen for StandardBase where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into, Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget { - fn show(_index: &mut usize, _frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer::Raw, BO, WIDTH, HEIGHT, N>) -> anyhow::Result<(), as DrawTarget>::Error> + { if *dirty { - display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W, H), MACCHIATO.crust)?; - display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W -10, H -10), MACCHIATO.mantle, CornerRadii::new(Size::new(10, 10)))?; + display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W_I, H_I), MACCHIATO.crust.into())?; + display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W_I - 10, H_I - 10), MACCHIATO.mantle.into(), CornerRadii::new(Size::new(10, 10)))?; } Ok(()) } } pub struct ErrorBase; -impl DisplayScreen for ErrorBase +impl DisplayScreen for ErrorBase where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into, Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget { - fn show(_index: &mut usize, _frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer::Raw, BO, WIDTH, HEIGHT, N>) -> anyhow::Result<(), as DrawTarget>::Error> { if *dirty { - display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W, H), MACCHIATO.maroon)?; - display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W -10, H -10), MACCHIATO.mantle, CornerRadii::new(Size::new(10, 10)))?; + display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W_I, H_I), MACCHIATO.maroon.into())?; + display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W_I-10, H_I-10), MACCHIATO.mantle.into(), CornerRadii::new(Size::new(10, 10)))?; + } Ok(()) } } pub struct SuccessBase; -impl DisplayScreen for SuccessBase +impl DisplayScreen for SuccessBase where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into, Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget { - fn show(_index: &mut usize, _frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer::Raw, BO, WIDTH, HEIGHT, N>) -> anyhow::Result<(), as DrawTarget>::Error> { if *dirty { - display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W, H), MACCHIATO.green)?; - display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W -10, H -10), MACCHIATO.mantle, CornerRadii::new(Size::new(10, 10)))?; + display.draw_rectangle_bounds(Point::new(0, 0), Point::new(W_I, H_I), MACCHIATO.green.into())?; + display.draw_rounded_rectangle_bounds(Point::new(10, 10), Point::new(W_I-10, H_I-10), MACCHIATO.mantle.into(), CornerRadii::new(Size::new(10, 10)))?; } Ok(()) } diff --git a/src/display/screens/error.rs b/src/display/screens/error.rs index 495a783..cdd4132 100644 --- a/src/display/screens/error.rs +++ b/src/display/screens/error.rs @@ -1,16 +1,16 @@ -use crate::{error_screen, FRAMERATE, H, W}; +use crate::{error_screen, FRAMERATE, H_I, W_I}; use crate::display::screens::base::{ButtonPosition, ErrorBase}; use crate::DisplayScreen; -use mipidsi::models::Model; -use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::Point; -use mipidsi::interface::InterfacePixelFormat; -use embedded_hal::digital::OutputPin; use crate::display::tools::DrawTools; +use embedded_graphics::pixelcolor::PixelColor; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::framebuffer::Framebuffer; +use embedded_graphics::pixelcolor::RgbColor; -error_screen!(ErrorScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display<_, _, _>|->anyhow::Result<(), _> { +error_screen!(ErrorScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer<_, _, _, WIDTH, HEIGHT, N>|->anyhow::Result<(), _> { if *dirty { - display.draw_text_centered(Point::new(W/2, H/2), "Error!")?; + display.draw_text_centered(Point::new(W_I/2, H_I/2), "Error!")?; *dirty = false; } else if *frame_counter % FRAMERATE*4 == 0 { #[cfg(debug_assertions)] diff --git a/src/display/screens/home.rs b/src/display/screens/home.rs index 2bb58eb..11fa8e3 100644 --- a/src/display/screens/home.rs +++ b/src/display/screens/home.rs @@ -1,16 +1,16 @@ +use embedded_graphics::framebuffer::Framebuffer; use embedded_graphics::geometry::Point; -use crate::{standard_screen, FRAMERATE, H, W}; +use crate::{standard_screen, FRAMERATE, H_I, W_I}; use crate::display::screens::base::{ButtonPosition, StandardBase}; use crate::DisplayScreen; -use mipidsi::models::Model; -use embedded_graphics::pixelcolor::Rgb565; -use mipidsi::interface::InterfacePixelFormat; -use embedded_hal::digital::OutputPin; use crate::display::tools::DrawTools; +use embedded_graphics::pixelcolor::PixelColor; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::pixelcolor::RgbColor; -standard_screen!(StandardScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display<_, _, _>|->anyhow::Result<(), _> { +standard_screen!(StandardScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer<_, _, _, WIDTH, HEIGHT, N>|->anyhow::Result<(), _> { if *dirty { - display.draw_text_centered(Point::new(W/2, H/2), "Standard!")?; + display.draw_text_centered(Point::new(W_I/2, H_I/2), "Standard!")?; *dirty = false; } else if *frame_counter % FRAMERATE*4 == 0 { #[cfg(debug_assertions)] diff --git a/src/display/screens/macros.rs b/src/display/screens/macros.rs index c97682f..4afcee8 100644 --- a/src/display/screens/macros.rs +++ b/src/display/screens/macros.rs @@ -2,21 +2,18 @@ macro_rules! standard_screen { ( $name: ident, $show: expr, $input: expr ) => { pub struct $name; - impl DisplayScreen for $name - where - DI: mipidsi::interface::Interface, - M: Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin { + impl + Into, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> DisplayScreen for $name + where Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget + { #[inline] - fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut embedded_graphics::framebuffer::Framebuffer) -> anyhow::Result<(), as DrawTarget>::Error> { StandardBase::show(idex, frame_counter, dirty, display)?; $show(idex, frame_counter, dirty, display) } #[inline] - fn input(button: ButtonPosition) { - $input(button); + fn input(button: ButtonPosition) -> anyhow::Result<(), as DrawTarget>::Error> { + $input(button) } } }; @@ -26,21 +23,18 @@ macro_rules! standard_screen { macro_rules! error_screen { ( $name: ident, $show: expr, $input: expr ) => { pub struct $name; - impl DisplayScreen for $name - where - DI: mipidsi::interface::Interface, - M: Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin { + impl + Into, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> DisplayScreen for $name + where Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget + { #[inline] - fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut embedded_graphics::framebuffer::Framebuffer) -> anyhow::Result<(), as DrawTarget>::Error> { ErrorBase::show(idex, frame_counter, dirty, display)?; $show(idex, frame_counter, dirty, display) } #[inline] - fn input(button: ButtonPosition) { - $input(button); + fn input(button: ButtonPosition) -> anyhow::Result<(), as DrawTarget>::Error> { + $input(button) } } }; @@ -50,21 +44,18 @@ macro_rules! error_screen { macro_rules! success_screen { ( $name: ident, $show: expr, $input: expr ) => { pub struct $name; - impl DisplayScreen for $name - where - DI: mipidsi::interface::Interface, - M: Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin { + impl + Into, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> DisplayScreen for $name + where Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget + { #[inline] - fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display) -> anyhow::Result<(), DI::Error> { + fn show(idex: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut embedded_graphics::framebuffer::Framebuffer) -> anyhow::Result<(), as DrawTarget>::Error> { SuccessBase::show(idex, frame_counter, dirty, display)?; $show(idex, frame_counter, dirty, display) } #[inline] - fn input(button: ButtonPosition) { - $input(button); + fn input(button: ButtonPosition) -> anyhow::Result<(), as DrawTarget>::Error> { + $input(button) } } }; diff --git a/src/display/screens/prelude.rs b/src/display/screens/prelude.rs deleted file mode 100644 index 62db7e0..0000000 --- a/src/display/screens/prelude.rs +++ /dev/null @@ -1,9 +0,0 @@ -use embedded_graphics::geometry::Point; -use crate::{success_screen, FRAMERATE, H, W}; -use crate::display::screens::base::{ButtonPosition, SuccessBase}; -use crate::DisplayScreen; -use mipidsi::models::Model; -use embedded_graphics::pixelcolor::Rgb565; -use mipidsi::interface::InterfacePixelFormat; -use embedded_hal::digital::OutputPin; -use crate::display::tools::DrawTools; \ No newline at end of file diff --git a/src/display/screens/success.rs b/src/display/screens/success.rs index ef4b4ec..7c58682 100644 --- a/src/display/screens/success.rs +++ b/src/display/screens/success.rs @@ -1,8 +1,16 @@ -use crate::display::screens::prelude; +use embedded_graphics::framebuffer::{Framebuffer}; +use crate::{success_screen, FRAMERATE, H_I, W_I}; +use crate::display::screens::base::{ButtonPosition, SuccessBase}; +use crate::DisplayScreen; +use embedded_graphics::pixelcolor::{PixelColor}; +use embedded_graphics::prelude::Point; +use crate::display::tools::DrawTools; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::pixelcolor::RgbColor; -success_screen!(SuccessScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut mipidsi::Display<_, _, _>|->anyhow::Result<(), _> { +success_screen!(SuccessScreen, |index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer<_, _, _, WIDTH, HEIGHT, N>|->anyhow::Result<(), _> { if *dirty { - display.draw_text_centered(Point::new(W/2, H/2), "Success!")?; + display.draw_text_centered(Point::new(W_I/2, H_I/2), "Success!")?; *dirty = false; } else if *frame_counter % FRAMERATE*4 == 0 { #[cfg(debug_assertions)] diff --git a/src/display/tools.rs b/src/display/tools.rs index 2c7c14c..29f2ec2 100644 --- a/src/display/tools.rs +++ b/src/display/tools.rs @@ -1,72 +1,65 @@ use embedded_graphics::draw_target::DrawTarget; use embedded_graphics::Drawable; +use embedded_graphics::framebuffer::Framebuffer; use embedded_graphics::geometry::{Point, Size}; use embedded_graphics::mono_font::MonoTextStyle; -use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::pixelcolor::{PixelColor, Rgb565}; +use embedded_graphics::prelude::RgbColor; use embedded_graphics::primitives::{CornerRadii, PrimitiveStyle, Rectangle, RoundedRectangle, StyledDrawable}; use embedded_graphics::text::Text; -use embedded_hal::digital::OutputPin; -use mipidsi::Display; -use mipidsi::interface::InterfacePixelFormat; use crate::display::theme::MACCHIATO; -pub trait DrawTools +pub trait DrawTools where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into, + Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget, { - fn draw_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: M::ColorFormat) -> anyhow::Result<(), DI::Error>; - fn draw_rectangle_top_left(&mut self, top_left: Point, size: Size, color: M::ColorFormat) -> anyhow::Result<(), DI::Error>; - fn draw_rectangle_center(&mut self, center: Point, size: Size, color: M::ColorFormat) -> anyhow::Result<(), DI::Error>; + fn draw_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: C) -> anyhow::Result<(), as DrawTarget>::Error>; + fn draw_rectangle_top_left(&mut self, top_left: Point, size: Size, color: C) -> anyhow::Result<(), as DrawTarget>::Error>; + fn draw_rectangle_center(&mut self, center: Point, size: Size, color: C) -> anyhow::Result<(), as DrawTarget>::Error>; - fn draw_rounded_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error>; - fn draw_rounded_rectangle_top_left(&mut self, top_left: Point, size: Size, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error>; - fn draw_rounded_rectangle_center(&mut self, center: Point, size: Size, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error>; + fn draw_rounded_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error>; + fn draw_rounded_rectangle_top_left(&mut self, top_left: Point, size: Size, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error>; + fn draw_rounded_rectangle_center(&mut self, center: Point, size: Size, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error>; - fn draw_text_centered(&mut self, center: Point, text: &str) -> anyhow::Result<(), DI::Error>; + fn draw_text_centered(&mut self, center: Point, text: &str) -> anyhow::Result<(), as DrawTarget>::Error>; } - -impl DrawTools for Display +impl DrawTools for Framebuffer where - DI: mipidsi::interface::Interface, - M: mipidsi::models::Model, - M::ColorFormat: InterfacePixelFormat, - RST: OutputPin, + C: RgbColor + From + Into + Copy, + Framebuffer::Raw, BO, WIDTH, HEIGHT, N>: DrawTarget, { - fn draw_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: M::ColorFormat) -> anyhow::Result<(), DI::Error> { + fn draw_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: C) -> anyhow::Result<(), as DrawTarget>::Error> { self.draw_rectangle_top_left(top_left, Size::new((bottom_right.x - top_left.x) as u32, (bottom_right.y - top_left.y) as u32), color) } - fn draw_rectangle_top_left(&mut self, top_left: Point, size: Size, color: M::ColorFormat) -> anyhow::Result<(), DI::Error> { + fn draw_rectangle_top_left(&mut self, top_left: Point, size: Size, color: C) -> anyhow::Result<(), as DrawTarget>::Error> { self.fill_solid(&Rectangle::new(top_left, size), color) } - fn draw_rectangle_center(&mut self, center: Point, size: Size, color: M::ColorFormat) -> anyhow::Result<(), DI::Error> { + fn draw_rectangle_center(&mut self, center: Point, size: Size, color: C) -> anyhow::Result<(), as DrawTarget>::Error> { self.draw_rectangle_top_left(center - Point::new((size.width / 2) as i32, (size.height / 2) as i32), size, color) } - fn draw_rounded_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error> { + fn draw_rounded_rectangle_bounds(&mut self, top_left: Point, bottom_right: Point, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error> { self.draw_rounded_rectangle_top_left(top_left, Size::new((bottom_right.x - top_left.x) as u32, (bottom_right.y - top_left.y) as u32), color, corner_radii) } - fn draw_rounded_rectangle_top_left(&mut self, top_left: Point, size: Size, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error> { + fn draw_rounded_rectangle_top_left(&mut self, top_left: Point, size: Size, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error> { let rectangle = Rectangle::new(top_left, size); let rounded_rectangle = RoundedRectangle::new(rectangle, corner_radii); rounded_rectangle.draw_styled(&PrimitiveStyle::with_fill(color), self) } - fn draw_rounded_rectangle_center(&mut self, center: Point, size: Size, color: M::ColorFormat, corner_radii: CornerRadii) -> anyhow::Result<(), DI::Error> { + fn draw_rounded_rectangle_center(&mut self, center: Point, size: Size, color: C, corner_radii: CornerRadii) -> anyhow::Result<(), as DrawTarget>::Error> { self.draw_rounded_rectangle_top_left(center - Point::new((size.width / 2) as i32, (size.height / 2) as i32), size, color, corner_radii) } - fn draw_text_centered(&mut self, center: Point, text: &str) -> anyhow::Result<(), DI::Error> { - Text::new(text, center - Point::new((text.len()*5) as i32, -10), TEXT_STYLE).draw(self)?; + fn draw_text_centered(&mut self, center: Point, text: &str) -> anyhow::Result<(), as DrawTarget>::Error> { + let text_style: MonoTextStyle = MonoTextStyle::new(&embedded_graphics::mono_font::ascii::FONT_10X20, MACCHIATO.text.into()); + Text::new(text, center - Point::new((text.len()*5) as i32, -10), text_style).draw(self)?; Ok(()) } -} - -static TEXT_STYLE: MonoTextStyle = MonoTextStyle::new(&embedded_graphics::mono_font::ascii::FONT_10X20, MACCHIATO.text); \ No newline at end of file +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 69e75c4..aa2281b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,71 @@ +///#region Imports mod display; use std::{ thread, time::Duration }; +use embedded_graphics::{ + framebuffer::{ + buffer_size, + Framebuffer + }, + pixelcolor::{ + PixelColor, + Rgb565 + } +}; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::image::ImageDrawable; +use embedded_graphics::pixelcolor::raw::BigEndian; +use embedded_graphics::pixelcolor::RgbColor; use esp_idf_svc::hal::{ delay::Ets, - gpio::{Gpio16, Gpio18, Gpio19, Gpio20, Gpio23, Gpio4, Gpio5, PinDriver}, + gpio::{Gpio16, Gpio18, Gpio19, Gpio20, Gpio21, Gpio23, Gpio4, Gpio5, PinDriver}, peripherals::Peripherals, - spi::{config, SpiDeviceDriver, SpiDriverConfig}, + spi::{ + config, + SpiDeviceDriver, + SpiDriverConfig}, spi::config::MODE_3, units::* }; -use mipidsi::{Builder, interface::SpiInterface, models::{ST7789}, options::{ColorInversion, Orientation}}; -use mipidsi::options::{ColorOrder, Rotation}; -use crate::display::screens::base::DisplayScreen; -use crate::display::screens::error::ErrorScreen; -use crate::display::screens::home::StandardScreen; -use crate::display::screens::success::SuccessScreen; +use mipidsi::{Builder, interface::SpiInterface, models::ST7789, options::{ + Orientation, + ColorOrder, + Rotation, + ColorInversion +}}; +use crate::display::screens::{ + base::DisplayScreen, + error::ErrorScreen, + home::StandardScreen, + success::SuccessScreen +}; +///#endregion +///#region Constants // Display -const H: i32 = 135; +const H: usize = 135; +const H_I: i32 = 135; const X_OFF: i32 = 52; -const W: i32 = 240; +const W: usize = 240; +const W_I: i32 = 240; const Y_OFF: i32 = 40; const FRAMERATE: usize = 30; -static mut BUFFER: [u8; (H * W) as usize] = [0u8; (H * W) as usize]; +type ScreenHolder = [fn(index: &mut usize, frame_counter: &mut usize, dirty: &mut bool, display: &mut Framebuffer) -> anyhow::Result<(), as DrawTarget>::Error>; X]; + +const SCREENS: ScreenHolder(W, H)}, 3> = [ + SuccessScreen::show, + StandardScreen::show, + ErrorScreen::show +]; + +static mut DISPLAYBUFFER: [u8; W*H] = [0; W*H]; +static mut FRAMEBUFFER: Framebuffer::Raw, BigEndian, {W}, {H}, { buffer_size::(W, H) }> = Framebuffer::new(); + +//#endregion fn main() -> anyhow::Result<()> { let peripherals: Peripherals = Peripherals::take()?; @@ -35,16 +74,12 @@ fn main() -> anyhow::Result<()> { let pin_bl: Gpio4 = peripherals.pins.gpio4; let pin_sclk: Gpio18 = peripherals.pins.gpio18; let pin_mosi: Gpio19 = peripherals.pins.gpio19; + #[cfg(debug_assertions)] + let pin_miso: Gpio21 = peripherals.pins.gpio21; + #[cfg(not(debug_assertions))] let pin_miso: Gpio20 = peripherals.pins.gpio20; let pin_cs: Gpio5 = peripherals.pins.gpio5; - let screens: Vec) -> anyhow::Result<(), _>> = vec!( - StandardScreen::show, - ErrorScreen::show, - SuccessScreen::show, - ); - - unsafe { esp_idf_svc::sys::link_patches(); esp_idf_svc::log::EspLogger::initialize_default(); @@ -72,8 +107,21 @@ fn main() -> anyhow::Result<()> { )?; // display interface abstraction from SPI and DC - let di = SpiInterface::new(device, PinDriver::output(pin_dc)?, &mut *&raw mut BUFFER); + let di = SpiInterface::new(device, PinDriver::output(pin_dc)?, &mut *&raw mut DISPLAYBUFFER); + + #[cfg(debug_assertions)] + // create driver + let mut display = Builder::new(ST7789, di) + .display_size(H as u16, W as u16) + .orientation(Orientation::new().flip_horizontal().rotate(Rotation::Deg90)) + .reset_pin(PinDriver::output(pin_rst)?) + .color_order(ColorOrder::Bgr) + .display_offset(X_OFF as u16, Y_OFF as u16) + .init(&mut delay) + .unwrap(); + + #[cfg(not(debug_assertions))] // create driver let mut display = Builder::new(ST7789, di) .display_size(H as u16, W as u16) @@ -85,25 +133,25 @@ fn main() -> anyhow::Result<()> { .init(&mut delay) .unwrap(); + // turn on the backlight backlight.set_high()?; - let mut screen_index = 0; - let mut frame_counter = 0; - let mut dirty = true; + let mut screen_index: usize = 0; + let mut frame_counter: usize = 0; + let mut dirty: bool = true; + loop { - screens[screen_index](&mut screen_index, &mut frame_counter, &mut dirty, &mut display).unwrap(); + SCREENS[screen_index](&mut screen_index, &mut frame_counter, &mut dirty, &mut FRAMEBUFFER)?; - if screen_index == screens.len() { + if screen_index == SCREENS.len() { screen_index = 0; - } else if screen_index >= screens.len() + 1 { - screen_index = screens.len() - 1; + } else if screen_index >= SCREENS.len() + 1 { + screen_index = SCREENS.len() - 1; } - #[cfg(debug_assertions)] - println!("Sleeping for {}", 1000/FRAMERATE); - + FRAMEBUFFER.as_image().draw(&mut display).unwrap(); thread::sleep(Duration::from_millis((1000 / FRAMERATE) as u64)); frame_counter += 1; }