diff --git a/README.md b/README.md index 3db5370..ce06f20 100644 --- a/README.md +++ b/README.md @@ -44,20 +44,16 @@ All code is **pure ESP-IDF v5.x (C) / FreeRTOS** — no Arduino. ### Pin map -| Peripheral | Function | ESP32 GPIO | Notes | -| :--- | :--- | :---: | :--- | > **Display and reader are on two separate SPI controllers:** the ST7789 on > **SPI2_HOST (VSPI)**, the MFRC522 on **SPI3_HOST (HSPI)** — so the panel and > the RFID reader never share bus timing. -### Pin map - | Peripheral | Function | ESP32 GPIO | Notes | | :--- | :--- | :---: | :--- | | **ST7789** (7-pin) — SPI2_HOST | SCL | **18** | SPI2 (VSPI) clock | | | SDA | **23** | SPI2 MOSI (data) | -| | CS | **15** | dedicated chip select | -| | DC | **2** | data/command | +| | CS | **21** | dedicated chip select (non-strapping pin) | +| | DC | **19** | data/command (non-strapping pin) | | | RST | **4** | panel reset | | | VCC / GND | 3.3V / GND | panel power (no separate LED pin) | | **MFRC522** — SPI3_HOST | SCK | **16** | SPI3 (HSPI) clock (own bus) | @@ -82,8 +78,8 @@ All code is **pure ESP-IDF v5.x (C) / FreeRTOS** — no Arduino. │ 13 ── MISO ────┼──┘ │ │ 26 ── SDA(CS) ─┘ │ │ 22 ── RST ─┐ │ - │ 15 ── CS ──┼───────┤ ST7789 (7-pin) - │ 2 ── DC ──┤ │ SCL = 18, SDA = 23 + │ 21 ── CS ──┼───────┤ ST7789 (7-pin) + │ 19 ── DC ──┤ │ SCL = 18, SDA = 23 │ 4 ── RST ─┘ │ VCC = 3V3, GND = GND │ 18 ── SCL ─────────┘ │ 23 ── SDA ───────── (display = SPI2) @@ -96,7 +92,11 @@ All code is **pure ESP-IDF v5.x (C) / FreeRTOS** — no Arduino. > **MFRC522 (own SPI3/HSPI bus):** SCK→16, MOSI→17, MISO→13, SDA(CS)→26, > RST→22, VCC→3.3V, GND→GND. It shares **no lines** with the display. > -> **ST7789 (SPI2/VSPI):** SCL→18, SDA→23, CS→15, DC→2, RST→4, VCC→3.3V, GND→GND. +> **ST7789 (SPI2/VSPI):** SCL→18, SDA→23, CS→21, DC→19, RST→4, VCC→3.3V, GND→GND. +> +> CS (GPIO21) and DC (GPIO19) are deliberately **not** strapping pins, so the +> panel can stay connected during `idf.py flash`. (The old GPIO15/GPIO2 +> assignment made the panel hold boot-strap lines and block flashing.) - Keep SPI signal runs short (< 10 cm) for reliable 20 MHz display transfers. - NTAG213/215 FPC stickers need to sit flat and close to the MFRC522 antenna. @@ -319,12 +319,12 @@ time (`littlefs_create_partition_image`), so a fresh flash already contains | Display = black / garbage | Check CS/DC/RST wiring; try toggling `esp_lcd_panel_invert_color` and `LCD_RGB_ELEMENT_ORDER_*` in `display_manager.c` | | Colors inverted | Same toggle as above — panel clones differ | | No UID printed on scan | Verify MFRC522 wiring, tag type (ISO14443A), antenna positioning; confirm `rfid: RC522 polling task pinned to Core 0` in the log | -| Boot log: `rc522: FIFO length missmatch` / `RTOS: RFID unavailable` | Reader self-test failed. Check the MFRC522 has 3.3V power (many clones have a separate power pin), CS=GPIO5 / RST=GPIO22, and SCK/MOSI/MISO=18/23/19. Try lowering `RC522_SPI_CLK_HZ` in `rfid_manager.c` (e.g. `2000000`); some clones need a slower clock on a shared bus | +| Boot log: `rc522: FIFO length missmatch` / `RTOS: RFID unavailable` | Reader self-test failed. Check the MFRC522 has 3.3V power (many clones have a separate power pin), CS=GPIO26 / RST=GPIO22, SCK/MOSI/MISO=16/17/13 on its own SPI3 bus. Try lowering `RC522_SPI_CLK_HZ` in `rfid_manager.c` (e.g. `1000000`); the skip-self-test option (`CONFIG_MTG_RFID_SKIP_SELFTEST`) lets scanning start anyway | | Wi-Fi never connects | Re-run `idf.py menuconfig`, confirm you replaced the `YOUR_...` placeholders | | Scryfall autocomplete shows nothing | The AP has no internet passthrough — the phone needs its own mobile data connection, or type the card name manually | | Can't reach 192.168.4.1 | Ensure your phone joined `MTG-Companion`, not a cached network | -| Flash fails: `Serial data stream stopped` / must unplug the display to flash | Disconnect the ST7789 (or power it down) during `idf.py flash`: this board's display shares strapping pins GPIO2/GPIO15 and the panel can pull the 3.3V rail / strap pins at reset, corrupting the serial link mid-write. Flash, then reconnect the display. | -| RFID step of boot log: `Buffers content missmatch`, buffer2 = `13 33 37` | The reader now answers (SPI OK) but glitches on the write/read race. `RC522_SPI_CLK_HZ` is already 2 MHz; lower further to `1000000` in `rfid_manager.c`, or check the MFRC522's separate power header gets a clean 3.3V and confirm MISO=GPIO19 is actually connected | +| Flash fails: `Serial data stream stopped` | If the ST7789 is wired with CS=GPIO15 / DC=GPIO2 (the old strap-pin assignment), disconnect/power-down the display during `idf.py flash` — the panel holds the boot-strap lines at reset and corrupts the serial link. With the current recommended wiring (CS=GPIO21, DC=GPIO19, both non-strapping) the display can stay connected. | +| RFID step of boot log: `Buffers content missmatch`, buffer2 = `13 33 37` | The reader answers (SPI OK) but the PCD self-test is flaky on clones. RST can stay unconnected (`-1`), the clock is already 1 MHz; confirm the MFRC522's dedicated power header gets a clean 3.3V and that MISO=GPIO13 is actually connected | | Card renders but no art | Card not cached yet — check `scryfall` log lines; art downloads are best-effort | | App grows near 2MB | mbedTLS + HTTP pulls are large; if needed, enable `CONFIG_MBEDTLS_CERTIFICATE_BUNDLE` (smaller) | diff --git a/main/hw_pins.h b/main/hw_pins.h index 03cf916..6e1a23f 100644 --- a/main/hw_pins.h +++ b/main/hw_pins.h @@ -13,11 +13,12 @@ /* SPI2_HOST (VSPI): dedicated to the ST7789 display. * On 7-pin ST7789 modules the display labels these SDA (MOSI) and - * SCL (SCK). */ + * SCL (SCK). MISO is unused (the display never reads the bus; the RFID + * reader lives on its own SPI3 bus). */ #define HW_SPI_HOST (SPI2_HOST) #define HW_SPI_SCK_GPIO (GPIO_NUM_18) /* display SCL */ #define HW_SPI_MOSI_GPIO (GPIO_NUM_23) /* display SDA */ -#define HW_SPI_MISO_GPIO (GPIO_NUM_19) /* unused by display; kept for bus */ +#define HW_SPI_MISO_GPIO (GPIO_NUM_NC) /* unused */ /* MFRC522 RFID reader - OWN SPI3_HOST (HSPI) bus, separate from the display. * Using a independent controller avoids any bus interference between the @@ -30,9 +31,14 @@ #define HW_RC522_RST_GPIO (GPIO_NUM_22) /* ST7789 display - 7-pin breakout: CS / DC / RST / SDA / SCL / GND / VCC. - * SDA and SCL share the SPI bus above (SCL=HW_SPI_SCK, SDA=HW_SPI_MOSI). */ -#define HW_LCD_CS_GPIO (GPIO_NUM_15) -#define HW_LCD_DC_GPIO (GPIO_NUM_2) + * SDA and SCL share the SPI bus above (SCL=HW_SPI_SCK, SDA=HW_SPI_MOSI). + * + * IMPORTANT: CS and DC are on NON-STRAPPING pins (GPIO21, GPIO19) so the + * panel never interferes with the ESP32 boot/flash. Keeping these on + * GPIO15/GPIO2 (strapping pins) blocks flashing while the display is + * connected, because the panel holds the strap lines at reset. */ +#define HW_LCD_CS_GPIO (GPIO_NUM_21) +#define HW_LCD_DC_GPIO (GPIO_NUM_19) #define HW_LCD_RST_GPIO (GPIO_NUM_4) /* EC11 rotary encoder */ diff --git a/main/main.c b/main/main.c index 58abfd4..406eade 100644 --- a/main/main.c +++ b/main/main.c @@ -20,9 +20,9 @@ void app_main(void) ESP_ERROR_CHECK(spi_bus_manager_init()); ESP_ERROR_CHECK(storage_manager_init()); - /* RFID comes BEFORE the display: the panel's init traffic plus the strap - * load on GPIO15/GPIO2 can glitch the shared SPI bus and make the MFRC522 - * self-test flake. Starting the reader on a quiet bus yields a clean test. */ + /* RFID comes BEFORE the display: the reader lives on its own SPI3 bus now + * (display owns SPI2), but initializing it before the panel's init traffic + * still gives the self-test the quietest possible bus timing. */ esp_err_t ret = rfid_manager_init(); if (ret != ESP_OK || rfid_manager_start() != ESP_OK) { ESP_LOGW(TAG, "RFID unavailable (%s) - continuing without card scanning", esp_err_to_name(ret));