Files
MTGcompanion/README.md
2026-09-11 19:10:31 +02:00

14 KiB
Raw Blame History

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).


🌟 Feature Tour & Modes

The companion boots directly into an interactive, rotary-controlled interface designed specifically for tabletop MTG gameplay:

                  ┌──────────────────────────────┐
                  │      ★ MTG COMPANION ★       │
                  ├──────────────────────────────┤
                  │  > [1] Card Scanner       <  │
                  │    [2] Life & Counters       │
                  │    [3] Dice & Coin           │
                  │    [4] Commander Tax         │
                  │    [5] Token & Counters      │
                  │    [6] Deck Storage          │
                  │    [7] Device Info           │
                  └──────────────────────────────┘

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.

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.

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.

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).

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:

  • ST7789 Display: SPI2_HOST (VSPI) at 20 MHz.
  • MFRC522 Reader: SPI3_HOST (HSPI) at 1 MHz.
Peripheral Function 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
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
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

Wiring Diagram

        ESP32-WROOM-32
  ┌────────────────────────────┐
  │ 3V3  16 ── SCK ────────┐   │
  │ GND  17 ── MOSI ────┐  │   │
  │       13 ── MISO ────┼──┘   │
  │       26 ── SDA(CS) ─┘      │
  │       22 ── RST ─┐          │
  │       21 ── CS ──┼───────┤ ST7789 (7-pin, 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)
  └────────────────────────────┘
        │   │
      [2200 µF Cap]
        │   │
  ┌─────┴───┴──────────────────┐
  │ 3V3  GND                   │
  │ MFRC522 RFID Module (SPI3) │
  └────────────────────────────┘

Note on Flashing: GPIO21 (CS) and GPIO19 (DC) are deliberate non-strapping pins. The ST7789 display can remain fully connected during idf.py flash.


💻 Software Setup & Build

1. Requirements

  • ESP-IDF v5.x (v5.0 through v5.5 supported):
    . C:\Espressif\frameworks\esp-idf-v5.5\export.ps1
    idf.py --version
    

2. Configure Wi-Fi

Configure home Wi-Fi credentials for automatic Scryfall fetching:

idf.py menuconfig
# Navigate to: MTG RFID Companion -> Wi-Fi SSID & Password

(Or edit sdkconfig.defaults.esp32 directly).

3. Build & Flash

idf.py set-target esp32
idf.py build
idf.py -p COM4 flash monitor

📂 LittleFS Storage Structure

/spiffs/
├── mappings.json          UID -> Card Name JSON map
└── cards/
    ├── <UID>.json         Scryfall attributes (Mana, Type, Oracle, 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

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.