Add Gitea OTA firmware update, dual-slot partition layout, and Gitea Actions release workflow
This commit is contained in:
342
README.md
342
README.md
@@ -1,14 +1,28 @@
|
||||
# MTG RFID Companion
|
||||
# MTG RFID Companion 🧙♂️✨
|
||||
|
||||
A feature-packed, handheld **Magic: The Gathering** companion built on the **ESP32-WROOM-32**. Slip an RFID/NFC tag into your card sleeves and tap them to the device for instant card lookups, official art display, life tracking, dice rolling, and complete deck management.
|
||||
|
||||
All firmware is written in **pure ESP-IDF v5.x (C) / FreeRTOS** — no Arduino overhead, dual-core task segregation, and strictly optimized for devices without external PSRAM (< 520 KB SRAM).
|
||||
A dedicated tabletop companion for **Magic: The Gathering** players. Slip micro RFID/NFC stickers into your card sleeves and tap them to the device for instant card lookups, official full-color art, life tracking, dice rolling, and complete deck management.
|
||||
|
||||
---
|
||||
|
||||
## 🌟 Feature Tour & Modes
|
||||
## 🃏 Part 1: Player's Guide (Non-Technical Overview)
|
||||
|
||||
The companion boots directly into an interactive, rotary-controlled interface designed specifically for tabletop MTG gameplay:
|
||||
### What is the MTG Companion?
|
||||
The MTG Companion is a handheld gadget designed to sit on your playmat during Commander (EDH), Modern, or casual kitchen-table games.
|
||||
|
||||
Instead of fumbling for your phone to check complex Oracle card text, searching for spindown dice, or asking *"Wait, how much commander tax am I at?"*, the Companion handles everything with a turn of a knob and a tap of a card:
|
||||
|
||||
* **⚡ Tap-to-Identify:** Tap any sleeved card with an NFC sticker to instantly display its official illustration, mana cost, updated Oracle text, type line, power/toughness, and current market price.
|
||||
* **👑 Legendary Fanfares:** An 8-bit stinger plays whenever you cast a Mythic Rare or Legendary spell!
|
||||
* **❤️ Life & Multi-Counter:** Tracks starting life (40 for Commander, 20 for Standard/Modern), **Poison Counters** (tracks to 10 lethal), and **Commander Combat Damage** (tracks to 21 lethal). Sounds an 8-bit defeat tone if a player dies.
|
||||
* **🎲 Spindown D20, D6 & Fair Coin:** Roll animated dice on screen with ticking sound effects and special fanfares for Natural 20s and Natural 1s.
|
||||
* **🪙 Token & Counter Spawner:** Digital counters for **Treasures, Foods, Clues, 1/1 Soldiers, 1/1 Goblins, 2/2 Zombies, 3/3 Beasts**, and **+1/+1 Counters**.
|
||||
* **👑 Commander Tax & Turn Tracker:** Automatically calculates the extra {2} mana tax every time your commander returns to the command zone, alongside a table turn counter.
|
||||
* **📱 Wireless Phone Pairing:** Connect your phone or laptop over your home Wi-Fi (or the device's hotspot) to easily assign card names to tags with live Scryfall search autocomplete.
|
||||
* **🔄 Over-The-Air (OTA) Updates:** Update to new software versions wirelessly over Wi-Fi right from the on-device menu.
|
||||
|
||||
---
|
||||
|
||||
### How to Use at the Table
|
||||
|
||||
```
|
||||
┌──────────────────────────────┐
|
||||
@@ -20,160 +34,115 @@ The companion boots directly into an interactive, rotary-controlled interface de
|
||||
│ [4] Commander Tax │
|
||||
│ [5] Token & Counters │
|
||||
│ [6] Deck Storage │
|
||||
│ [7] Device Info │
|
||||
│ [7] Device & WiFi Info │
|
||||
│ [8] Check Firmware OTA │
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1. Interactive Boot Menu (`APP_STATE_MENU`)
|
||||
On power-up, the device greets you with the Main Menu.
|
||||
* **Rotate the knob** to highlight any of the 7 modes with an active amber cursor.
|
||||
* **Click the knob** to enter the highlighted mode.
|
||||
* **Universal Back (Hold knob $\ge$ 0.75s):** Press and hold the rotary switch from **any** screen to sound a double-chirp, flash purple on the WS2812B LED, and instantly return to the Main Menu.
|
||||
* **Universal Card Interrupt:** Tapping a card tag from **any** screen or menu immediately transitions into that card's view.
|
||||
#### Controls
|
||||
* **Turn the knob:** Scroll through menus, adjust life totals, change token quantities, or pick dice modes.
|
||||
* **Click the knob:** Select an option, roll dice, or toggle between Life, Poison, and Commander Damage modes.
|
||||
* **Long Press (Hold knob for 0.75s):** Sounds a chirp and instantly takes you back to the **Main Menu** from any screen.
|
||||
* **Tap a Card Anytime:** Tapping a card sleeve immediately pulls up that card's details, regardless of which screen you are on.
|
||||
|
||||
---
|
||||
|
||||
### 2. Universal RFID Scanner & Art Crop Display (`APP_STATE_CARD_VIEW`)
|
||||
* **Instant Tag Identification:** Supports MFRC522, ISO/IEC 14443A, NTAG213/215 stickers, and standard MIFARE 1K cards (4-byte and 7-byte UIDs).
|
||||
* **True RGB565 Scryfall Art:** Cards display official card illustrations pre-scaled to a crisp 200×110 format, decoded via hardware-assisted Baseline JPEG in ~10 ms with true color accuracy.
|
||||
* **Card Metadata:** Shows card name, mana cost, type line, oracle text, power/toughness, loyalty, and market pricing.
|
||||
* **8-Bit Legendary Stinger & Neopixel Feedback:**
|
||||
* **Legendary / Mythic Stinger:** Scanning any Legendary creature or Mythic Rare plays an upward 8-bit stinger and pulses the LED in gold!
|
||||
* **Mana Color LEDs:** WS2812B Neopixel illuminates in the card's native mana identity (White, Blue, Black, Red, Green, Gold, Colorless).
|
||||
* **Unmapped Card Support:** Tapping an unmapped tag switches to the Registration view, displaying the UID and pairing instructions.
|
||||
* **Smart Cache Validation:** When a card tag is re-paired or changed in the web UI, the firmware automatically detects the change, purges old cached assets, and downloads the fresh card details and art.
|
||||
### Tabletop Modes
|
||||
|
||||
#### 1. Card Scanner & Art Viewer
|
||||
Tap your card against the scanner area. The device checks its internal memory and displays:
|
||||
* Full-color official art crop streamed from Scryfall.
|
||||
* Mana cost, card type, power / toughness, and loyalty.
|
||||
* Updated Oracle card text with rules text formatting.
|
||||
* Market price in USD.
|
||||
|
||||
#### 2. Life & Metric Tracker
|
||||
* Starts at **40 life** (Commander) or **20 life** (1v1).
|
||||
* Rotate clockwise to gain life; counter-clockwise to take damage.
|
||||
* **Click the knob** to cycle between:
|
||||
1. **Life Total** (Standard life score).
|
||||
2. **Poison Counters** (Counts 0 to 10; triggers a defeat tone at 10).
|
||||
3. **Commander Combat Damage** (Counts 0 to 21; triggers lethal banner at 21).
|
||||
|
||||
#### 3. Spindown D20 / D6 / Fair Coin Flip
|
||||
* Select **D20 Spindown**, **D6**, or **Coin Flip** and click to roll.
|
||||
* An animated roll plays with sound effects.
|
||||
* **Natural 20:** Plays a triumphant 8-bit Victory Fanfare!
|
||||
* **Natural 1:** Sounds a critical failure buzz.
|
||||
* **Coin Flip:** Clean 50/50 toss landing on **HEADS** or **TAILS**.
|
||||
|
||||
#### 4. Built-in Token & Counter Spawner
|
||||
Never dig through your token box again for missing tokens:
|
||||
* Pre-loaded with MTG staples: **Treasure, Food, Clue, Soldier (1/1), Zombie (2/2), Goblin (1/1), Beast (3/3)**, and **+1/+1 Counters**.
|
||||
* Rotate to select a token, click to edit, and rotate to change quantity (persists throughout your game).
|
||||
|
||||
#### 5. Commander Tax & Turn Tracker
|
||||
* Rotate the knob each time your commander is recast from the command zone; the screen calculates the extra mana required (e.g. `Cast 3 = +4 Mana`).
|
||||
* Click to switch to the table turn counter.
|
||||
|
||||
#### 6. Pairing Cards from your Phone (No App Needed!)
|
||||
When you scan a new card tag that hasn't been programmed yet:
|
||||
1. The screen displays:
|
||||
```
|
||||
PAIR VIA WI-FI:
|
||||
http://192.168.0.57
|
||||
(or Hotspot: MTG-Companion @ 192.168.4.1)
|
||||
```
|
||||
2. Open that address in your smartphone or laptop browser.
|
||||
3. Tap the card sleeve to the device—its unique ID pops up in the web form automatically.
|
||||
4. Start typing the card name (e.g. `"Sol Ring"`). Real-time Scryfall suggestions appear.
|
||||
5. Click **Pair Card**. The device downloads the high-res card art and text and saves it to its permanent memory.
|
||||
6. **Deck Overview:** The web page also lets you view your entire scanned deck with card art thumbnails and unbind old cards with one click.
|
||||
|
||||
#### 7. Over-The-Air (OTA) Updates
|
||||
* Select **8. CHECK FIRMWARE OTA** from the menu (or let it auto-check on boot when connected to Wi-Fi).
|
||||
* If a new version is detected, the screen shows the new version number and asks you to click to install or turn the knob to dismiss.
|
||||
* While updating, a live progress bar shows the download. When finished, the device verifies the update and restarts automatically.
|
||||
|
||||
---
|
||||
|
||||
### 3. Life & Multi-Counter (`APP_STATE_LIFE_COUNTER`)
|
||||
A dedicated, high-contrast tournament-grade counter supporting the three most important Magic metrics:
|
||||
* **Life Total (Starts at 40 Commander / 20 Standard):**
|
||||
* Turn clockwise to gain life (green LED flash); turn counter-clockwise to lose life (red LED flash).
|
||||
* **Click to Cycle Counter Types:**
|
||||
1. **Life Total:** Standard life tracking.
|
||||
2. **Poison Counters (0–10):** In MTG, taking 10 poison counters loses the game.
|
||||
3. **Commander Combat Damage (0–21):** Dealing 21 combat damage with a single commander eliminates a player.
|
||||
* **8-Bit Dramatic Loss Tone:** Reaching 0 life or 10 poison triggers an 8-bit descending defeat stinger and a red alert banner.
|
||||
## 🛠️ Part 2: Technical Specifications & Build Guide
|
||||
|
||||
### Hardware Architecture
|
||||
|
||||
| Component | Part / Model | Purpose |
|
||||
| :--- | :--- | :--- |
|
||||
| **MCU** | ESP32-WROOM-32 (4MB Flash, no external PSRAM) | Dual-core 240 MHz processor |
|
||||
| **Display** | 2.0" ST7789 IPS TFT LCD (240x320 resolution) | 16-bit RGB565 high-contrast screen |
|
||||
| **RFID Reader** | MFRC522 (13.56 MHz, SPI Interface) | Reads ISO/IEC 14443A tags & stickers |
|
||||
| **User Input** | EC11 Rotary Encoder with push button | Tabletop navigation & life adjustment |
|
||||
| **Audio** | Passive Piezo Buzzer (GPIO 14) | LEDC PWM multi-frequency tones |
|
||||
| **Tags** | NTAG213 / NTAG215 micro FPC stickers | Thin adhesive tags embedded inside sleeves |
|
||||
| **Capacitor** | **2200 µF Electrolytic Capacitor** | **CRITICAL**: Placed across MFRC522 VCC/GND to absorb RF transmit current spikes |
|
||||
|
||||
---
|
||||
|
||||
### 4. Spindown D20 / D6 / Fair Coin Flip (`APP_STATE_DICE_ROLLER`)
|
||||
* **Rotate knob** to select between **D20 (Spindown)**, **D6**, or **Coin Flip**, then **click to roll**.
|
||||
* Plays an interactive rolling shuffle animation with rapid tick sounds.
|
||||
* **Natural 20 (Critical Hit):** Plays the 8-bit **Victory Fanfare** and flashes brilliant green.
|
||||
* **Natural 1 (Critical Fail):** Sounds a buzzer tone and flashes red.
|
||||
* **D6 Mode:** Quick six-sided die roll for ability triggers and random player selection.
|
||||
* **Coin Flip Mode:** Random 50/50 flip landing on **HEADS (Green)** or **TAILS (Amber)**.
|
||||
### GPIO Wiring & Pinout
|
||||
|
||||
---
|
||||
|
||||
### 5. Built-in Token & Counter Spawner (`APP_STATE_TOKEN_SPAWNER`)
|
||||
An interactive tabletop tool for spawning and managing tokens on the battlefield:
|
||||
* **Pre-configured Tokens:**
|
||||
* **Treasure** (Artifact Token) — `{T}, Sacrifice: Add one mana of any color.`
|
||||
* **Food** (Artifact Token) — `{2}, {T}, Sacrifice: You gain 3 life.`
|
||||
* **Clue** (Artifact Token) — `{2}, Sacrifice: Draw a card.`
|
||||
* **1/1 Soldier** (White Creature Token) — With full P/T box.
|
||||
* **2/2 Zombie** (Black Creature Token) — With full P/T box.
|
||||
* **1/1 Goblin** (Red Creature Token) — With full P/T box.
|
||||
* **3/3 Beast** (Green Creature Token) — With full P/T box.
|
||||
* **+1/+1 Counter** (Permanent Modifier) — Universal stat counter.
|
||||
* **Controls:**
|
||||
* **Pick Mode:** Rotate the knob to cycle through tokens (`< 1 OF 8 >`).
|
||||
* **Edit Mode:** Click the knob to select; rotate to increment/decrement count (`0` to `99`). Click again to save. Token quantities persist throughout the play session.
|
||||
|
||||
---
|
||||
|
||||
### 6. Commander Tax & Turn Tracker (`APP_STATE_COMMANDER_TRACKER`)
|
||||
In Commander (EDH), casting your commander costs an additional {2} generic mana for each time it has previously been cast from the command zone.
|
||||
* **Commander Casts:** Rotate the knob to adjust casts; the screen automatically calculates and displays the total tax (e.g., `Cast 3 = +4 Mana`).
|
||||
* **Turn Counter:** Click the button to switch to the table turn tracker.
|
||||
|
||||
---
|
||||
|
||||
### 7. Deck & Storage Manager (`APP_STATE_STORAGE_MANAGER`)
|
||||
View flash disk usage and manage cards stored in LittleFS:
|
||||
* **Storage Metrics:** Displays total storage space (~1.9 MB), used bytes, and counts of cached JSON cards and art crop images.
|
||||
* **Wipe All Cards (New Deck Mode):** Switching to a new deck? Rotate to highlight "Wipe All Cards", click, and confirm. This purges `/spiffs/cards/*` and resets `mappings.json`, freeing space for a completely new 100-card deck with full artwork.
|
||||
|
||||
---
|
||||
|
||||
### 8. Web Registration, SoftAP Pairing & Scanned Cards Overview (`web_server`)
|
||||
Pair tags and manage your entire scanned deck directly from your smartphone browser—no host software required:
|
||||
1. Connect your phone or laptop to the Wi-Fi network: **`MTG-Companion`** (open network, default IP `192.168.4.1`).
|
||||
2. Open `http://192.168.4.1` in your browser.
|
||||
3. **Pair New Tag:**
|
||||
* Tap an RFID tag to the reader — the UID populates automatically.
|
||||
* Type the card name (Scryfall autocomplete suggestions appear in real time).
|
||||
* Click **Pair Card**. The binding is saved to `/spiffs/mappings.json` and the firmware fetches the card details and cover art over Wi-Fi.
|
||||
4. **Scanned / Paired Cards Overview:**
|
||||
* View an alphabetized list of all registered cards in your deck with live card counter (`Paired Cards (X)`).
|
||||
* Displays the card title, tag UID, and cover art thumbnails streamed directly from LittleFS flash storage (`/api/art?uid=...`).
|
||||
* **Unbind Card:** Click "Unbind" next to any card to immediately delete its mapping and clean up its cached JSON and JPEG files from flash memory.
|
||||
* **Refresh:** Click "Refresh" to re-sync the list after scans or edits.
|
||||
|
||||
---
|
||||
|
||||
### 9. Device Info Screen (`APP_STATE_DEVICE_INFO`)
|
||||
Real-time diagnostic screen showing:
|
||||
* Wi-Fi STA connection status, SSID, and assigned IP address.
|
||||
* SoftAP network details (`MTG-Companion`, `192.168.4.1`).
|
||||
* Free internal heap SRAM (typically ~180 KB free during active rendering).
|
||||
* System uptime and LittleFS partition status.
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Quick Controls Cheat Sheet
|
||||
|
||||
| Action | Control |
|
||||
| :--- | :--- |
|
||||
| **Navigate / Adjust** | Rotate EC11 rotary knob clockwise / counter-clockwise |
|
||||
| **Select / Roll / Toggle** | Short press encoder button |
|
||||
| **Universal Back (To Menu)** | **Long press encoder button ($\ge$ 0.75s)** (double chirp + purple flash) |
|
||||
| **Instant Card View** | Tap any RFID card sleeve to reader from **any** screen |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Hardware Requirements
|
||||
|
||||
- **ESP32-WROOM-32** development board (4MB flash, dual-core LX6, no external PSRAM needed).
|
||||
- **ST7789** SPI TFT LCD, 240x320 resolution (2.0" or 2.4" breakout).
|
||||
- **MFRC522** RFID reader module (13.56 MHz, SPI).
|
||||
- **EC11** rotary encoder with integrated push switch.
|
||||
- **WS2812B / Neopixel** (single addressable RGB LED).
|
||||
- **Passive piezo buzzer** (driven via LEDC PWM).
|
||||
- **Antenna-friendly NTAG213/NTAG215** micro FPC stickers (for card sleeves) or standard MIFARE cards.
|
||||
- **2200 µF Electrolytic Capacitor** (placed directly across MFRC522 VCC and GND) — **CRITICAL**: absorbs RF transmit spikes and prevents 3.3V rail voltage dips that trigger ESP32 brownouts or MFRC522 register resets.
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Peripheral Wiring & Pinout
|
||||
|
||||
The display and RFID reader use **two separate SPI host controllers** to prevent SPI bus contention and clock mismatch:
|
||||
The display and RFID reader run on **two separate SPI host controllers** to prevent SPI bus contention and clock frequency mismatches:
|
||||
- **ST7789 Display:** `SPI2_HOST` (VSPI) at 20 MHz.
|
||||
- **MFRC522 Reader:** `SPI3_HOST` (HSPI) at 1 MHz.
|
||||
|
||||
| Peripheral | Function | ESP32 GPIO | Notes |
|
||||
| Peripheral | Functional Pin | ESP32 GPIO | Notes |
|
||||
| :--- | :--- | :---: | :--- |
|
||||
| **ST7789 Display** (SPI2) | SCL (Clock) | **18** | SPI2_HOST (VSPI) clock |
|
||||
| | SDA (MOSI) | **23** | SPI2_HOST MOSI |
|
||||
| | CS | **21** | Dedicated Chip Select (non-strapping pin) |
|
||||
| | DC | **19** | Data / Command select (non-strapping pin) |
|
||||
| | RST | **4** | Display Reset |
|
||||
| **ST7789 Display** (SPI2) | SCL (Clock) | **GPIO 18** | SPI2_HOST (VSPI) Clock |
|
||||
| | SDA (MOSI) | **GPIO 23** | SPI2_HOST MOSI |
|
||||
| | CS | **GPIO 21** | Dedicated Chip Select (non-strapping) |
|
||||
| | DC | **GPIO 19** | Data / Command Select (non-strapping) |
|
||||
| | RST | **GPIO 4** | Display Reset |
|
||||
| | VCC / GND | 3.3V / GND | Display logic & backlight power |
|
||||
| **MFRC522 RFID** (SPI3) | SCK | **16** | SPI3_HOST (HSPI) clock |
|
||||
| | MOSI | **17** | SPI3_HOST MOSI |
|
||||
| | MISO | **13** | SPI3_HOST MISO |
|
||||
| | SDA (CS) | **26** | Dedicated Chip Select |
|
||||
| | RST | **22** | Hard reset line |
|
||||
| **MFRC522 RFID** (SPI3) | SCK | **GPIO 16** | SPI3_HOST (HSPI) Clock |
|
||||
| | MOSI | **GPIO 17** | SPI3_HOST MOSI |
|
||||
| | MISO | **GPIO 13** | SPI3_HOST MISO |
|
||||
| | SDA (CS) | **GPIO 26** | Dedicated Chip Select |
|
||||
| | RST | **GPIO 22** | Reader Reset |
|
||||
| | 3.3V / GND | 3.3V / GND | **Attach 2200 µF capacitor across these pins!** |
|
||||
| **EC11 Rotary Encoder** | CLK (A) | **32** | Quadrature A (interrupt-driven, internal pull-up) |
|
||||
| | DT (B) | **33** | Quadrature B (internal pull-up) |
|
||||
| | SW (Button) | **25** | Push button (active LOW, internal pull-up) |
|
||||
| **Indicators** | WS2812B DIN | **27** | RMT peripheral Tx (supply 5V to VDD, common GND) |
|
||||
| **Audio** | Buzzer SIG | **14** | LEDC PWM channel |
|
||||
| **EC11 Rotary Encoder** | CLK (A) | **GPIO 32** | Quadrature A (interrupt-driven) |
|
||||
| | DT (B) | **GPIO 33** | Quadrature B |
|
||||
| | SW (Button) | **GPIO 25** | Push button (active LOW) |
|
||||
| **Audio** | Buzzer SIG | **GPIO 14** | LEDC PWM audio output |
|
||||
|
||||
### Wiring Diagram
|
||||
#### Wiring Diagram
|
||||
```
|
||||
ESP32-WROOM-32
|
||||
┌────────────────────────────┐
|
||||
@@ -182,13 +151,12 @@ The display and RFID reader use **two separate SPI host controllers** to prevent
|
||||
│ 13 ── MISO ────┼──┘ │
|
||||
│ 26 ── SDA(CS) ─┘ │
|
||||
│ 22 ── RST ─┐ │
|
||||
│ 21 ── CS ──┼───────┤ ST7789 (7-pin, SPI2_HOST)
|
||||
│ 21 ── CS ──┼───────┤ ST7789 Display (SPI2_HOST)
|
||||
│ 19 ── DC ──┤ │ SCL=18, SDA=23, CS=21, DC=19, RST=4
|
||||
│ 4 ── RST ─┘ │ VCC=3.3V, GND=GND
|
||||
│ 18 ── SCL ─────────┘
|
||||
│ 23 ── SDA ─────────
|
||||
│ 32 ── CLK ────────┤ EC11 Rotary Encoder (CLK=32, DT=33, SW=25)
|
||||
│ 27 ── Din ────────┤ WS2812B LED (GPIO 27, 5V rail)
|
||||
│ 14 ── SIG ────────┤ Piezo Buzzer (GPIO 14)
|
||||
└────────────────────────────┘
|
||||
│ │
|
||||
@@ -200,57 +168,93 @@ The display and RFID reader use **two separate SPI host controllers** to prevent
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
> **Note on Flashing:** GPIO21 (CS) and GPIO19 (DC) are deliberate non-strapping pins. The ST7789 display can remain fully connected during `idf.py flash`.
|
||||
---
|
||||
|
||||
### Flash Partition Layout (4MB Dual-OTA)
|
||||
|
||||
Configured in [`partitions.csv`](file:///c:/Users/rsben/Desktop/Rasmus/Programmering/espMTG/partitions.csv):
|
||||
|
||||
| Partition | Type | SubType | Offset | Size | Purpose |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| `nvs` | data | nvs | `0x9000` | 16 KB | Wi-Fi credentials & system settings |
|
||||
| `otadata` | data | ota | `0xd000` | 8 KB | Active OTA slot pointer & rollback state |
|
||||
| `phy_init` | data | phy | `0xf000` | 4 KB | RF calibration data |
|
||||
| `ota_0` | app | ota_0 | `0x10000` | 1,600 KB | Primary firmware slot |
|
||||
| `ota_1` | app | ota_1 | `0x1a0000` | 1,600 KB | Secondary firmware slot |
|
||||
| `storage` | data | littlefs | `0x330000` | 832 KB | LittleFS flash database (`/spiffs`) |
|
||||
|
||||
* **Rollback Safety:** Uses `CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y`. On first boot of a new firmware version, the app must call `esp_ota_mark_app_valid_cancel_rollback()`. If an update is corrupt or crashes on boot, the bootloader automatically reverts to the previous working slot.
|
||||
|
||||
---
|
||||
|
||||
## 💻 Software Setup & Build
|
||||
### FreeRTOS Dual-Core Architecture
|
||||
|
||||
### 1. Requirements
|
||||
- **ESP-IDF v5.x** (v5.0 through v5.5 supported):
|
||||
```powershell
|
||||
. C:\Espressif\frameworks\esp-idf-v5.5\export.ps1
|
||||
idf.py --version
|
||||
```
|
||||
* **Core 0 (Networking, Storage & Hardware I/O):**
|
||||
* `rc522_polling_task`: Continuously polls the MFRC522 reader.
|
||||
* `net_task`: Manages Wi-Fi auto-reconnection and Scryfall HTTPS API downloads (`esp_http_client`).
|
||||
* `httpd`: Runs the embedded web server (serves the pairing SPA and REST APIs).
|
||||
* `ota_check` / `ota_update`: Queries Gitea release API and streams firmware updates into the inactive OTA bank.
|
||||
* **Core 1 (User Interface & Rendering):**
|
||||
* `ui_task`: Drives the LVGL display subsystem, rotary encoder state machine, and screen animations at 40 FPS without I/O stutter.
|
||||
|
||||
### 2. Configure Wi-Fi
|
||||
Configure home Wi-Fi credentials for automatic Scryfall fetching:
|
||||
---
|
||||
|
||||
### Software Setup & Build Commands
|
||||
|
||||
#### 1. Prerequisites
|
||||
Install [ESP-IDF v5.x](https://docs.espressif.com/projects/esp-idf/en/v5.5/esp32/get-started/):
|
||||
```powershell
|
||||
. C:\Espressif\frameworks\esp-idf-v5.5\export.ps1
|
||||
idf.py --version
|
||||
```
|
||||
|
||||
#### 2. Configuration
|
||||
Configure Wi-Fi credentials and Gitea instance details:
|
||||
```powershell
|
||||
idf.py menuconfig
|
||||
# Navigate to: MTG RFID Companion -> Wi-Fi SSID & Password
|
||||
# Navigate to: "MTG RFID Companion"
|
||||
# - Wi-Fi SSID & Password
|
||||
# - Gitea instance base URL (e.g. https://git.example.com)
|
||||
# - Gitea repository owner & repo name
|
||||
```
|
||||
*(Or edit `sdkconfig.defaults.esp32` directly).*
|
||||
|
||||
### 3. Build & Flash
|
||||
#### 3. Build & Flash (Initial USB Provisioning)
|
||||
```powershell
|
||||
idf.py set-target esp32
|
||||
idf.py build
|
||||
idf.py -p COM4 flash monitor
|
||||
idf.py -p COM4 erase-flash flash monitor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📂 LittleFS Storage Structure
|
||||
### Automated CI / Gitea Actions Workflow
|
||||
|
||||
The repository includes a Gitea Actions workflow in [`.gitea/workflows/releases.yml`](file:///c:/Users/rsben/Desktop/Rasmus/Programmering/espMTG/.gitea/workflows/releases.yml):
|
||||
* **Trigger:** Pushing any version tag (e.g. `git tag v1.0.1 && git push origin v1.0.1`).
|
||||
* **Environment:** Official `docker://espressif/idf:v5.5` container.
|
||||
* **Artifacts:** Compiles the firmware and automatically attaches `mtg-rfid-companion.bin` (for wireless OTA updates) and `full-flash-bundle-*.tar.gz` (for USB cable flashing) directly to the Gitea release.
|
||||
|
||||
---
|
||||
|
||||
### LittleFS Storage Structure
|
||||
|
||||
All local card details and artwork are stored in LittleFS mounted at `/spiffs`:
|
||||
```
|
||||
/spiffs/
|
||||
├── mappings.json UID -> Card Name JSON map
|
||||
├── mappings.json # Scanned UID -> Card Name mapping table
|
||||
└── cards/
|
||||
├── <UID>.json Scryfall attributes (Mana, Type, Oracle, P/T)
|
||||
└── <UID>.jpg Cached 200x110 Baseline JPEG art crop
|
||||
├── <UID>.json # Cached Scryfall card data (Mana, Oracle, Type, P/T)
|
||||
└── <UID>.jpg # Cached 200x110 Baseline JPEG art crop
|
||||
```
|
||||
|
||||
The `storage/` repository directory is compiled directly into the LittleFS partition image at build time (`littlefs_create_partition_image`).
|
||||
|
||||
---
|
||||
|
||||
## ❓ Troubleshooting
|
||||
### ❓ Troubleshooting
|
||||
|
||||
| Symptom | Cause & Solution |
|
||||
| :--- | :--- |
|
||||
| **ESP32 reboots when scanning card** | 3.3V rail voltage sag caused by the MFRC522 RF transmitter. **Add a 2200 µF capacitor** directly across the MFRC522 VCC and GND pins. |
|
||||
| **Display colors inverted (blues look red)** | Check `flags.swap_color_bytes = 1` in JPEG config and `esp_lcd_panel_invert_color()` in `display_manager.c`. Panel clones differ between RGB and BGR. |
|
||||
| **Card shows "PARSE FAILED"** | Corrupt card JSON in cache. The firmware auto-purges corrupt entries on reboot, or use **Deck Storage -> Wipe** to reset. |
|
||||
| **Scanned card shows previously paired card** | Re-pairing a card now automatically purges the old cache. Ensure firmware is up to date, or clear via **Deck Storage -> Wipe**. |
|
||||
| **Art crop doesn't show** | Ensure device has Wi-Fi connectivity to download from Scryfall. Images are cached locally on flash once downloaded. |
|
||||
| **Flash fails: `Failed to connect to ESP32`** | Make sure no other terminal is monitoring COM4 (`Ctrl + ]` to exit monitor). If using older GPIO15/2 wiring, hold the BOOT button during connect. |
|
||||
| **Device reboots when scanning a card** | Power rail sag caused by the RF transmitter. **Solder a 2200 µF capacitor** directly across the MFRC522 VCC and GND pins. |
|
||||
| **Display colors inverted (blues look red)** | Check `flags.swap_color_bytes = 1` in JPEG config and `esp_lcd_panel_invert_color()` in `display_manager.c`. |
|
||||
| **Card displays "Could not fetch card"** | Device is unable to reach Scryfall. Verify your home Wi-Fi credentials in `menuconfig` or verify card spelling on the web pairing page. |
|
||||
| **Router displays device name as "espressif"** | Hostname is set to `mtg-companion`. Clear DHCP lease on your router or reboot the ESP32 after connecting. |
|
||||
| **Flash fails: `Failed to connect to ESP32`** | Ensure no serial monitor is holding COM4 open (`Ctrl + ]` to exit monitor). Hold the device BOOT button while plugging into USB. |
|
||||
Reference in New Issue
Block a user