Files
pictureFrame-firmware/platformio.ini
T
football2801 013e49d859 fix(13e6): partition + SPI corruption + bootstrap stay-awake
Three problems surfaced during the first 13.3" end-to-end run:

1) LittleFS IntegerDivideByZero on 200 → write /img.bin. Cause: the
   ~3.5 MB SPIFFS in default_16MB.csv can't fit three 960 KB setup
   screens + a 960 KB cached image (~3.84 MB). Switching to a custom
   partitions_13e6.csv with 24 MB LittleFS on the 32 MB flash.

2) Yellow wash across the panel on long SPI bursts. Cause: SPI DMA
   from a PSRAM-backed scratch buffer hits a cache-coherency window —
   the CPU's writes hadn't reached PSRAM yet when DMA read it. Push
   each half in 8 KB chunks through an internal-SRAM (DMA-coherent)
   scratch, and drop the bus clock to 4 MHz to match the 7.3"
   production speed.

3) Bootstrap window (no image yet) was deep-sleeping for 15 s between
   polls — each cycle a ~5 s ROM-boot + Wi-Fi reconnect, so the user
   waited ~20 s × N retries between scanning the setup QR and seeing
   their first photo land. Now normal_operation_impl returns early
   during bootstrap and main.cpp's normal_operation loops with a
   2 s delay, keeping Wi-Fi up. Once the first image arrives, the
   normal scheduled deep sleep takes over.

   Also fixes a related bug Matt called out: a transient TLS hiccup
   during bootstrap was hitting the 5xx fallback path and painting a
   full yellow fill over the green setup QR, leaving the user with
   no claim path. Criterion is now "does /img.bin exist?" (panel has
   something worth showing with a border) rather than "is currentImgId
   set?", so a fresh device with no cached image preserves the setup
   screen through transient network errors.

Diagnostic prints in the panel driver + [op] start/code lines in
normal_operation_impl that proved invaluable during bringup; leaving
them in for now. Tests updated for the new bootstrap semantics
(deep sleep no longer arms on bootstrap-cycle 204/404/5xx); 43/43
native tests pass, 7.3" production build stays byte-identical.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:50:36 -04:00

159 lines
5.4 KiB
INI

; pictureFrame firmware build environments.
;
; Layout: shared sources at src/ root + panel-specific implementations at
; src/panels/{vendor}/v{N}/. Each panel/version gets its own [env:...] block
; that sets dimensions, pins, and panel-id via build_flags, and selects its
; driver via build_src_filter. New panel = new env block + new
; src/panels/{vendor}/v{N}/ folder + new data/{vendor}-v{N}/ folder. No
; surgery to existing envs.
;
; Old envs preserved as historical snapshots — re-flashing units in the
; field stays a one-line `pio run -e <env> --target upload` command.
; data_dir is single project-wide in [platformio]; PlatformIO silently
; ignores it inside [env:…] blocks. To route uploadfs to the right
; LittleFS payload per panel (waveshare73-v1 vs waveshare13e6-v1), each
; env wires in scripts/data_dir.py via extra_scripts, which overrides
; PROJECT_DATA_DIR from $PIOENV before SCons evaluates uploadfs.
; The project-level default below keeps tooling that runs outside a
; specific env (e.g. raw `pio run`) pointed at the 7.3" payload.
[platformio]
data_dir = data/waveshare73-v1
; ── Production firmware: Waveshare 7.3" Spectra-6 + ESP32 dev breakout ──
[env:waveshare73-v1]
platform = espressif32
board = esp32dev
framework = arduino
upload_port = /dev/ttyUSB0
monitor_port = /dev/ttyUSB0
monitor_speed = 115200
board_build.filesystem = littlefs
extra_scripts = pre:scripts/data_dir.py
build_src_filter =
+<main.cpp>
+<panels/waveshare73/v1/>
build_flags =
-DEPD_WIDTH=800
-DEPD_HEIGHT=480
-DMAX_PANEL_WIDTH=800
-DPIN_SCK=18
-DPIN_MOSI=23
-DPIN_CS=5
-DPIN_DC=17
-DPIN_RST=16
-DPIN_BUSY=4
-DPANEL_ID=\"waveshare-7.3-spectra6\"
lib_deps =
ricmoo/QRCode@^0.0.1
; ── Hardware visual test: flash a single image from data/waveshare73-v1/img.bin ──
; No WiFi, no server.
; 1. pio run -e test-display --target uploadfs (upload data/)
; 2. pio run -e test-display --target upload (upload sketch)
[env:test-display]
extends = env:waveshare73-v1
build_src_filter =
+<test_display.cpp>
+<panels/waveshare73/v1/>
build_flags =
${env:waveshare73-v1.build_flags}
-DENV_TEST_DISPLAY
; ── Visual hardware tests for the sync-fail / no-WiFi border ──
; Reads the cached /img.bin from LittleFS and draws it with a yellow / red
; border. Sets NVS err_border=1 so the next normal-firmware boot exercises
; the recovery redraw via 304. Flow:
; 1. pio run -e sim-yellow --target upload (see yellow border)
; 2. pio run -e sim-red --target upload (see red border)
; 3. pio run -e waveshare73-v1 --target upload (back to normal; verifies 304 recovery)
[env:sim-yellow]
extends = env:waveshare73-v1
build_src_filter =
+<sim_border.cpp>
+<panels/waveshare73/v1/>
build_flags =
${env:waveshare73-v1.build_flags}
-DSIM_BORDER
-DSIM_BORDER_COLOR=COLOR_YELLOW
[env:sim-red]
extends = env:waveshare73-v1
build_src_filter =
+<sim_border.cpp>
+<panels/waveshare73/v1/>
build_flags =
${env:waveshare73-v1.build_flags}
-DSIM_BORDER
-DSIM_BORDER_COLOR=COLOR_RED
; ── Production firmware: Waveshare 13.3" Spectra-6 + ESP32-S3-ePaper-13.3E6 ──
; All-in-one board: ESP32-S3-WROOM-2-N32R16V (32MB OPI flash, 16MB OPI PSRAM),
; CH343 USB-serial on USB-C. PIN_CS aliases CS_M only to satisfy config.h's
; required-pin check — the driver uses CS_M / CS_S explicitly, never PIN_CS.
[env:waveshare13e6-v1]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
board_build.flash_size = 32MB
board_build.flash_mode = opi
board_upload.flash_size = 32MB
board_build.arduino.memory_type = opi_opi
board_build.filesystem = littlefs
; Custom partition layout: 4 MB app slots + 24 MB LittleFS on 32 MB flash.
; The 16 MB preset's ~3.5 MB SPIFFS is too tight — three 960 KB setup
; screens + a 960 KB cached /img.bin overflows it, and LittleFS panics
; in lfs_ctz_traverse (lfs.c:2988) with an IntegerDivideByZero
; mid-write rather than returning a clean "no space" error.
board_build.partitions = partitions_13e6.csv
extra_scripts = pre:scripts/data_dir.py
build_src_filter =
+<main.cpp>
+<panels/waveshare13e6/v1/>
build_flags =
-DEPD_WIDTH=1200
-DEPD_HEIGHT=1600
-DMAX_PANEL_WIDTH=1200
-DPIN_SCK=9
-DPIN_MOSI=46
-DPIN_CS=10
-DPIN_CS_M=10
-DPIN_CS_S=3
-DPIN_DC=11
-DPIN_RST=2
-DPIN_BUSY=12
-DPIN_PWR=1
-DPANEL_ID=\"waveshare-13.3-spectra6\"
-DBOARD_HAS_PSRAM
lib_deps =
ricmoo/QRCode@^0.0.1
; ── First-pixels smoke test for ESP32-S3-ePaper-13.3E6 ──
; Self-contained color-bar bringup, no LittleFS / no shared driver. Kept
; alongside the production env as a fallback for hardware diagnostics:
; if waveshare13e6-v1 misbehaves, this verifies the panel + SPI bus alone.
; pio run -e test-display-13e6 --target upload
[env:test-display-13e6]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
board_build.flash_size = 32MB
board_build.flash_mode = opi
board_upload.flash_size = 32MB
board_build.arduino.memory_type = opi_opi
build_src_filter =
+<test_display_13e6.cpp>
build_flags =
-DENV_TEST_DISPLAY_13E6
-DBOARD_HAS_PSRAM
; ── Native unit tests — no hardware, uses test/mocks/ ──
[env:native-test]
platform = native
lib_deps =
throwtheswitch/Unity@^2.6
build_flags = -DUNIT_TEST -std=c++17 -iquote test/mocks -iquote test -Itest/mocks -Itest
test_build_src = no