# ESP32-P4 Tarot Touchscreen App ESP-IDF + LVGL tarot reading app for the Waveshare `ESP32-P4-86-Panel-ETH-2RO`. The first version is intentionally simple and stable: it draws unique tarot cards, renders card art on-device, persists settings in NVS, and does not require a microSD card. ## What Is Included - ESP-IDF project scaffold - LVGL home, reading, and settings screens - Full 78-card tarot deck data structure - 3-card and 8-card spread support - `esp_random()` card drawing with duplicate prevention - Upright and reversed cards - On-device generated card art - NVS-backed settings - Waveshare BSP display, touch, and backlight integration ## Project Layout ```text main/ app_main.c card_assets.c card_assets.h tarot_deck.c tarot_deck.h tarot_logic.c tarot_logic.h ui_main.c ui_main.h ui_settings.c ui_settings.h settings.c settings.h ``` ## Target Hardware This project targets the Waveshare `ESP32-P4-86-Panel-ETH-2RO`, part of the ESP32-P4 4-inch 86-panel family. Hardware assumptions: - 4-inch 720 x 720 IPS display - MIPI-DSI display interface - ST7703 display driver through Waveshare BSP - GT911 capacitive touch - microSD/TF slot over SDMMC/SDIO, currently not required by this app - Onboard 32 MB flash and 32 MB PSRAM - Ethernet, RS485, and 2 relay outputs present but not used by this app yet The board support is handled through the Waveshare ESP-IDF BSP component: ```yaml waveshare/esp32_p4_wifi6_touch_lcd_4b ``` The BSP initializes the MIPI display, GT911 touch, LVGL port, and backlight PWM. ## Build Install and export ESP-IDF first: ```sh . $IDF_PATH/export.sh idf.py set-target esp32p4 idf.py menuconfig idf.py build ``` This project declares LVGL through `main/idf_component.yml`, so ESP-IDF's component manager will fetch it during build. The Waveshare BSP is also declared there. It provides the display, touch, and backlight hardware integration for this panel. ## Flash And Monitor ```sh idf.py -p /dev/tty.usbmodemXXXX flash monitor ``` Replace the serial port with your board's port. ## On-Device Card Art No SD card is required. `main/card_assets.c` renders a compact tarot card visual directly with LVGL widgets using deck metadata compiled into firmware. This is deliberate for the first device build: - No filesystem dependency - No JPEG decoder dependency - No missing-image crash path - Fast startup on the panel The deck still keeps a filename-style asset key for each card. When you want full illustrated embedded artwork, replace `card_assets_create_card_art()` with a lookup table from card id to embedded LVGL image descriptors. ## Embedded Asset Naming Convention Major arcana: ```text 00_fool.jpg 01_magician.jpg 02_high_priestess.jpg 03_empress.jpg 04_emperor.jpg 05_hierophant.jpg 06_lovers.jpg 07_chariot.jpg 08_strength.jpg 09_hermit.jpg 10_wheel_of_fortune.jpg 11_justice.jpg 12_hanged_man.jpg 13_death.jpg 14_temperance.jpg 15_devil.jpg 16_tower.jpg 17_star.jpg 18_moon.jpg 19_sun.jpg 20_judgement.jpg 21_world.jpg ``` Minor arcana: ```text wands_ace.jpg wands_02.jpg wands_03.jpg wands_04.jpg wands_05.jpg wands_06.jpg wands_07.jpg wands_08.jpg wands_09.jpg wands_10.jpg wands_page.jpg wands_knight.jpg wands_queen.jpg wands_king.jpg cups_ace.jpg cups_02.jpg cups_03.jpg cups_04.jpg cups_05.jpg cups_06.jpg cups_07.jpg cups_08.jpg cups_09.jpg cups_10.jpg cups_page.jpg cups_knight.jpg cups_queen.jpg cups_king.jpg swords_ace.jpg swords_02.jpg swords_03.jpg swords_04.jpg swords_05.jpg swords_06.jpg swords_07.jpg swords_08.jpg swords_09.jpg swords_10.jpg swords_page.jpg swords_knight.jpg swords_queen.jpg swords_king.jpg pentacles_ace.jpg pentacles_02.jpg pentacles_03.jpg pentacles_04.jpg pentacles_05.jpg pentacles_06.jpg pentacles_07.jpg pentacles_08.jpg pentacles_09.jpg pentacles_10.jpg pentacles_page.jpg pentacles_knight.jpg pentacles_queen.jpg pentacles_king.jpg ``` ## Settings Saved In NVS - `reversed_cards_enabled` - `save_readings_enabled` - `brightness` - `theme` - `selected_spread` The `save_readings_enabled` flag is persisted and exposed in UI. Actual reading history storage is intentionally left for the next version so this first build stays stable.