- Nano: B data is drawn fast enough for the serial line. A hex digit arrives
every 87 us; with a division and four drawPixel() calls per digit a lit
digit took about 105 us, so dense frames (all yellow, the panda bitmap)
overflowed the 64 byte receive buffer: frames not shown or wrong, "Line
too long", frame check repairs that failed the same way. Now the parser
counts columns and rows and BROSE9323::drawDots() sets the 4 dots
(about 20 us).
- ESP32: Power off and the start of the night draw the off image also when
slow mode had the power off already (it powers on for it, once)
- Tests: drawDots() against drawPixel(), off image in slow mode
- Version 2.19.3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Nano's periodic full redraw blocked for ~0.8 s. A frame that arrived
meanwhile overflowed its 64-byte serial buffer; lost bytes in a bitmap
shift the rest of the image (picture moved up), and diff frames never
repaired it.
- Nano: all drawing (frames, effects, the dot refresh) runs from update()
in ~1 ms slices; the refresh pauses while a frame is received or shown
- New commands: C (reply with the image checksum) and I (refresh minutes,
EEPROM)
- ESP32: NanoMonitor asks for the checksum after frames and sends the whole
image again on a mismatch, missing answer or Nano restart; counts ERR
replies. Periodic whole-image resync.
- Settings: "Dot refresh" and "Image resync" intervals (settings v5,
v4 records are migrated)
- System tab: loop timing, free memory, frame check counts
- test_driver: the real driver against a simulated panel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Text elements can scroll in a window at a set speed; clock, countdown and
stopwatch can show seconds. Moving pages are sent as instant frames (new
Nano command D1) and paced by the estimated flip time.
- Countdown to a date and time (smart, days, days + time, with seconds),
stopwatch (web UI, HA switch and reset button), image element (fixed or
by Home Assistant state), multiplier for HA values, degree sign (char 127)
in all fonts and the font converter.
- Page format version 2; version 1 pages are converted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home Assistant: remove the Clock switch (its entity is deleted on connect),
add an IP sensor and Mode / Off image dropdowns whose options follow the
saved bitmaps. Remove the built-in "Nintendo border" bitmap.
Off image: a bitmap (or blank) left on the dots when the display switches off.
Nano: pause after each flip pulse and repeat pulses for changed dots, both
stored in EEPROM (G/N commands). Refresh effects (E command): instant,
sparkle, wipe, rain, from the middle out, diagonal, spiral, flip all then
reveal, push and random, optionally only for small changes. Effects run in
steps from loop() so serial input keeps flowing.
Web UI: flip settings, refresh effect and test patterns under Settings; the
System tab shows why the ESP32 last restarted. Settings records from
versions 1 and 2 are migrated. Firmware 2.3.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
- 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>
- 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>
- 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>
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>
- 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>
- 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>