Mainmenu #28
@@ -15,7 +15,6 @@ use creaturedex::navigation::inputs::Inputs;
|
|||||||
use creaturedex::navigation::navigation;
|
use creaturedex::navigation::navigation;
|
||||||
use creaturedex::navigation::state::NavigationState;
|
use creaturedex::navigation::state::NavigationState;
|
||||||
use creaturedex::network::wifi::setup_wifi;
|
use creaturedex::network::wifi::setup_wifi;
|
||||||
use creaturedex::views::card_view::render_nfc_payload;
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use embedded_graphics::draw_target::DrawTarget;
|
use embedded_graphics::draw_target::DrawTarget;
|
||||||
|
|||||||
+187
-1
@@ -1,7 +1,10 @@
|
|||||||
|
use core::fmt::Display;
|
||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use num_enum::FromPrimitive;
|
use num_enum::FromPrimitive;
|
||||||
|
|
||||||
use crate::card::decoder::{Events, decode_known_event, decode_packed_card_text, decode_secret};
|
use crate::card::decoder::{Events, decode_known_event, decode_packed_card_text, decode_secret};
|
||||||
|
use embedded_graphics::pixelcolor::Rgb565;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct NfcPayload<'a> {
|
pub struct NfcPayload<'a> {
|
||||||
@@ -29,6 +32,189 @@ pub enum CardType {
|
|||||||
Fairy = 7,
|
Fairy = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for CardType {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match *self {
|
||||||
|
CardType::Default => write!(f, "Default"),
|
||||||
|
CardType::Blueprint => write!(f, "Blueprint"),
|
||||||
|
CardType::CYBER => write!(f, "CYBER"),
|
||||||
|
CardType::Nature => write!(f, "Nature"),
|
||||||
|
CardType::Fossil => write!(f, "Fossil"),
|
||||||
|
CardType::Ghost => write!(f, "Ghost"),
|
||||||
|
CardType::Daemon => write!(f, "Daemon"),
|
||||||
|
CardType::Fairy => write!(f, "Fairy"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PrimaryColor = Rgb565;
|
||||||
|
impl Into<PrimaryColor> for CardType {
|
||||||
|
fn into(self) -> PrimaryColor {
|
||||||
|
match self {
|
||||||
|
CardType::Default => Rgb565::new(0xD8, 0x68, 0x30),
|
||||||
|
CardType::Blueprint => Rgb565::new(0x6D, 0x81, 0xFF),
|
||||||
|
CardType::CYBER => Rgb565::new(0xFF, 0xFF, 0x04),
|
||||||
|
CardType::Nature => Rgb565::new(0x55, 0xA0, 0x58),
|
||||||
|
CardType::Fossil => Rgb565::new(0xB9, 0x7A, 0x60),
|
||||||
|
CardType::Ghost => Rgb565::new(0xAB, 0xAB, 0xAB),
|
||||||
|
CardType::Daemon => Rgb565::new(0x60, 0x00, 0x88),
|
||||||
|
CardType::Fairy => Rgb565::new(0xB0, 0xA9, 0xE4),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Palette = [Rgb565; 16];
|
||||||
|
impl Into<Palette> for CardType {
|
||||||
|
fn into(self) -> Palette {
|
||||||
|
match self {
|
||||||
|
CardType::Default => [
|
||||||
|
Rgb565::new(31, 23, 35),
|
||||||
|
Rgb565::new(60, 47, 82),
|
||||||
|
Rgb565::new(178, 39, 65),
|
||||||
|
Rgb565::new(70, 86, 165),
|
||||||
|
Rgb565::new(245, 70, 76),
|
||||||
|
Rgb565::new(216, 104, 48),
|
||||||
|
Rgb565::new(140, 127, 144),
|
||||||
|
Rgb565::new(73, 149, 243),
|
||||||
|
Rgb565::new(62, 197, 75),
|
||||||
|
Rgb565::new(240, 149, 72),
|
||||||
|
Rgb565::new(188, 176, 179),
|
||||||
|
Rgb565::new(247, 156, 136),
|
||||||
|
Rgb565::new(114, 222, 235),
|
||||||
|
Rgb565::new(180, 230, 86),
|
||||||
|
Rgb565::new(239, 208, 129),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Blueprint => [
|
||||||
|
Rgb565::new(83, 67, 127),
|
||||||
|
Rgb565::new(44, 111, 153),
|
||||||
|
Rgb565::new(142, 88, 111),
|
||||||
|
Rgb565::new(0, 188, 170),
|
||||||
|
Rgb565::new(153, 104, 226),
|
||||||
|
Rgb565::new(109, 129, 255),
|
||||||
|
Rgb565::new(255, 84, 112),
|
||||||
|
Rgb565::new(196, 143, 158),
|
||||||
|
Rgb565::new(168, 159, 204),
|
||||||
|
Rgb565::new(190, 155, 255),
|
||||||
|
Rgb565::new(255, 155, 113),
|
||||||
|
Rgb565::new(127, 206, 255),
|
||||||
|
Rgb565::new(255, 155, 182),
|
||||||
|
Rgb565::new(255, 217, 174),
|
||||||
|
Rgb565::new(255, 217, 232),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::CYBER => [
|
||||||
|
Rgb565::new(0, 0, 0),
|
||||||
|
Rgb565::new(0, 0, 126),
|
||||||
|
Rgb565::new(0, 0, 255),
|
||||||
|
Rgb565::new(126, 0, 0),
|
||||||
|
Rgb565::new(126, 0, 126),
|
||||||
|
Rgb565::new(4, 126, 0),
|
||||||
|
Rgb565::new(254, 0, 0),
|
||||||
|
Rgb565::new(4, 126, 126),
|
||||||
|
Rgb565::new(254, 0, 255),
|
||||||
|
Rgb565::new(126, 126, 0),
|
||||||
|
Rgb565::new(126, 126, 126),
|
||||||
|
Rgb565::new(6, 255, 4),
|
||||||
|
Rgb565::new(6, 255, 255),
|
||||||
|
Rgb565::new(190, 190, 190),
|
||||||
|
Rgb565::new(255, 255, 4),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Nature => [
|
||||||
|
Rgb565::new(35, 34, 40),
|
||||||
|
Rgb565::new(40, 66, 97),
|
||||||
|
Rgb565::new(30, 116, 83),
|
||||||
|
Rgb565::new(117, 77, 69),
|
||||||
|
Rgb565::new(95, 88, 84),
|
||||||
|
Rgb565::new(36, 133, 166),
|
||||||
|
Rgb565::new(198, 80, 70),
|
||||||
|
Rgb565::new(85, 160, 88),
|
||||||
|
Rgb565::new(135, 133, 115),
|
||||||
|
Rgb565::new(84, 186, 210),
|
||||||
|
Rgb565::new(161, 191, 65),
|
||||||
|
Rgb565::new(230, 146, 138),
|
||||||
|
Rgb565::new(184, 176, 149),
|
||||||
|
Rgb565::new(227, 192, 84),
|
||||||
|
Rgb565::new(195, 213, 199),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Fossil => [
|
||||||
|
Rgb565::new(75, 61, 68),
|
||||||
|
Rgb565::new(119, 66, 81),
|
||||||
|
Rgb565::new(78, 84, 99),
|
||||||
|
Rgb565::new(100, 83, 85),
|
||||||
|
Rgb565::new(156, 82, 78),
|
||||||
|
Rgb565::new(132, 109, 89),
|
||||||
|
Rgb565::new(91, 125, 115),
|
||||||
|
Rgb565::new(125, 123, 98),
|
||||||
|
Rgb565::new(140, 124, 121),
|
||||||
|
Rgb565::new(185, 122, 96),
|
||||||
|
Rgb565::new(168, 138, 94),
|
||||||
|
Rgb565::new(142, 159, 125),
|
||||||
|
Rgb565::new(170, 162, 93),
|
||||||
|
Rgb565::new(169, 156, 141),
|
||||||
|
Rgb565::new(204, 168, 123),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Ghost => [
|
||||||
|
Rgb565::new(0, 0, 0),
|
||||||
|
Rgb565::new(24, 24, 24),
|
||||||
|
Rgb565::new(40, 40, 40),
|
||||||
|
Rgb565::new(56, 56, 56),
|
||||||
|
Rgb565::new(71, 71, 71),
|
||||||
|
Rgb565::new(86, 86, 86),
|
||||||
|
Rgb565::new(100, 100, 100),
|
||||||
|
Rgb565::new(113, 113, 113),
|
||||||
|
Rgb565::new(126, 126, 126),
|
||||||
|
Rgb565::new(140, 140, 140),
|
||||||
|
Rgb565::new(155, 155, 155),
|
||||||
|
Rgb565::new(171, 171, 171),
|
||||||
|
Rgb565::new(189, 189, 189),
|
||||||
|
Rgb565::new(209, 209, 209),
|
||||||
|
Rgb565::new(231, 231, 231),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Daemon => [
|
||||||
|
Rgb565::new(0, 3, 60),
|
||||||
|
Rgb565::new(96, 0, 136),
|
||||||
|
Rgb565::new(0, 56, 132),
|
||||||
|
Rgb565::new(42, 46, 121),
|
||||||
|
Rgb565::new(0, 82, 96),
|
||||||
|
Rgb565::new(177, 5, 133),
|
||||||
|
Rgb565::new(255, 0, 78),
|
||||||
|
Rgb565::new(172, 41, 206),
|
||||||
|
Rgb565::new(0, 157, 74),
|
||||||
|
Rgb565::new(0, 138, 197),
|
||||||
|
Rgb565::new(78, 110, 168),
|
||||||
|
Rgb565::new(255, 92, 255),
|
||||||
|
Rgb565::new(10, 255, 82),
|
||||||
|
Rgb565::new(0, 247, 255),
|
||||||
|
Rgb565::new(173, 212, 250),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
CardType::Fairy => [
|
||||||
|
Rgb565::new(40, 40, 46),
|
||||||
|
Rgb565::new(108, 86, 113),
|
||||||
|
Rgb565::new(135, 168, 137),
|
||||||
|
Rgb565::new(249, 130, 132),
|
||||||
|
Rgb565::new(176, 169, 228),
|
||||||
|
Rgb565::new(222, 163, 139),
|
||||||
|
Rgb565::new(172, 204, 228),
|
||||||
|
Rgb565::new(254, 170, 228),
|
||||||
|
Rgb565::new(217, 200, 191),
|
||||||
|
Rgb565::new(255, 195, 132),
|
||||||
|
Rgb565::new(176, 235, 147),
|
||||||
|
Rgb565::new(179, 227, 218),
|
||||||
|
Rgb565::new(233, 245, 157),
|
||||||
|
Rgb565::new(255, 230, 198),
|
||||||
|
Rgb565::new(255, 247, 160),
|
||||||
|
Rgb565::new(255, 255, 255),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Sprite {
|
pub struct Sprite {
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
@@ -53,7 +239,7 @@ impl TryFrom<NfcPayload<'static>> for Card {
|
|||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
|
|
||||||
fn try_from(payload: NfcPayload) -> Result<Self, Self::Error> {
|
fn try_from(payload: NfcPayload) -> Result<Self, Self::Error> {
|
||||||
let uuid: String = str::from_utf8(payload.card_uuid).unwrap().into();
|
let uuid: String = "empty for now".into(); //str::from_utf8(payload.card_uuid).unwrap().into();
|
||||||
let event = decode_known_event(payload.event_encoding);
|
let event = decode_known_event(payload.event_encoding);
|
||||||
let cardtype = CardType::from(payload.card_type);
|
let cardtype = CardType::from(payload.card_type);
|
||||||
let (name, trait1, trait2, trait3) = decode_packed_card_text(payload.packed_card_text);
|
let (name, trait1, trait2, trait3) = decode_packed_card_text(payload.packed_card_text);
|
||||||
|
|||||||
@@ -15,201 +15,3 @@ pub struct TypeStyle {
|
|||||||
pub primary: Rgb,
|
pub primary: Rgb,
|
||||||
pub text: Rgb,
|
pub text: Rgb,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PALETTES: [[Rgb; 16]; 8] = [
|
|
||||||
// Palette Default
|
|
||||||
[
|
|
||||||
Rgb(31, 23, 35),
|
|
||||||
Rgb(60, 47, 82),
|
|
||||||
Rgb(178, 39, 65),
|
|
||||||
Rgb(70, 86, 165),
|
|
||||||
Rgb(245, 70, 76),
|
|
||||||
Rgb(216, 104, 48),
|
|
||||||
Rgb(140, 127, 144),
|
|
||||||
Rgb(73, 149, 243),
|
|
||||||
Rgb(62, 197, 75),
|
|
||||||
Rgb(240, 149, 72),
|
|
||||||
Rgb(188, 176, 179),
|
|
||||||
Rgb(247, 156, 136),
|
|
||||||
Rgb(114, 222, 235),
|
|
||||||
Rgb(180, 230, 86),
|
|
||||||
Rgb(239, 208, 129),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Blueprint
|
|
||||||
[
|
|
||||||
Rgb(83, 67, 127),
|
|
||||||
Rgb(44, 111, 153),
|
|
||||||
Rgb(142, 88, 111),
|
|
||||||
Rgb(0, 188, 170),
|
|
||||||
Rgb(153, 104, 226),
|
|
||||||
Rgb(109, 129, 255),
|
|
||||||
Rgb(255, 84, 112),
|
|
||||||
Rgb(196, 143, 158),
|
|
||||||
Rgb(168, 159, 204),
|
|
||||||
Rgb(190, 155, 255),
|
|
||||||
Rgb(255, 155, 113),
|
|
||||||
Rgb(127, 206, 255),
|
|
||||||
Rgb(255, 155, 182),
|
|
||||||
Rgb(255, 217, 174),
|
|
||||||
Rgb(255, 217, 232),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette CYBER
|
|
||||||
[
|
|
||||||
Rgb(0, 0, 0),
|
|
||||||
Rgb(0, 0, 126),
|
|
||||||
Rgb(0, 0, 255),
|
|
||||||
Rgb(126, 0, 0),
|
|
||||||
Rgb(126, 0, 126),
|
|
||||||
Rgb(4, 126, 0),
|
|
||||||
Rgb(254, 0, 0),
|
|
||||||
Rgb(4, 126, 126),
|
|
||||||
Rgb(254, 0, 255),
|
|
||||||
Rgb(126, 126, 0),
|
|
||||||
Rgb(126, 126, 126),
|
|
||||||
Rgb(6, 255, 4),
|
|
||||||
Rgb(6, 255, 255),
|
|
||||||
Rgb(190, 190, 190),
|
|
||||||
Rgb(255, 255, 4),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Nature
|
|
||||||
[
|
|
||||||
Rgb(35, 34, 40),
|
|
||||||
Rgb(40, 66, 97),
|
|
||||||
Rgb(30, 116, 83),
|
|
||||||
Rgb(117, 77, 69),
|
|
||||||
Rgb(95, 88, 84),
|
|
||||||
Rgb(36, 133, 166),
|
|
||||||
Rgb(198, 80, 70),
|
|
||||||
Rgb(85, 160, 88),
|
|
||||||
Rgb(135, 133, 115),
|
|
||||||
Rgb(84, 186, 210),
|
|
||||||
Rgb(161, 191, 65),
|
|
||||||
Rgb(230, 146, 138),
|
|
||||||
Rgb(184, 176, 149),
|
|
||||||
Rgb(227, 192, 84),
|
|
||||||
Rgb(195, 213, 199),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Fossil
|
|
||||||
[
|
|
||||||
Rgb(75, 61, 68),
|
|
||||||
Rgb(119, 66, 81),
|
|
||||||
Rgb(78, 84, 99),
|
|
||||||
Rgb(100, 83, 85),
|
|
||||||
Rgb(156, 82, 78),
|
|
||||||
Rgb(132, 109, 89),
|
|
||||||
Rgb(91, 125, 115),
|
|
||||||
Rgb(125, 123, 98),
|
|
||||||
Rgb(140, 124, 121),
|
|
||||||
Rgb(185, 122, 96),
|
|
||||||
Rgb(168, 138, 94),
|
|
||||||
Rgb(142, 159, 125),
|
|
||||||
Rgb(170, 162, 93),
|
|
||||||
Rgb(169, 156, 141),
|
|
||||||
Rgb(204, 168, 123),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Ghost
|
|
||||||
[
|
|
||||||
Rgb(0, 0, 0),
|
|
||||||
Rgb(24, 24, 24),
|
|
||||||
Rgb(40, 40, 40),
|
|
||||||
Rgb(56, 56, 56),
|
|
||||||
Rgb(71, 71, 71),
|
|
||||||
Rgb(86, 86, 86),
|
|
||||||
Rgb(100, 100, 100),
|
|
||||||
Rgb(113, 113, 113),
|
|
||||||
Rgb(126, 126, 126),
|
|
||||||
Rgb(140, 140, 140),
|
|
||||||
Rgb(155, 155, 155),
|
|
||||||
Rgb(171, 171, 171),
|
|
||||||
Rgb(189, 189, 189),
|
|
||||||
Rgb(209, 209, 209),
|
|
||||||
Rgb(231, 231, 231),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Daemon
|
|
||||||
[
|
|
||||||
Rgb(0, 3, 60),
|
|
||||||
Rgb(96, 0, 136),
|
|
||||||
Rgb(0, 56, 132),
|
|
||||||
Rgb(42, 46, 121),
|
|
||||||
Rgb(0, 82, 96),
|
|
||||||
Rgb(177, 5, 133),
|
|
||||||
Rgb(255, 0, 78),
|
|
||||||
Rgb(172, 41, 206),
|
|
||||||
Rgb(0, 157, 74),
|
|
||||||
Rgb(0, 138, 197),
|
|
||||||
Rgb(78, 110, 168),
|
|
||||||
Rgb(255, 92, 255),
|
|
||||||
Rgb(10, 255, 82),
|
|
||||||
Rgb(0, 247, 255),
|
|
||||||
Rgb(173, 212, 250),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
// Palette Fairy
|
|
||||||
[
|
|
||||||
Rgb(40, 40, 46),
|
|
||||||
Rgb(108, 86, 113),
|
|
||||||
Rgb(135, 168, 137),
|
|
||||||
Rgb(249, 130, 132),
|
|
||||||
Rgb(176, 169, 228),
|
|
||||||
Rgb(222, 163, 139),
|
|
||||||
Rgb(172, 204, 228),
|
|
||||||
Rgb(254, 170, 228),
|
|
||||||
Rgb(217, 200, 191),
|
|
||||||
Rgb(255, 195, 132),
|
|
||||||
Rgb(176, 235, 147),
|
|
||||||
Rgb(179, 227, 218),
|
|
||||||
Rgb(233, 245, 157),
|
|
||||||
Rgb(255, 230, 198),
|
|
||||||
Rgb(255, 247, 160),
|
|
||||||
Rgb(255, 255, 255),
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const TYPE_STYLES: [TypeStyle; 8] = [
|
|
||||||
TypeStyle {
|
|
||||||
name: "Default",
|
|
||||||
primary: Rgb(0xD8, 0x68, 0x30),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Blueprint",
|
|
||||||
primary: Rgb(0x6D, 0x81, 0xFF),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "CYBER",
|
|
||||||
primary: Rgb(0xFF, 0xFF, 0x04),
|
|
||||||
text: Rgb(0x00, 0x00, 0x00),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Nature",
|
|
||||||
primary: Rgb(0x55, 0xA0, 0x58),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Fossil",
|
|
||||||
primary: Rgb(0xB9, 0x7A, 0x60),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Ghost",
|
|
||||||
primary: Rgb(0xAB, 0xAB, 0xAB),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Daemon",
|
|
||||||
primary: Rgb(0x60, 0x00, 0x88),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
TypeStyle {
|
|
||||||
name: "Fairy",
|
|
||||||
primary: Rgb(0xB0, 0xA9, 0xE4),
|
|
||||||
text: Rgb(0xFF, 0xFF, 0xFF),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
use embedded_graphics::{geometry::Size, pixelcolor::Rgb565, primitives::Rectangle, prelude::Point};
|
use crate::card::model::Palette;
|
||||||
use embedded_graphics_core::draw_target::DrawTarget;
|
|
||||||
use crate::display::palette::Rgb;
|
use crate::display::palette::Rgb;
|
||||||
|
use embedded_graphics::{
|
||||||
|
geometry::Size, pixelcolor::Rgb565, pixelcolor::RgbColor, prelude::Point, primitives::Rectangle,
|
||||||
|
};
|
||||||
|
use embedded_graphics_core::draw_target::DrawTarget;
|
||||||
|
|
||||||
pub fn render_sprite_onto_ili9341<D>(ili9341: &mut D, sprite: &[u8], palette: &[Rgb; 16])
|
pub fn render_sprite_onto_ili9341<D>(ili9341: &mut D, sprite: &[u8], palette: &Palette)
|
||||||
where
|
where
|
||||||
D: DrawTarget<Color = Rgb565>,
|
D: DrawTarget<Color = Rgb565>,
|
||||||
{
|
{
|
||||||
@@ -13,8 +16,8 @@ where
|
|||||||
|
|
||||||
// OPTIMIZATION 1: Pre-compute the 16-color palette to Rgb565 once.
|
// OPTIMIZATION 1: Pre-compute the 16-color palette to Rgb565 once.
|
||||||
let mut palette565 = [Rgb565::new(0, 0, 0); 16];
|
let mut palette565 = [Rgb565::new(0, 0, 0); 16];
|
||||||
for (i, Rgb(r, g, b)) in palette.iter().enumerate() {
|
for (i, c) in palette.iter().enumerate() {
|
||||||
palette565[i] = Rgb565::new(*r >> 3, *g >> 2, *b >> 3);
|
palette565[i] = Rgb565::new(c.r() >> 3, c.g() >> 2, c.b() >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut src_width = 1usize;
|
let mut src_width = 1usize;
|
||||||
|
|||||||
+71
-55
@@ -1,8 +1,3 @@
|
|||||||
use crate::card::decoder::{
|
|
||||||
decode_known_event, decode_packed_card_text, decode_secret, split_nfc_hex,
|
|
||||||
};
|
|
||||||
use crate::card::model::NfcPayload;
|
|
||||||
use crate::display::palette::{PALETTES, TYPE_STYLES};
|
|
||||||
use crate::display::sprite::render_sprite_onto_ili9341;
|
use crate::display::sprite::render_sprite_onto_ili9341;
|
||||||
use alloc::{format, string::String};
|
use alloc::{format, string::String};
|
||||||
use embedded_graphics::mono_font::MonoTextStyle;
|
use embedded_graphics::mono_font::MonoTextStyle;
|
||||||
@@ -14,81 +9,102 @@ 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;
|
||||||
|
|
||||||
pub fn render_nfc_payload<D>(display: &mut D, payload: &[u8; 858])
|
use core::future;
|
||||||
where
|
|
||||||
D: DrawTarget<Color = Rgb565>,
|
|
||||||
D::Error: core::fmt::Debug,
|
|
||||||
{
|
|
||||||
let nfc_payload: Option<NfcPayload<'_>> = split_nfc_hex(payload);
|
|
||||||
|
|
||||||
if let Some(nfc_payload) = nfc_payload {
|
use crate::{
|
||||||
let (name, trait1, trait2, trait3) = decode_packed_card_text(nfc_payload.packed_card_text);
|
card::model::{Card, Palette},
|
||||||
let secret = decode_secret(nfc_payload.secret);
|
display::primary_lcd::PrimaryLcdDisplay,
|
||||||
|
navigation::navigation::{Action, Navigable},
|
||||||
|
views::view::View,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CardView {
|
||||||
|
pub card: Card,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Navigable for CardView {
|
||||||
|
fn display(
|
||||||
|
&self,
|
||||||
|
display: &mut PrimaryLcdDisplay<'static>,
|
||||||
|
) -> impl core::future::Future<Output = ()> + Send {
|
||||||
|
display.clear(Rgb565::BLACK).unwrap();
|
||||||
|
|
||||||
let background = Rectangle::new(Point::new(0, 0), Size::new(240, 320));
|
let background = Rectangle::new(Point::new(0, 0), Size::new(240, 320));
|
||||||
let bg_color: Rgb565 = TYPE_STYLES[(nfc_payload.card_type - 1) as usize]
|
let bg_color = self.card.cardtype.clone().into();
|
||||||
.primary
|
|
||||||
.into_rgb565();
|
|
||||||
|
|
||||||
let _ = display.fill_solid(&background, bg_color);
|
let _ = display.fill_solid(&background, bg_color);
|
||||||
|
|
||||||
let style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE);
|
let style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE);
|
||||||
Text::new(&format!("Name: {}", name), Point::new(20, 240), style)
|
|
||||||
.draw(display)
|
|
||||||
.unwrap();
|
|
||||||
Text::new(
|
Text::new(
|
||||||
&format!(
|
&format!("Name: {}", self.card.name),
|
||||||
"Type: {}",
|
Point::new(20, 240),
|
||||||
TYPE_STYLES[(nfc_payload.card_type - 1) as usize].name
|
style,
|
||||||
),
|
)
|
||||||
|
.draw(display)
|
||||||
|
.unwrap();
|
||||||
|
Text::new(
|
||||||
|
&format!("Type: {}", self.card.cardtype),
|
||||||
Point::new(20, 250),
|
Point::new(20, 250),
|
||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
.draw(display)
|
.draw(display)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new(
|
Text::new(
|
||||||
&format!("Event: {}", decode_known_event(nfc_payload.event_encoding)),
|
&format!("Event: {}", self.card.event),
|
||||||
Point::new(20, 260),
|
Point::new(20, 260),
|
||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
.draw(display)
|
.draw(display)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new(
|
Text::new(
|
||||||
&format!(
|
&format!("UUID: {}", self.card.uuid),
|
||||||
"UUID: {}",
|
|
||||||
nfc_payload
|
|
||||||
.card_uuid
|
|
||||||
.iter()
|
|
||||||
.map(|b| format!("{:02X}", b))
|
|
||||||
.collect::<String>()
|
|
||||||
),
|
|
||||||
Point::new(20, 270),
|
Point::new(20, 270),
|
||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
.draw(display)
|
.draw(display)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new(&format!("Trait1: {}", trait1), Point::new(20, 280), style)
|
Text::new(
|
||||||
.draw(display)
|
&format!("Trait1: {}", self.card.trait1),
|
||||||
.unwrap();
|
Point::new(20, 280),
|
||||||
Text::new(&format!("Trait2: {}", trait2), Point::new(20, 290), style)
|
style,
|
||||||
.draw(display)
|
)
|
||||||
.unwrap();
|
.draw(display)
|
||||||
Text::new(&format!("Trait3: {}", trait3), Point::new(20, 300), style)
|
.unwrap();
|
||||||
.draw(display)
|
Text::new(
|
||||||
.unwrap();
|
&format!("Trait2: {}", self.card.trait2),
|
||||||
Text::new(&format!("Secret: {}", secret), Point::new(20, 310), style)
|
Point::new(20, 290),
|
||||||
.draw(display)
|
style,
|
||||||
.unwrap();
|
)
|
||||||
|
.draw(display)
|
||||||
|
.unwrap();
|
||||||
|
Text::new(
|
||||||
|
&format!("Trait3: {}", self.card.trait3),
|
||||||
|
Point::new(20, 300),
|
||||||
|
style,
|
||||||
|
)
|
||||||
|
.draw(display)
|
||||||
|
.unwrap();
|
||||||
|
Text::new(
|
||||||
|
&format!("Secret: {}", self.card.secret),
|
||||||
|
Point::new(20, 310),
|
||||||
|
style,
|
||||||
|
)
|
||||||
|
.draw(display)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
render_sprite_onto_ili9341(
|
let palette: Palette = self.card.cardtype.clone().into();
|
||||||
display,
|
render_sprite_onto_ili9341(display, self.card.sprite.data.as_slice(), &palette);
|
||||||
nfc_payload.sprite,
|
|
||||||
&PALETTES[(nfc_payload.card_type - 1) as usize],
|
core::future::ready(())
|
||||||
);
|
}
|
||||||
} else {
|
|
||||||
log::error!(
|
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = View> + Send {
|
||||||
"NFC payload too short to decode packed text: {} bytes",
|
let new_menu = match input {
|
||||||
payload.len()
|
Action::Ok => View::Card(self.clone()),
|
||||||
);
|
_ => View::Card(self.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
|
future::ready(new_menu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use core::future;
|
use core::future;
|
||||||
|
|
||||||
|
use crate::card::model::Card;
|
||||||
|
use crate::card::{decoder::split_nfc_hex, mock::MOCK_PAYLOAD, mock::MOCK_PAYLOAD2};
|
||||||
use crate::display::primary_lcd::PrimaryLcdDisplay;
|
use crate::display::primary_lcd::PrimaryLcdDisplay;
|
||||||
|
|
||||||
|
use crate::views::card_view::CardView;
|
||||||
use crate::views::journal_view::JournalView;
|
use crate::views::journal_view::JournalView;
|
||||||
use crate::views::{menu_item, settings_menu::SettingsMenu, view::View};
|
use crate::views::{menu_item, settings_menu::SettingsMenu, view::View};
|
||||||
|
|
||||||
@@ -33,6 +36,9 @@ impl Navigable for MainMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = View> + Send {
|
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = View> + Send {
|
||||||
|
let card_mock1 = Card::try_from(split_nfc_hex(&MOCK_PAYLOAD).unwrap()).unwrap();
|
||||||
|
let card_mock2 = Card::try_from(split_nfc_hex(&MOCK_PAYLOAD2).unwrap()).unwrap();
|
||||||
|
|
||||||
let new_menu = match input {
|
let new_menu = match input {
|
||||||
Action::Up => {
|
Action::Up => {
|
||||||
let new_selected = if (self.selected - 1) < 0 {
|
let new_selected = if (self.selected - 1) < 0 {
|
||||||
@@ -51,8 +57,9 @@ impl Navigable for MainMenu {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
Action::Ok => match self.selected {
|
Action::Ok => match self.selected {
|
||||||
|
0 => View::Card(CardView { card: card_mock1 }),
|
||||||
1 => View::Journal(JournalView {
|
1 => View::Journal(JournalView {
|
||||||
cards: vec![],
|
cards: vec![card_mock1, card_mock2],
|
||||||
selected_card: 0,
|
selected_card: 0,
|
||||||
}),
|
}),
|
||||||
2 => View::Settings(SettingsMenu { selected: 0 }),
|
2 => View::Settings(SettingsMenu { selected: 0 }),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::views::card_view::CardView;
|
||||||
use crate::views::{
|
use crate::views::{
|
||||||
journal_view::JournalView, main_menu::MainMenu, scan_menu::ScanMenu,
|
journal_view::JournalView, main_menu::MainMenu, scan_menu::ScanMenu,
|
||||||
settings_menu::SettingsMenu,
|
settings_menu::SettingsMenu,
|
||||||
@@ -11,6 +12,7 @@ pub enum View {
|
|||||||
Scan(ScanMenu),
|
Scan(ScanMenu),
|
||||||
Settings(SettingsMenu),
|
Settings(SettingsMenu),
|
||||||
Journal(JournalView),
|
Journal(JournalView),
|
||||||
|
Card(CardView),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Navigable for View {
|
impl Navigable for View {
|
||||||
@@ -24,6 +26,7 @@ impl Navigable for View {
|
|||||||
View::Scan(scan_menu) => scan_menu.display(display).await,
|
View::Scan(scan_menu) => scan_menu.display(display).await,
|
||||||
View::Settings(settings_menu) => settings_menu.display(display).await,
|
View::Settings(settings_menu) => settings_menu.display(display).await,
|
||||||
View::Journal(journal_view) => journal_view.display(display).await,
|
View::Journal(journal_view) => journal_view.display(display).await,
|
||||||
|
View::Card(card_view) => card_view.display(display).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,6 +41,7 @@ impl Navigable for View {
|
|||||||
View::Scan(scan_menu) => scan_menu.handle_input(input).await,
|
View::Scan(scan_menu) => scan_menu.handle_input(input).await,
|
||||||
View::Settings(settings_menu) => settings_menu.handle_input(input).await,
|
View::Settings(settings_menu) => settings_menu.handle_input(input).await,
|
||||||
View::Journal(journal_view) => journal_view.handle_input(input).await,
|
View::Journal(journal_view) => journal_view.handle_input(input).await,
|
||||||
|
View::Card(card_view) => card_view.handle_input(input).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user