From f32a1ac6f059a7c2e784ff00fb89655d21be6583 Mon Sep 17 00:00:00 2001 From: lukas Date: Sun, 2 Aug 2026 14:04:02 +0200 Subject: [PATCH] BG Color rendering and button to switch between mock payloads --- .gitignore | 3 + diagram.json | 40 ++++------ src/bin/main.rs | 207 +++++++++++++++++++++++++++++------------------- 3 files changed, 143 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index deb0257..5bb3e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ target/ # Ignore .DS_Store file in mac **/.DS_Store + +# Ignore checked out wiki +creaturedex.wiki/ diff --git a/diagram.json b/diagram.json index 04d2356..1dc4954 100644 --- a/diagram.json +++ b/diagram.json @@ -3,31 +3,24 @@ "author": "CreatureDex", "editor": "wokwi", "parts": [ - { "type": "board-esp32-s3-devkitc-1", "id": "esp1", "top": 67.2, "left": -263.96, "attrs": {} }, { - "type": "wokwi-ili9341", - "id": "lcd1", - "top": -191.24, - "left": -0.38, + "type": "board-esp32-s3-devkitc-1", + "id": "esp1", + "top": 67.2, + "left": -263.96, "attrs": {} }, + { "type": "wokwi-ili9341", "id": "lcd1", "top": -191.24, "left": -0.38, "attrs": {} }, { - "type": "wokwi-led", - "id": "led1", - "top": -82.89, - "left": 196.26, - "attrs": { "color": "red" } - }, - { - "type": "wokwi-resistor", - "id": "r1", - "top": 183.86, - "left": 154.06, - "attrs": { "value": "220" } + "type": "wokwi-pushbutton", + "id": "btn1", + "top": 131, + "left": -124.8, + "attrs": { "color": "green", "xray": "1", "key": "1" } } ], - "connections": [ - [ "esp1:TX", "$serialMonitor:RX", "", [] ], + "connections": [ + [ "esp1:TX", "$serialMonitor:RX", "", [] ], [ "esp1:RX", "$serialMonitor:TX", "", [] ], [ "lcd1:VCC", "esp1:3V3", "red", [ "v19.2", "h-57.6", "v-105.6", "h-124.95" ] ], [ "lcd1:GND", "esp1:GND.2", "black", [ "v28.8", "h-76.8", "v-76.8" ] ], @@ -39,9 +32,8 @@ [ "esp1:37", "lcd1:MISO", "magenta", [ "h57.6", "v105.6", "h172.8" ] ], [ "esp1:22", "lcd1:SCL", "yellow", [ "h48", "v163.2", "h192" ] ], [ "esp1:21", "lcd1:SDA", "cyan", [ "h38.4", "v144", "h211.2" ] ], - [ "r1:2", "led1:A", "green", [ "h8.4", "v-230.4" ] ], - [ "esp1:GND.2", "led1:C", "black", [ "v0", "h86.4", "v76.8", "h278.4" ] ], - [ "esp1:17", "r1:1", "green", [ "h0" ] ] -], + [ "btn1:1.l", "esp1:GND.2", "green", [ "h-9.6", "v-48" ] ], + [ "btn1:2.l", "esp1:38", "green", [ "h-9.6", "v19.4" ] ] + ], "dependencies": {} -} +} \ No newline at end of file diff --git a/src/bin/main.rs b/src/bin/main.rs index cd781fc..b97d308 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -27,8 +27,8 @@ use embedded_hal_bus::spi::ExclusiveDevice; use esp_hal::clock::CpuClock; use esp_hal::delay::Delay; use esp_hal::gpio::Level; -use esp_hal::gpio::Output; -use esp_hal::gpio::OutputConfig; +use esp_hal::gpio::{Input, Output, Pull}; +use esp_hal::gpio::{InputConfig, OutputConfig}; use esp_hal::spi::{ Mode, master::{Config, Spi}, @@ -169,6 +169,12 @@ const MOCK_PAYLOAD: [u8; 858] = [ #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct Rgb(pub u8, pub u8, pub u8); +impl Rgb { + fn into_rgb565(self) -> Rgb565 { + Rgb565::new(self.0, self.1, self.2) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct TypeStyle { pub name: &'static str, @@ -515,6 +521,101 @@ fn decode_packed_card_text(bytes: &[u8]) -> (String, String, String, String) { (name, trait1, trait2, trait3) } +fn render_nfc_payload(display: &mut D, payload: &[u8; 858]) +where + D: DrawTarget, + D::Error: core::fmt::Debug, +{ + let nfc_payload: Option> = split_nfc_hex(payload); + // let simulated_time: u64 = 1780757711176; // Simulated time in milliseconds since epoch (2023-06-05 12:15:11 UTC) + // let mut final_payload = [0u8; 867]; + + // final_payload[..858].copy_from_slice(payload); + // final_payload[858..866].copy_from_slice(&simulated_time.to_be_bytes()); + // final_payload[866] = 0x00; + + // let b64_string = general_purpose::STANDARD.encode(&final_payload); + // log::info!("Base64 String:"); + // log::info!("{}", b64_string); + + if let Some(nfc_payload) = nfc_payload { + 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 bg_color: Rgb565 = TYPE_STYLES[(nfc_payload.card_type - 1) as usize] + .primary + .into_rgb565(); + + let _ = display.fill_solid(&background, bg_color); + + let style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE); + Text::new(&format!("Name: {}", name), Point::new(20, 240), style) + .draw(display) + .unwrap(); + Text::new( + &format!( + "Type: {}", + TYPE_STYLES[(nfc_payload.card_type - 1) as usize].name + ), + Point::new(20, 250), + style, + ) + .draw(display) + .unwrap(); + Text::new( + &format!( + "Event: {}", + decode_known_event(nfc_payload.event_encoding).unwrap_or("Unknown") + ), + Point::new(20, 260), + style, + ) + .draw(display) + .unwrap(); + Text::new( + &format!( + "UUID: {}", + nfc_payload + .card_uuid + .iter() + .map(|b| format!("{:02X}", b)) + .collect::() + ), + Point::new(20, 270), + style, + ) + .draw(display) + .unwrap(); + Text::new(&format!("Trait1: {}", trait1), Point::new(20, 280), style) + .draw(display) + .unwrap(); + Text::new(&format!("Trait2: {}", trait2), Point::new(20, 290), style) + .draw(display) + .unwrap(); + Text::new(&format!("Trait3: {}", trait3), Point::new(20, 300), style) + .draw(display) + .unwrap(); + Text::new(&format!("Secret: {}", secret), Point::new(20, 310), style) + .draw(display) + .unwrap(); + + render_sprite_onto_ili9341( + display, + nfc_payload.sprite, + &PALETTES[(nfc_payload.card_type - 1) as usize], + ); + } else { + log::error!( + "NFC payload too short to decode packed text: {} bytes", + payload.len() + ); + } +} + #[cfg(not(feature = "wokwi"))] async fn setup_wifi( wifi: esp_hal::peripherals::WIFI<'static>, @@ -616,6 +717,9 @@ async fn main(spawner: Spawner) { esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 73744); + let button_config = InputConfig::default().with_pull(Pull::Up); + let button1 = Input::new(peripherals.GPIO38, button_config); + let timg0 = TimerGroup::new(peripherals.TIMG0); let sw_interrupt = esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); @@ -652,92 +756,29 @@ async fn main(spawner: Spawner) { display.clear(Rgb565::BLACK).unwrap(); - let nfc_payload: Option> = split_nfc_hex(&MOCK_PAYLOAD); - let simulated_time: u64 = 1780757711176; // Simulated time in milliseconds since epoch (2023-06-05 12:15:11 UTC) - let mut final_payload = [0u8; 867]; + - final_payload[..858].copy_from_slice(&MOCK_PAYLOAD); - final_payload[858..866].copy_from_slice(&simulated_time.to_be_bytes()); - final_payload[866] = 0x00; - - let b64_string = general_purpose::STANDARD.encode(&final_payload); - log::info!("Base64 String:"); - log::info!("{}", b64_string); - - if let Some(nfc_payload) = nfc_payload { - let (name, trait1, trait2, trait3) = decode_packed_card_text(nfc_payload.packed_card_text); - let secret = decode_secret(nfc_payload.secret); - - let style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE); - Text::new(&format!("Name: {}", name), Point::new(20, 240), style) - .draw(&mut display) - .unwrap(); - Text::new( - &format!( - "Type: {}", - TYPE_STYLES[(nfc_payload.card_type - 1) as usize].name - ), - Point::new(20, 250), - style, - ) - .draw(&mut display) - .unwrap(); - Text::new( - &format!( - "Event: {}", - decode_known_event(nfc_payload.event_encoding).unwrap_or("Unknown") - ), - Point::new(20, 260), - style, - ) - .draw(&mut display) - .unwrap(); - Text::new( - &format!( - "UUID: {}", - nfc_payload - .card_uuid - .iter() - .map(|b| format!("{:02X}", b)) - .collect::() - ), - Point::new(20, 270), - style, - ) - .draw(&mut display) - .unwrap(); - Text::new(&format!("Trait1: {}", trait1), Point::new(20, 280), style) - .draw(&mut display) - .unwrap(); - Text::new(&format!("Trait2: {}", trait2), Point::new(20, 290), style) - .draw(&mut display) - .unwrap(); - Text::new(&format!("Trait3: {}", trait3), Point::new(20, 300), style) - .draw(&mut display) - .unwrap(); - Text::new(&format!("Secret: {}", secret), Point::new(20, 310), style) - .draw(&mut display) - .unwrap(); - - render_sprite_onto_ili9341( - &mut display, - nfc_payload.sprite, - &PALETTES[(nfc_payload.card_type - 1) as usize], - ); - } else { - log::error!( - "NFC payload too short to decode packed text: {} bytes", - MOCK_PAYLOAD.len() - ); - } - - setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await; + //setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await; log::info!("Setup complete, entering main loop"); + let mut use_first_payload = true; + loop { - info!("Hello world!"); - Timer::after_millis(500).await; + if button1.is_low() { + log::info!("Button pressed!"); + display.clear(Rgb565::BLACK).unwrap(); + let payload = if use_first_payload { + &MOCK_PAYLOAD + } else { + &MOCK_PAYLOAD2 + }; + + render_nfc_payload(&mut display, payload); + use_first_payload = !use_first_payload; + } + // info!("Hello world!"); + Timer::after_millis(10).await; } // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.1.0/examples