# AGENTS.md — MTG RFID Companion (ESP-IDF) > **Context for AI Agents & Assistant Tools:** > This file outlines the architecture, coding guidelines, dependencies, hardware constraints, and build procedures for the **MTG RFID Companion** project. Read this completely before generating code, refactoring, or suggesting dependencies. --- ## 1. Project Overview The **MTG RFID Companion** is a hand-held hardware utility for Magic: The Gathering players. It uses an **ESP32** microcontroller running **ESP-IDF v5.x (FreeRTOS)** to scan RFID/NFC tags embedded in card sleeves, query card data locally or via Scryfall's API, render data to a 2.0" ST7789 TFT LCD (240x320), and host a local registration web server. --- ## 2. Target Hardware & Specifications * **MCU:** ESP32-WROOM-32 (Dual-Core Xtensa LX6, 240MHz, 520KB SRAM, 4MB Flash). *No external PSRAM.* * **Display:** 2.0" ST7789 SPI TFT LCD (240x320 resolution, RGB565 format). Full-screen JPEG wallpapers supported via tjpgd decoder. * **RFID Reader:** MFRC522 (13.56 MHz, SPI Interface, ISO/IEC 14443A). * **Target Tags:** NTAG213 / NTAG215 micro FPC stickers or standard MIFARE ISO cards (7-byte or 4-byte UIDs). * **User Input:** EC11 Rotary Encoder with integrated push button. * **Storage:** On-chip SPI Flash partitioned with **LittleFS** (mounted at `/spiffs`, size ~1.5 MB). --- ## 3. Peripheral Wiring & GPIO Pinout > **CRITICAL:** Do NOT modify GPIO pin assignments in code generation unless explicitly instructed. SPI bus is shared between ST7789 and MFRC522. | Peripheral | Functional Pin | ESP32 GPIO Pin | Shared Bus / Notes | | :--- | :--- | :--- | :--- | | **Shared SPI** | SCK / MOSI / MISO | GPIO 18 / 23 / 19 | Shared SPI2_HOST (VSPI) | | **MFRC522 RFID**| CS (SDA) / RST | GPIO 5 / GPIO 22 | Dedicated CS & Reset | | **ST7789 Display**| CS / DC / RST | GPIO 15 / GPIO 2 / GPIO 4 | Dedicated CS, Data/Cmd & Reset | | **Rotary Encoder**| CLK / DT / SW | GPIO 32 / GPIO 33 / GPIO 25 | Active low / Interrupt driven | | **Indicators** | Neopixel (WS2812B) | GPIO 27 | RMT driver | | **Audio** | Piezo Buzzer | GPIO 14 | LEDC PWM channel | --- ## 4. Software Architecture & FreeRTOS Task Allocation The project strictly follows a **multithreaded, event-driven model** using FreeRTOS tasks and the ESP Event Loop. ### Core Core Split * **Core 0 (System, I/O & Network):** * `rc522_task`: Continuously polls RFID reader, emits events upon card detection. * `net_task`: Manages Wi-Fi reconnects, Scryfall HTTPS fetches (`esp_http_client`), and `esp_http_server`. * `storage_task`: Reads/writes JSON files to `/spiffs` via VFS. * **Core 1 (User Interface & Rendering):** * `ui_task`: Handles ST7789 display drawing using `esp_lcd` and rotary encoder inputs. Maintains UI frame rates without blocking Core 0 I/O. ### System State Machine State transitions must be managed cleanly using FreeRTOS Event Groups or Queue messaging: 1. `STATE_BOOT`: Hardware setup, LittleFS mount, Wi-Fi auto-connect. 2. `STATE_SCANNER`: Waiting for RFID tag read. 3. `STATE_CARD_VIEW`: Displaying fetched/cached card attributes (P/T, Mana, Oracle text). 4. `STATE_LIFE_COUNTER`: Interactive 20/40 life counter utilizing rotary encoder. 5. `STATE_REGISTRATION`: Local SoftAP mode (`192.168.4.1`) active to pair unknown UIDs with card names via web browser. --- ## 5. Storage Structure (LittleFS `/spiffs`) Do NOT assume an SD card is attached. All local database operations use standard C file I/O (`fopen`, `fread`, `fwrite`) over LittleFS. * `/spiffs/mappings.json` — Maps scanned UIDs to Card Names: ```json { "04A2B3C4": "Sol Ring", "04E1F2A3": "Atraxa, Praetors' Voice" } /spiffs/cards/[UID].json — Cached Scryfall card attribute details: JSON { "name": "Sol Ring", "mana_cost": "{1}", "type": "Artifact", "oracle": "Tap: Add CC.", "price_usd": "1.25" } 6. Coding Standards & Conventions When generating or editing code for this repository: Framework: Pure ESP-IDF v5.x (C99/C11 standard). Do NOT use Arduino.h headers, functions, or Arduino libraries (Serial.print, delay(), Wire, etc.). Error Handling: Always wrap ESP-IDF API functions in ESP_ERROR_CHECK() or handle errors gracefully using esp_err_t ret. Log errors via ESP_LOGE(). Memory Management: SRAM is tight (~520KB total, no PSRAM). Do NOT allocate huge static buffers on the FreeRTOS task stack. Allocate HTTP response buffers and cJSON trees dynamically on the heap (heap_caps_malloc(..., MALLOC_CAP_8BIT)), and always free them immediately after use. JSON Parsing: Use native cJSON. Check every pointer return for NULL before accessing object fields. Logging Tag: Define a static tag per source file: C static const char *TAG = "MODULE_NAME"; 7. Project Dependencies & Configuration Managed via idf_component.yml: abobija/rc522: SPI RFID reader driver. joltwallet/littlefs: LittleFS VFS port for ESP-IDF. espressif/esp_lcd: Official display subsystem (ST7789 controller driver). Build Commands Build Project: idf.py build Flash to Device: idf.py -p flash Monitor Logs: idf.py -p monitor Partition Table: Uses custom partitions.csv (Flash allocation: 2MB App, 1.5MB LittleFS data). 8. Guidance for AI Agents Generating Code When asked to build features: Write full, compile-ready C files (.c) and header files (.h) targeting ESP-IDF v5.x. When modifying hardware code: Cross-check the shared SPI bus configurations to prevent SPI2_HOST bus conflicts between ST7789 and MFRC522. When implementing network code: Use non-blocking esp_http_client requests running on a dedicated FreeRTOS task to keep screen rendering smooth.