fix(13e6): 180° rotate setup screens for ribbon-at-bottom mounting

Matches the server-side V2 physicalRotationDegrees=180° introduced in
pictureFrame-webApp@b355572. The setup screens are firmware-drawn (not
server-rendered) so they need their own compensation:

- scripts/gen_screens_13e6.py rotates the PIL image 180° in save_bin()
  before packing to 4bpp; preview PNGs reflect the rotated layout too.
- All three bg .bins regenerated (ap_bg, ap_bg_retry, setup_bg).
- epd_driver.cpp QR overlay coords updated to the post-rotation
  positions (AP 642,590 → 40,492; Setup 313,750 → 313,276).
- PANEL_FW_VERSION → v1.0.2

To deploy: pio run -e <env> -t upload AND pio run -e <env> -t uploadfs
so the rotated .bins land in LittleFS alongside the new code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 13:19:52 -04:00
parent fc1367fc55
commit 55ee5aa95c
9 changed files with 24 additions and 8 deletions
+14 -4
View File
@@ -564,6 +564,12 @@ def gen_setup():
# ── Save ─────────────────────────────────────────────────────────────────────
def save_bin(img, path, preview_path):
# Physical mount compensation: 13.3" panel ships ribbon-at-bottom of
# portrait, opposite the scan-zero corner. Rotate 180° before packing
# so the .bin's scan order maps to a right-side-up image on the panel.
# Server-side render does the same — see DeviceModel::physicalRotationDegrees().
img = img.rotate(180)
data = pack(img)
with open(path, "wb") as f:
f.write(data)
@@ -593,7 +599,11 @@ if __name__ == "__main__":
print("Generating setup screen…")
save_bin(gen_setup(), f"{out_dir}/setup_bg.bin", f"{out_dir}/setup_bg_preview.png")
print()
print("QR overlay constants — keep these in sync with epd_driver.cpp:")
print(f" AP_QR_X={AP_QR_X}, AP_QR_Y={AP_QR_Y}, AP_QR_CELL={AP_QR_CELL}, AP_QR_PX={AP_QR_PX}")
print(f" SETUP_QR_X={SETUP_QR_X}, SETUP_QR_Y={SETUP_QR_Y}, "
f"SETUP_QR_CELL={SETUP_QR_CELL}, SETUP_QR_PX={SETUP_QR_PX}")
# Post-180°-rotation coords for firmware (.bin is rotated in save_bin).
rot_ap_x = W - AP_QR_X - AP_QR_PX
rot_ap_y = H - AP_QR_Y - AP_QR_PX
rot_setup_x = W - SETUP_QR_X - SETUP_QR_PX
rot_setup_y = H - SETUP_QR_Y - SETUP_QR_PX
print("QR overlay constants (POST-180°-rotation) — keep these in sync with epd_driver.cpp:")
print(f" AP qr_x={rot_ap_x}, qr_y={rot_ap_y}, cell={AP_QR_CELL}, px={AP_QR_PX}")
print(f" Setup qr_x={rot_setup_x}, qr_y={rot_setup_y}, cell={SETUP_QR_CELL}, px={SETUP_QR_PX}")