rework card view to display information on all displays as intended
This commit is contained in:
Generated
+10
@@ -206,6 +206,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"pn532",
|
"pn532",
|
||||||
|
"profont",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1595,6 +1596,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profont"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "016681370a9dd6e7ddb4c1a959922fd59dc45e5ebaa5ff5b13090267898ced34"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-graphics",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.47"
|
version = "1.0.47"
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ esp-backtrace = { version = "0.19.0", features = [
|
|||||||
"println",
|
"println",
|
||||||
] }
|
] }
|
||||||
esp-radio = { version = "0.18.0", features = ["esp32s3", "wifi"] }
|
esp-radio = { version = "0.18.0", features = ["esp32s3", "wifi"] }
|
||||||
|
profont = "0.7.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
use alloc::format;
|
use alloc::format;
|
||||||
use ch1115::{Ch1115, Size128x64};
|
use ch1115::{Ch1115, Size128x64};
|
||||||
|
use core::convert::Infallible;
|
||||||
|
use core::error::Error;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use core::fmt::Display;
|
||||||
use display_interface_spi::SPIInterface;
|
use display_interface_spi::SPIInterface;
|
||||||
use embedded_hal_bus::spi::AtomicDevice;
|
use embedded_hal_bus::spi::AtomicDevice;
|
||||||
use embedded_hal_bus::util::AtomicCell;
|
use embedded_hal_bus::util::AtomicCell;
|
||||||
@@ -8,6 +12,29 @@ use esp_hal::gpio::Output;
|
|||||||
|
|
||||||
use crate::drivers::spi_bus::{DisplaySpiBus, SharedOutput, SharedReset};
|
use crate::drivers::spi_bus::{DisplaySpiBus, SharedOutput, SharedReset};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SecondaryDisplayError(ch1115::Error<Infallible>);
|
||||||
|
|
||||||
|
impl Display for SecondaryDisplayError {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SecondaryDisplayError {}
|
||||||
|
|
||||||
|
impl From<ch1115::Error<Infallible>> for SecondaryDisplayError {
|
||||||
|
fn from(value: ch1115::Error<Infallible>) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Infallible> for SecondaryDisplayError {
|
||||||
|
fn from(value: Infallible) -> Self {
|
||||||
|
Self(ch1115::Error::Pin(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type GenericSecondaryDisplay<'a, BUS, RST, DC> =
|
pub type GenericSecondaryDisplay<'a, BUS, RST, DC> =
|
||||||
Ch1115<SPIInterface<AtomicDevice<'a, BUS, Output<'a>, Delay>, DC>, RST, Size128x64>;
|
Ch1115<SPIInterface<AtomicDevice<'a, BUS, Output<'a>, Delay>, DC>, RST, Size128x64>;
|
||||||
pub type SecondaryDisplay<'a> =
|
pub type SecondaryDisplay<'a> =
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use core::error::Error;
|
||||||
use embedded_hal_bus::i2c::AtomicDevice;
|
use embedded_hal_bus::i2c::AtomicDevice;
|
||||||
use esp_hal::delay::Delay;
|
use esp_hal::delay::Delay;
|
||||||
use i2c_character_display::{CharacterDisplayPCF8574T, LcdDisplayType};
|
use i2c_character_display::{CharacterDisplayPCF8574T, LcdDisplayType};
|
||||||
@@ -48,6 +49,8 @@ pub enum TertiaryDisplayWriteError<'a> {
|
|||||||
Format(LinesError),
|
Format(LinesError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Error for TertiaryDisplayWriteError<'a> {}
|
||||||
|
|
||||||
impl<'a> From<TertiaryDisplayError<'a>> for TertiaryDisplayWriteError<'a> {
|
impl<'a> From<TertiaryDisplayError<'a>> for TertiaryDisplayWriteError<'a> {
|
||||||
fn from(value: TertiaryDisplayError<'a>) -> Self {
|
fn from(value: TertiaryDisplayError<'a>) -> Self {
|
||||||
Self::Display(value)
|
Self::Display(value)
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use core::error;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
draw_target::DrawTarget as _,
|
draw_target::DrawTarget as _,
|
||||||
pixelcolor::{Rgb565, RgbColor as _},
|
pixelcolor::{Rgb565, RgbColor as _},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::drivers::{
|
use crate::drivers::{
|
||||||
primary_lcd::PrimaryDisplay, secondary_oled::SecondaryDisplay, tertiary_lcd::TertiaryDisplay,
|
primary_lcd::{PrimaryDisplay, PrimaryDisplayError},
|
||||||
|
secondary_oled::{SecondaryDisplay, SecondaryDisplayError},
|
||||||
|
tertiary_lcd::TertiaryDisplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Outputs {
|
pub struct Outputs {
|
||||||
@@ -17,11 +21,20 @@ pub struct Outputs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Outputs {
|
impl Outputs {
|
||||||
pub fn clear_screens(&mut self) {
|
pub fn clear_screens(&mut self) -> Result<(), Box<dyn error::Error>> {
|
||||||
self.primary_display.clear(Rgb565::BLACK).unwrap();
|
self.primary_display
|
||||||
self.secondary_display_1.clear().unwrap();
|
.clear(Rgb565::BLACK)
|
||||||
// self.secondary_display_2.clear().unwrap();
|
.map_err(PrimaryDisplayError::from)?;
|
||||||
// self.secondary_display_3.clear().unwrap();
|
self.secondary_display_1
|
||||||
|
.clear()
|
||||||
|
.map_err(SecondaryDisplayError::from)?;
|
||||||
|
self.secondary_display_2
|
||||||
|
.clear()
|
||||||
|
.map_err(SecondaryDisplayError::from)?;
|
||||||
|
self.secondary_display_3
|
||||||
|
.clear()
|
||||||
|
.map_err(SecondaryDisplayError::from)?;
|
||||||
self.tertiary_display.clear().unwrap();
|
self.tertiary_display.clear().unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+133
-72
@@ -1,5 +1,7 @@
|
|||||||
use crate::display::sprite::render_sprite_onto_ili9341;
|
use crate::display::sprite::render_sprite_onto_ili9341;
|
||||||
use crate::drivers::primary_lcd::PrimaryDisplayError;
|
use crate::drivers::primary_lcd::{PrimaryDisplay, PrimaryDisplayError};
|
||||||
|
use crate::drivers::secondary_oled::{SecondaryDisplay, SecondaryDisplayError};
|
||||||
|
use crate::drivers::tertiary_lcd::{TertiaryDisplay, TertiaryDisplayWriteError};
|
||||||
use crate::navigation::navigation::NewState;
|
use crate::navigation::navigation::NewState;
|
||||||
use crate::navigation::outputs::Outputs;
|
use crate::navigation::outputs::Outputs;
|
||||||
use crate::peripherals::Peripherals;
|
use crate::peripherals::Peripherals;
|
||||||
@@ -8,14 +10,23 @@ use alloc::format;
|
|||||||
use core::error;
|
use core::error;
|
||||||
use embedded_graphics::mono_font::MonoTextStyle;
|
use embedded_graphics::mono_font::MonoTextStyle;
|
||||||
use embedded_graphics::mono_font::ascii::FONT_6X10;
|
use embedded_graphics::mono_font::ascii::FONT_6X10;
|
||||||
|
use embedded_graphics::pixelcolor::BinaryColor;
|
||||||
use embedded_graphics::pixelcolor::Rgb565;
|
use embedded_graphics::pixelcolor::Rgb565;
|
||||||
use embedded_graphics::prelude::Point;
|
use embedded_graphics::prelude::Point;
|
||||||
use embedded_graphics::prelude::RgbColor;
|
use embedded_graphics::prelude::RgbColor;
|
||||||
use embedded_graphics::text::Text;
|
use embedded_graphics::text::Text;
|
||||||
use embedded_graphics::{Drawable, geometry::Size, primitives::Rectangle};
|
use embedded_graphics::{Drawable, geometry::Size, primitives::Rectangle};
|
||||||
use embedded_graphics_core::draw_target::DrawTarget;
|
use embedded_graphics_core::draw_target::DrawTarget;
|
||||||
|
use profont::PROFONT_7_POINT;
|
||||||
|
use profont::PROFONT_18_POINT;
|
||||||
|
|
||||||
use core::future;
|
use core::future;
|
||||||
|
use embedded_graphics::geometry::Dimensions;
|
||||||
|
use embedded_text::{
|
||||||
|
TextBox,
|
||||||
|
alignment::{HorizontalAlignment, VerticalAlignment},
|
||||||
|
style::{HeightMode, TextBoxStyleBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
card::model::{Card, Palette},
|
card::model::{Card, Palette},
|
||||||
@@ -27,7 +38,118 @@ use crate::{
|
|||||||
pub struct CardView {
|
pub struct CardView {
|
||||||
pub card: Card,
|
pub card: Card,
|
||||||
}
|
}
|
||||||
|
impl CardView {
|
||||||
|
fn display_card(
|
||||||
|
&self,
|
||||||
|
primary_display: &mut PrimaryDisplay,
|
||||||
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
let background = Rectangle::new(Point::new(0, 0), Size::new(240, 320));
|
||||||
|
let bg_color = self.card.cardtype.clone().into();
|
||||||
|
|
||||||
|
let _ = primary_display.fill_solid(&background, bg_color);
|
||||||
|
// name as header
|
||||||
|
let text_style_name = MonoTextStyle::new(&PROFONT_18_POINT, Rgb565::WHITE);
|
||||||
|
let textbox_style = TextBoxStyleBuilder::new()
|
||||||
|
.height_mode(HeightMode::FitToText)
|
||||||
|
.alignment(HorizontalAlignment::Center)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let display_area = primary_display.bounding_box();
|
||||||
|
let bounds = Rectangle::new(Point::new(0, 10), Size::new(display_area.size.width, 50));
|
||||||
|
|
||||||
|
TextBox::with_textbox_style(&self.card.name, bounds, text_style_name, textbox_style)
|
||||||
|
.draw(primary_display)
|
||||||
|
.map_err(PrimaryDisplayError::from)?;
|
||||||
|
|
||||||
|
// event lower left corner
|
||||||
|
let text_style_event = MonoTextStyle::new(&PROFONT_7_POINT, Rgb565::WHITE);
|
||||||
|
|
||||||
|
let textbox_style = TextBoxStyleBuilder::new()
|
||||||
|
.height_mode(HeightMode::FitToText)
|
||||||
|
.alignment(HorizontalAlignment::Right)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let display_area = primary_display.bounding_box();
|
||||||
|
let bounds = Rectangle::new(Point::new(0, 310), Size::new(display_area.size.width, 50));
|
||||||
|
|
||||||
|
TextBox::with_textbox_style(
|
||||||
|
&format!("{}", self.card.event),
|
||||||
|
bounds,
|
||||||
|
text_style_event,
|
||||||
|
textbox_style,
|
||||||
|
)
|
||||||
|
.draw(primary_display)
|
||||||
|
.map_err(PrimaryDisplayError::from)?;
|
||||||
|
|
||||||
|
// card sprite
|
||||||
|
let palette: Palette = self.card.cardtype.clone().into();
|
||||||
|
|
||||||
|
render_sprite_onto_ili9341(
|
||||||
|
primary_display,
|
||||||
|
self.card.sprite.data.as_slice(),
|
||||||
|
&palette,
|
||||||
|
Point::new(0, 50),
|
||||||
|
240,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_trait(
|
||||||
|
&self,
|
||||||
|
secondary_display: &mut SecondaryDisplay,
|
||||||
|
trait_str: &str,
|
||||||
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
let text_style_secondary = MonoTextStyle::new(&PROFONT_18_POINT, BinaryColor::On);
|
||||||
|
|
||||||
|
let textbox_style = TextBoxStyleBuilder::new()
|
||||||
|
.height_mode(HeightMode::FitToText)
|
||||||
|
.vertical_alignment(VerticalAlignment::Middle)
|
||||||
|
.alignment(HorizontalAlignment::Justified)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let display_area = secondary_display.bounding_box();
|
||||||
|
let bounds = Rectangle::new(Point::new(0, 0), display_area.size);
|
||||||
|
|
||||||
|
TextBox::with_textbox_style(
|
||||||
|
&format!("{}", trait_str),
|
||||||
|
bounds,
|
||||||
|
text_style_secondary,
|
||||||
|
textbox_style,
|
||||||
|
)
|
||||||
|
.draw(secondary_display)
|
||||||
|
.map_err(SecondaryDisplayError::from)?;
|
||||||
|
|
||||||
|
secondary_display
|
||||||
|
.flush()
|
||||||
|
.map_err(SecondaryDisplayError::from)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_traits(
|
||||||
|
&self,
|
||||||
|
secondary_display_1: &mut SecondaryDisplay,
|
||||||
|
secondary_display_2: &mut SecondaryDisplay,
|
||||||
|
secondary_display_3: &mut SecondaryDisplay,
|
||||||
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
self.display_trait(secondary_display_1, self.card.trait1.as_str())?;
|
||||||
|
self.display_trait(secondary_display_2, self.card.trait2.as_str())?;
|
||||||
|
self.display_trait(secondary_display_3, self.card.trait3.as_str())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_secret<'a>(
|
||||||
|
&self,
|
||||||
|
tertiary_display: &mut TertiaryDisplay<'a>,
|
||||||
|
) -> Result<(), Box<dyn error::Error + 'a>> {
|
||||||
|
tertiary_display
|
||||||
|
.write(&alloc::format!("{}", self.card.secret))
|
||||||
|
.map_err(TertiaryDisplayWriteError::from)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Navigable for CardView {
|
impl Navigable for CardView {
|
||||||
fn display(
|
fn display(
|
||||||
&self,
|
&self,
|
||||||
@@ -35,82 +157,21 @@ impl Navigable for CardView {
|
|||||||
_: &Peripherals,
|
_: &Peripherals,
|
||||||
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
|
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
|
||||||
async move {
|
async move {
|
||||||
let display = &mut outputs.primary_display;
|
outputs.clear_screens()?;
|
||||||
display
|
/*Text::new(
|
||||||
.clear(Rgb565::BLACK)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
|
|
||||||
let background = Rectangle::new(Point::new(0, 0), Size::new(240, 320));
|
|
||||||
let bg_color = self.card.cardtype.clone().into();
|
|
||||||
|
|
||||||
let _ = display.fill_solid(&background, bg_color);
|
|
||||||
|
|
||||||
let style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE);
|
|
||||||
Text::new(
|
|
||||||
&format!("Name: {}", self.card.name),
|
|
||||||
Point::new(20, 240),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Type: {}", self.card.cardtype),
|
|
||||||
Point::new(20, 250),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Event: {}", self.card.event),
|
|
||||||
Point::new(20, 260),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("UUID: {}", self.card.uuid),
|
|
||||||
Point::new(20, 270),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Trait1: {}", self.card.trait1),
|
|
||||||
Point::new(20, 280),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Trait2: {}", self.card.trait2),
|
|
||||||
Point::new(20, 290),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Trait3: {}", self.card.trait3),
|
|
||||||
Point::new(20, 300),
|
|
||||||
style,
|
|
||||||
)
|
|
||||||
.draw(display)
|
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
|
||||||
Text::new(
|
|
||||||
&format!("Secret: {}", self.card.secret),
|
&format!("Secret: {}", self.card.secret),
|
||||||
Point::new(20, 310),
|
Point::new(20, 310),
|
||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
.draw(display)
|
.draw(display)
|
||||||
.map_err(PrimaryDisplayError::from)?;
|
.map_err(PrimaryDisplayError::from)?;*/
|
||||||
|
self.display_traits(
|
||||||
let palette: Palette = self.card.cardtype.clone().into();
|
&mut outputs.secondary_display_1,
|
||||||
render_sprite_onto_ili9341(
|
&mut outputs.secondary_display_2,
|
||||||
display,
|
&mut outputs.secondary_display_3,
|
||||||
self.card.sprite.data.as_slice(),
|
)?;
|
||||||
&palette,
|
self.display_secret(&mut outputs.tertiary_display)?;
|
||||||
Point::new(13, 10),
|
self.display_card(&mut outputs.primary_display)?;
|
||||||
215,
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user