From 68250b2924661340149c42127ed5798baa7dd11e Mon Sep 17 00:00:00 2001 From: rhetenor Date: Tue, 18 Aug 2026 20:51:19 +0000 Subject: [PATCH] implement card model --- Cargo.lock | 1 + Cargo.toml | 1 + src/card/decoder.rs | 37 ++++++++++++++++++++++++------ src/card/model.rs | 52 ++++++++++++++++++++++++++++++++++-------- src/views/card_view.rs | 20 +++++++--------- 5 files changed, 82 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 601c3da..99be1df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,6 +322,7 @@ dependencies = [ "ili9341", "log", "ndef", + "num_enum", "pn532", ] diff --git a/Cargo.toml b/Cargo.toml index 142ecff..ba0ea29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ embedded-graphics-core = "0.4.1" base64 = { version = "0.22", default-features = false, features = ["alloc"] } pn532 = "0.5.0" ndef = "0.5.0" +num_enum = { version = "0.7.6", default-features = false } # For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html [profile.dev] diff --git a/src/card/decoder.rs b/src/card/decoder.rs index 9c865e8..60f2a39 100644 --- a/src/card/decoder.rs +++ b/src/card/decoder.rs @@ -1,5 +1,7 @@ -use alloc::string::{String, ToString}; +use core::fmt::Display; + use crate::card::model::NfcPayload; +use alloc::string::{String, ToString}; pub fn split_nfc_hex(payload: &[u8]) -> Option> { if payload.len() < 0x35A { @@ -18,13 +20,34 @@ pub fn split_nfc_hex(payload: &[u8]) -> Option> { }) } -pub fn decode_known_event(event_encoding: &[u8]) -> Option<&'static str> { +#[derive(Debug, Clone)] +pub enum Events { + CCC39, + CCC40, + GPN24, + GPN25, + Unknown, +} + +impl Display for Events { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match *self { + Events::CCC39 => write!(f, "39C3"), + Events::CCC40 => write!(f, "40C3"), + Events::GPN24 => write!(f, "GPN24"), + Events::GPN25 => write!(f, "GPN25"), + Events::Unknown => write!(f, "Unknown"), + } + } +} + +pub fn decode_known_event(event_encoding: &[u8]) -> Events { match event_encoding { - [0x39, 0xC3] => Some("39C3"), - [0x40, 0xC3] => Some("40C3"), // future proofing :) - [0xE9, 0x24] => Some("GPN 24"), - [0xE9, 0x25] => Some("GPN 25"), // future proofing :) - _ => None, + [0x39, 0xC3] => Events::CCC39, + [0x40, 0xC3] => Events::CCC40, // future proofing :) + [0xE9, 0x24] => Events::GPN24, + [0xE9, 0x25] => Events::GPN25, // future proofing :) + _ => Events::Unknown, } } diff --git a/src/card/model.rs b/src/card/model.rs index 0a69a54..e4fd0d4 100644 --- a/src/card/model.rs +++ b/src/card/model.rs @@ -1,4 +1,7 @@ use alloc::{string::String, vec::Vec}; +use num_enum::FromPrimitive; + +use crate::card::decoder::{Events, decode_known_event, decode_packed_card_text, decode_secret}; #[derive(Debug, Clone, Copy)] pub struct NfcPayload<'a> { @@ -12,16 +15,18 @@ pub struct NfcPayload<'a> { pub _opaque_trailer: &'a [u8], } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive)] +#[repr(u8)] pub enum CardType { - Default, - Blueprint, - CYBER, - Nature, - Fossil, - Ghost, - Daemon, - Fairy, + #[num_enum(default)] + Default = 0, + Blueprint = 1, + CYBER = 2, + Nature = 3, + Fossil = 4, + Ghost = 5, + Daemon = 6, + Fairy = 7, } #[derive(Debug, Clone)] @@ -32,8 +37,9 @@ pub struct Sprite { #[derive(Debug, Clone)] pub struct Card { pub uuid: String, - pub name: String, + pub event: Events, pub cardtype: CardType, + pub name: String, pub trait1: String, pub trait2: String, @@ -42,3 +48,29 @@ pub struct Card { pub sprite: Sprite, } + +impl TryFrom> for Card { + type Error = &'static str; + + fn try_from(payload: NfcPayload) -> Result { + let uuid: String = str::from_utf8(payload.card_uuid).unwrap().into(); + let event = decode_known_event(payload.event_encoding); + let cardtype = CardType::from(payload.card_type); + let (name, trait1, trait2, trait3) = decode_packed_card_text(payload.packed_card_text); + let secret = decode_secret(payload.secret); + let sprite = Sprite { + data: payload.sprite.to_vec(), + }; + Ok(Self { + uuid, + event, + cardtype, + name, + trait1, + trait2, + trait3, + secret, + sprite, + }) + } +} diff --git a/src/views/card_view.rs b/src/views/card_view.rs index d298883..9af0f91 100644 --- a/src/views/card_view.rs +++ b/src/views/card_view.rs @@ -1,3 +1,9 @@ +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 alloc::{format, string::String}; use embedded_graphics::mono_font::MonoTextStyle; use embedded_graphics::mono_font::ascii::FONT_6X10; @@ -7,10 +13,6 @@ use embedded_graphics::prelude::RgbColor; use embedded_graphics::text::Text; use embedded_graphics::{Drawable, geometry::Size, primitives::Rectangle}; use embedded_graphics_core::draw_target::DrawTarget; -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; pub fn render_nfc_payload(display: &mut D, payload: &[u8; 858]) where @@ -23,10 +25,7 @@ where let (name, trait1, trait2, trait3) = decode_packed_card_text(nfc_payload.packed_card_text); let secret = decode_secret(nfc_payload.secret); - 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] .primary .into_rgb565(); @@ -48,10 +47,7 @@ where .draw(display) .unwrap(); Text::new( - &format!( - "Event: {}", - decode_known_event(nfc_payload.event_encoding).unwrap_or("Unknown") - ), + &format!("Event: {}", decode_known_event(nfc_payload.event_encoding)), Point::new(20, 260), style, )