Commit Graph
18 Commits
Author SHA1 Message Date
mangavalkandClaude Opus 5.5 2b1ac12ed7 Add a web UI to the clock firmware
- Web UI on port 80: live view of the display, choose the page (clock or
  a bitmap), bitmaps (list, show, live, edit, delete), draw / image upload
  with conversion in the browser, live mode, settings, Home Assistant
- Live view from a shadow buffer in the BROSE9323 driver (shownPixel)
- Settings in NVS with the original behaviour as defaults: schedule times,
  quarter hours, yawning Pikachu, No WiFi screen, flip time, status LED,
  Home Assistant broker (restart on change)
- Bitmaps on LittleFS; new 320 KB partition, ota slots now 1.31 MB
- DisplayController: pages, live mode, settings; app.cpp holds the objects
- README for the recovery app; docs for the web UI
- Tests: settings, time parsing, bitmap format and names, schedule with
  settings, pages and live mode (95 total)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:52:34 +02:00
mangavalkandClaude Opus 5.5 c9e0800e36 Show status messages on the display
- Clock firmware: 'Connecting to WiFi...' and 'Getting the time...' at
  boot, 'Crashed!' in the OTA-only modes, and 'No WiFi' with the time
  when WiFi is down for over a minute (new DisplayController screen)
- Recovery app: shows its reason, the setup WiFi name, or its IP address,
  then powers the display off (flipdots keep the image)
- StatusScreen and drawTextLines shared by both apps
- Driver: ESP begin() no longer draws 'ESP Connected'
- Tests: No WiFi screen, short reason texts (70 total)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:34:04 +02:00
mangavalkandClaude Opus 5.5 4749f9e596 Add ESP32 recovery app with WiFi setup portal
- New flash layout (partitions.csv): factory = recovery app, ota_0/ota_1 =
  clock firmware; esp32_usb uploads to ota_0 so it never overwrites it
- src/recovery: WiFi + OTA + web page only. Opens the password protected
  'FlipDot-Setup' AP with a captive portal when WiFi fails, lets you pick
  another WiFi (stored in NVS, used by both apps), start the clock or stay
- Recovery is started when the clock firmware can't connect to WiFi,
  crashes 3 times, after 3 quick power cycles, from a new Home Assistant
  button, or by the bootloader when no clock firmware works
- Shared NVS store and boot switching in src/esp32/system
- Clock firmware keeps working on the old flash layout (falls back to
  OTA-only safe mode)
- README: recovery app, one-time USB installation; tests: 65 total

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:21:04 +02:00
mangavalkandClaude Opus 5.5 ddbdf7e65f Keep ESP32 OTA reachable whatever the firmware does
- Rollback: override verifyRollbackLater() so a new OTA image stays
  pending until it ran 60 s with WiFi; any earlier restart rolls back
  (the Arduino core marked every image valid at boot before)
- Task watchdog (30 s) on loop(), paused during OTA uploads
- Crash counter in RTC memory: OTA-only window after a crash, 10 min
  safe mode (WiFi + OTA only) after 3 crashes in a row
- Restart when WiFi stays down for 10 min
- Home Assistant sensor 'FlipDot Display Firmware' with version/state
- logic/boot_policy with tests (60 tests total)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:05:06 +02:00
mangavalkandClaude Opus 5.5 683a47c055 Restructure ESP32 firmware into modules, fix bugs, add tests
Structure (src/esp32/):
- logic/: DisplayController, schedule, power timer, LED pattern; pure C++
- display/: FlipdotFrames and bitmaps
- nano_link/: NanoLink (relay, serial, READY, bootloader) and flash bridge
- net/: WiFi/OTA/panic window, Home Assistant
- config.h with all settings; libs.h (globals in a header) removed

Bug fixes:
- Home Assistant switches now report their state back and start as ON
- loop() no longer blocks: WiFi.waitForConnectResult() (up to 60 s
  without WiFi) and getLocalTime() (5 s before NTP sync) were called
  every iteration
- Power switch off now powers off after 1 s even when a 30 s countdown
  is already running
- millis() overflow safe power-off timer; no frame catch-up bursts
- No garbage time string before NTP sync; 'Connecting...' stays instead
- Frames are only sent when the screen changes instead of every second
- Reset reasons are logged once instead of every 100 ms
- Removed dead code (unused fonts, WiFiMulti, rotated bitmap, ...)

Tests: new test_esp32 environment (26 tests); native renamed to test_nano

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:56:32 +02:00
mangavalkandClaude Opus 5.5 cefb76c1ad Support both Nano bootloaders for flashing over WiFi
- Uploader sends 'FLASH <baud>' first; the ESP32 restarts the Nano and
  bridges at that baud rate, then answers OK
- --baud=auto (default) tries 57600 (old ATmegaBOOT) then 115200 (Optiboot)
- Optional nano_reset GPIO (NPN to Nano RESET) pulses reset after power
  on, needed for Optiboot which skips the bootloader after a power cycle
- Clear errors for outdated ESP32 firmware and missing wires
- README: bootloader table, reset wire, troubleshooting

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:44:35 +02:00
mangavalkandClaude Opus 5.5 bea5b9daa1 Flash the Nano over WiFi through the ESP32
- ESP32: NanoFlashBridge on TCP port 2323. A connection power cycles the
  Nano into its bootloader and bridges TCP <-> Serial2 at 57600 baud; the
  clock pauses during the session, 10 s idle timeout
- tools/nano_net_upload.py: STK500v1 uploader over TCP (standard library
  only), with sync retries, write and read-back verification. avrdude 6.3
  net: ports are broken on Windows, so avrdude is not used
- New nano_ota environment: pio run -e nano_ota -t upload
- README: usage, requirements, troubleshooting; TODO for hardware test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:35:28 +02:00
mangavalkandClaude Opus 5.5 8415dee347 Add native unit tests for the Nano firmware
- New native environment: pio test -e native
- test/mocks: fake Arduino core, EEPROM and recording BROSE9323 driver
- test/test_nano: 25 tests covering every command, bitmaps, bad input,
  flip time storage and the periodic full redraw
- Board environments ignore tests so they are never uploaded

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:24:13 +02:00
mangavalkandClaude Opus 5.5 80f3f78152 Split Nano firmware into modules
- config.h: all constants and debug defines
- command_parser.h/.cpp: CommandParser class, one method per command
- settings.h/.cpp: EEPROM flip time storage
- main.cpp: setup/loop and the periodic full redraw only
- Full redraw now checks frameEnded() after the serial buffer is drained
- Drop the SPI/Adafruit_I2CDevice include workaround (not needed)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:19:25 +02:00
mangavalkandClaude Opus 5.5 75f677a2eb Move the Nano link to Serial2, update READMEs
- ESP32 talks to the Nano on UART2 (GPIO 17 TX / GPIO 16 RX); Serial (USB)
  is now free for debug output and boot messages no longer reach the Nano
- README: wiring table, actual schedule (clock from 08:00), TODO section
  for the rewiring

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:16:24 +02:00
mangavalkandClaude Opus 5.5 c67a90ba09 Document optional Nano TX to ESP RX wire
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:12:35 +02:00
mangavalkandClaude Opus 5.5 6e4d5e152b Power-cycle-friendly Nano boot and ESP relay handling
Nano / driver:
- No full on/off flip at boot; the first display() after boot is a forced
  full redraw instead, since the physical dot state is unknown
- Send READY when booted

ESP32:
- relayOn() only switches and waits when the relay was off, and waits for
  the Nano's READY (3 s timeout) instead of a fixed 3 s on every frame
- relayOff() ends Serial and releases the TX pin so the idle-high line no
  longer back-powers the Nano through its RX pin
- No display commands are sent while the relay is off
- Switching the relay on cancels a pending power-off countdown

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:12:28 +02:00
mangavalkandClaude Opus 5.5 f7ffcf4ab3 Fix README diagram alignment
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:07:35 +02:00
mangavalkandClaude Opus 5.5 2be4c20c66 Document that the relay also powers the Nano
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:07:16 +02:00
mangavalkandClaude Opus 5.5 f1dbc35ebd Rewrite Nano serial parser as line based, fix protocol bugs
- Commands run on '\n' instead of busy-waiting for a byte count, which
  fixes s/F/T waiting for the next command and P drawing 0xFF garbage
- Invalid bitmaps no longer leak their data as commands; bitmap data is
  streamed so full-screen bitmaps still fit
- Store flip time as uint16 with magic marker, validate 50-2000 us
- Overflow-safe millis() handling for the periodic refresh
- Run the full refresh only after D or when serial is idle, so incoming
  data is not lost while the redraw blocks
- Put the boot refresh measurement behind MEASURE_REFRESH
- Fix DEBUG hex output and use F() strings to save RAM
- Driver: direct mode now updates the old buffer instead of re-setting
  the new one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:06:49 +02:00
mangavalkandClaude Opus 5.5 459937352a Remove _hannio_splash startup bitmap from the BROSE9323 driver
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:00:56 +02:00
mangavalkandClaude Opus 5.5 65caecf9b2 Extend .gitignore and add .gitattributes for line endings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:57:42 +02:00
mangavalkandClaude Opus 5.5 0e4d39c47b Restructure into a single PlatformIO project with nano and esp32 targets
- Shared BROSE9323 driver in lib/, ESPSERIAL selected via build_flags
- Nano firmware in src/nano, ESP32 firmware in src/esp32
- Move WiFi/MQTT credentials to gitignored secrets.h (template provided)
- Pin home-assistant-integration to 2.1.0 from the registry
- Add esp32_usb environment for first flash / recovery
- Add READMEs and CLAUDE.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:55:15 +02:00