From 7b378b89abdfa5d43ad1ff5263d35a001225e661 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Sun, 23 Aug 2026 09:45:18 +0200 Subject: [PATCH] implement simple card storage retreival --- Cargo.lock | 58 +++++++++++++++++++++++++++++++ Cargo.toml | 3 ++ src/bin/main.rs | 8 +++-- src/lib.rs | 1 + src/storage.rs | 30 +++++++++++++++-- src/storage/cardstore.rs | 73 ++++++++++++++++++++++++++++++++++++++++ src/storage/dex_db.rs | 1 - src/storage/nvs.rs | 1 - src/storage/settings.rs | 0 src/storage/store.rs | 40 ++++++++++++++++++++++ 10 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 src/storage/cardstore.rs delete mode 100644 src/storage/dex_db.rs delete mode 100644 src/storage/nvs.rs create mode 100644 src/storage/settings.rs create mode 100644 src/storage/store.rs diff --git a/Cargo.lock b/Cargo.lock index c7ada03..4e7217d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c583acf993cf4245c4acb0a2cc2ab1f9cc097de73411bb6d3647ff6af2b1013d" +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + [[package]] name = "autocfg" version = "1.5.1" @@ -96,6 +102,29 @@ dependencies = [ "vsimd", ] +[[package]] +name = "binary_serde" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4b2fe974c561ed04fb89673dd221bed36fc4794b71ca6ae96ffe19949045686" +dependencies = [ + "array-init", + "binary_serde_macros", + "recursive_array", + "thiserror-no-std", +] + +[[package]] +name = "binary_serde_macros" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4790b8dbcfa9d3adf2020ebf5fd36c6bc89a77d434131615ea349bc9620e8831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "bitfield" version = "0.17.0" @@ -319,6 +348,7 @@ name = "creaturedex" version = "0.1.0" dependencies = [ "base64 0.22.1", + "binary_serde", "ch1115", "critical-section", "display-interface-spi", @@ -332,12 +362,14 @@ dependencies = [ "embedded-hal-async", "embedded-hal-bus", "embedded-io 0.7.1", + "embedded-storage", "esp-alloc", "esp-bootloader-esp-idf", "esp-hal", "esp-hal-wifimanager", "esp-println", "esp-rtos", + "esp-storage", "i2c-character-display", "ili9341", "log", @@ -2828,6 +2860,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "recursive_array" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69bad83913c3b39011ad9d43b7ac0cae139cec5d7e7288fbea5bb4b4e3cc78f6" + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3305,6 +3343,26 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "thiserror-impl-no-std" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e6318948b519ba6dc2b442a6d0b904ebfb8d411a3ad3e07843615a72249758" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thiserror-no-std" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ad459d94dd517257cc96add8a43190ee620011bb6e6cdc82dafd97dfafafea" +dependencies = [ + "thiserror-impl-no-std", +] + [[package]] name = "thread_local" version = "1.1.10" diff --git a/Cargo.toml b/Cargo.toml index 55b0e77..4656ff8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,9 @@ embassy-sync = "0.8.0" embedded-hal-async = "1.0.0" i2c-character-display = "0.5.1" ch1115 = { version = "0.1.2", features = ["graphics"] } +esp-storage = "0.9.0" +embedded-storage = "0.3.1" +binary_serde = "1.0.25" [patch.crates-io] diff --git a/src/bin/main.rs b/src/bin/main.rs index fa8a950..657c4bf 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -16,6 +16,8 @@ use creaturedex::drivers::nfc_pn532::NfcPn532Driver; use creaturedex::navigation::inputs::Inputs; use creaturedex::navigation::navigation::{self, CARD_DATA}; use creaturedex::network::wifi::setup_wifi; +use creaturedex::storage::cardstore::CardStore; +use creaturedex::storage::store::Store; use embassy_executor::Spawner; use embassy_time::Instant; use embedded_graphics::pixelcolor::BinaryColor; @@ -108,7 +110,9 @@ async fn main(spawner: Spawner) { ); } - setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await; + let store = Store::new(peripherals.FLASH).expect("Could not initialize Flash Store"); + let card_store = CardStore::new(store).expect("Could not initialize Card Store"); + //setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await; let mut nfc_driver = NfcPn532Driver::new(AtomicDevice::new(shared_i2c)); if nfc_driver.configure_sam().await.is_ok() { @@ -150,7 +154,7 @@ async fn nfc_driver_task( CARD_DATA .lock() .await - .replace(Card::try_from(split_data).unwrap()); + .replace(Card::try_from(split_data).expect("Invalid card data")); let elapsed_ms = start.elapsed().as_millis(); log::info!( "NFC read duration: {} ms, card data length: {}", diff --git a/src/lib.rs b/src/lib.rs index 501ca20..6697dde 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![no_std] +#![feature(vec_into_chunks)] extern crate alloc; diff --git a/src/storage.rs b/src/storage.rs index 4d0325f..7cfc291 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,2 +1,28 @@ -pub mod dex_db; -pub mod nvs; +struct MemoryRegion { + offset: u32, + size: usize, +} + +impl MemoryRegion { + const fn end(&self) -> usize { + self.offset as usize + self.size + } +} + +const MAX_FLASH: usize = 16 * 1024 * 1024; + +const MAGIC_REGION: MemoryRegion = MemoryRegion { offset: 0, size: 4 }; + +const SETTINGS_REGION: MemoryRegion = MemoryRegion { + offset: MAGIC_REGION.end() as u32, + size: 1024, +}; + +const CARDSTORE_REGION: MemoryRegion = MemoryRegion { + offset: SETTINGS_REGION.end() as u32, + size: MAX_FLASH - SETTINGS_REGION.end(), +}; + +pub mod cardstore; +pub mod settings; +pub mod store; diff --git a/src/storage/cardstore.rs b/src/storage/cardstore.rs new file mode 100644 index 0000000..1bd5780 --- /dev/null +++ b/src/storage/cardstore.rs @@ -0,0 +1,73 @@ +use alloc::collections::BTreeMap; use embedded_storage::nor_flash::ReadNorFlash; +use alloc::vec::Vec; + +use binary_serde::{BinarySerde, Endianness}; + +//use crate::card::model::NfcPayload; + +use crate::storage::store::{Store, StoreError}; + +use crate::storage::{MemoryRegion,CARDSTORE_REGION}; + +const MAX_CARDS: usize = 20000; + +const COUNT_REGION: MemoryRegion = MemoryRegion { offset: CARDSTORE_REGION.offset, size: size_of::()}; + +#[derive(Debug, BinarySerde, Default, PartialEq, Eq)] +#[repr(C)] +struct AllocationTableEntry { + uuid: u32, + offset: u32, + + creation_date: u64, + last_read_date: u64, + + // how often a card has been read + read_count: u32, + + deleted: bool, + + reserved: [u64; 4], +} + +const ALLOCATION_TABLE_SIZE: usize = size_of::(); + +const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {offset: COUNT_REGION.end() as u32, size: MAX_CARDS * size_of::()}; + +const CARDS_REGION: MemoryRegion = MemoryRegion { offset: ALLOCATION_TABLE_REGION.end() as u32, size: CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end()}; + +pub struct CardStore { + store: Store, + count: usize, + allocation_table: BTreeMap +} + +impl CardStore { + pub fn new(mut store: Store) -> Result { + let mut count_bytes: [u8; COUNT_REGION.size] = [0; COUNT_REGION.size]; + + store.read(COUNT_REGION.offset, &mut count_bytes)?; + + let count: usize = usize::from_ne_bytes(count_bytes); + + let mut allocation_table_entries: Vec = Vec::with_capacity(ALLOCATION_TABLE_SIZE * count); + + store + .read(ALLOCATION_TABLE_REGION.offset, &mut allocation_table_entries)?; + + let chunks = allocation_table_entries.into_chunks::(); + + let mut allocation_table = BTreeMap::::new(); + for chunk in chunks { + let allocation_table_entry = AllocationTableEntry::binary_deserialize(chunk.as_ref(), Endianness::Little).unwrap(); + allocation_table.insert(allocation_table_entry.uuid, allocation_table_entry); + } + + Ok(Self { store, count, allocation_table }) + } + + //fn get_card_by_uuid(uuid: &str) {} + + //fn get_card_by_position(position: usize) {} + +} diff --git a/src/storage/dex_db.rs b/src/storage/dex_db.rs deleted file mode 100644 index acd61ed..0000000 --- a/src/storage/dex_db.rs +++ /dev/null @@ -1 +0,0 @@ -// Storage dex_db module diff --git a/src/storage/nvs.rs b/src/storage/nvs.rs deleted file mode 100644 index 5c63f41..0000000 --- a/src/storage/nvs.rs +++ /dev/null @@ -1 +0,0 @@ -// Storage nvs module diff --git a/src/storage/settings.rs b/src/storage/settings.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/store.rs b/src/storage/store.rs new file mode 100644 index 0000000..31c80e2 --- /dev/null +++ b/src/storage/store.rs @@ -0,0 +1,40 @@ +use embedded_storage::nor_flash::NorFlash; +use embedded_storage::nor_flash::ReadNorFlash; +use esp_storage::{FlashStorage, FlashStorageError}; + +pub type StoreError = FlashStorageError; + +const FLASH_ADDR: u32 = 0x9000; + +const INITIALIZATION_SIZE: usize = 0x1004; +const FLASH_INITIALIZE_MAGIC: u32 = 0xde6de6de; + +pub struct Store { + pub storage: FlashStorage<'static>, +} + +fn initialize_flash(storage: &mut FlashStorage) -> Result<(), StoreError> { + let zeros: [u8; INITIALIZATION_SIZE] = [0; INITIALIZATION_SIZE]; + storage.write(FLASH_ADDR, &zeros)?; + storage.write(FLASH_ADDR, &FLASH_INITIALIZE_MAGIC.to_ne_bytes())?; + Ok(()) +} + +impl Store { + pub fn new(flash: esp_hal::peripherals::FLASH<'static>) -> Result { + let mut storage = FlashStorage::new(flash); + + let mut magic: [u8; 4] = [0, 0, 0, 0]; + storage.read(FLASH_ADDR, &mut magic)?; + + if (u32::from_ne_bytes(magic)) != FLASH_INITIALIZE_MAGIC { + initialize_flash(&mut storage)?; + } + + Ok(Self { storage }) + } + + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> { + self.storage.read(FLASH_ADDR + offset, bytes) + } +}