2026-10-12 23:55:15 +02:00
|
|
|
|
# Flipdot display: notes for Claude
|
|
|
|
|
|
|
|
|
|
|
|
A PlatformIO project with two firmware targets for an 84×19 Brose flipdot clock.
|
|
|
|
|
|
See README.md for the overview.
|
|
|
|
|
|
|
|
|
|
|
|
## Layout and build
|
|
|
|
|
|
|
|
|
|
|
|
- `platformio.ini` has the environments `nano`, `esp32` (OTA to 10.1.1.198) and
|
|
|
|
|
|
`esp32_usb` (COM11). The sources are split with `build_src_filter` (`src/nano/`,
|
|
|
|
|
|
`src/esp32/`).
|
|
|
|
|
|
- `lib/BROSE9323/` is the shared driver. Its behaviour depends on build flags set in
|
|
|
|
|
|
`platformio.ini`, not in the header:
|
|
|
|
|
|
- `ESPSERIAL` (ESP32): draw calls become serial commands.
|
|
|
|
|
|
- `FLIPDOT_PLCC_ADAPTER` (Nano, optional): alternative pinout.
|
|
|
|
|
|
- PlatformIO CLI is not on PATH. Run `~/.platformio/penv/Scripts/pio.exe run` (Git Bash)
|
|
|
|
|
|
or `$env:USERPROFILE\.platformio\penv\Scripts\pio.exe run` (PowerShell).
|
|
|
|
|
|
- If an ESP32 build fails with `No module named 'intelhex'`, run
|
|
|
|
|
|
`~/.platformio/penv/Scripts/python.exe -m pip install intelhex`.
|
|
|
|
|
|
- After any change, build both targets: `pio run -e nano -e esp32`.
|
|
|
|
|
|
|
|
|
|
|
|
## Constraints
|
|
|
|
|
|
|
|
|
|
|
|
- **Nano RAM is tight** (ATmega328P, 2 KB). The frame buffers are allocated with
|
|
|
|
|
|
`calloc`. Avoid `String`, large stack buffers and new globals in Nano code. Put constant
|
|
|
|
|
|
data in `PROGMEM`.
|
|
|
|
|
|
- The Nano and the ESP32 share one UART. On the ESP32, `Serial` is the display link, so
|
|
|
|
|
|
**don't print debug output on the ESP32's `Serial`**: the Nano would read it as
|
|
|
|
|
|
commands. The Nano ignores unknown command bytes, but text that starts with
|
|
|
|
|
|
s/S/F/D/P/B/R/T will be run as a command.
|
|
|
|
|
|
- `src/esp32/secrets.h` holds the real credentials and is gitignored. Never commit it.
|
|
|
|
|
|
Add new secrets to `secrets.example.h` as placeholders.
|
2026-10-13 00:07:16 +02:00
|
|
|
|
- The relay (ESP32 GPIO 13, `LOW` = on) powers both the panels and the Nano. Each time it
|
|
|
|
|
|
switches on, the Nano cold-boots: bootloader, then `begin()` flips every dot on and off.
|
|
|
|
|
|
Any data the ESP sends during that time is lost. The Nano keeps no state over a power
|
|
|
|
|
|
cycle except the flip time in EEPROM.
|
2026-10-12 23:55:15 +02:00
|
|
|
|
- Hardware is not available here. Builds can be checked, but runtime behaviour can't.
|
|
|
|
|
|
|
2026-10-13 00:06:49 +02:00
|
|
|
|
## Nano serial parser (`src/nano/main.cpp`)
|
2026-10-12 23:55:15 +02:00
|
|
|
|
|
2026-10-13 00:06:49 +02:00
|
|
|
|
- Line based and non-blocking: bytes are collected into a 64-character buffer and a
|
|
|
|
|
|
command runs when `\n` arrives. Bitmap (`B`) pixel data is the exception. It is drawn
|
|
|
|
|
|
while it arrives, so it can be longer than the buffer. Keep `loop()` free of busy-waits.
|
|
|
|
|
|
- A full redraw (`display(true)`) blocks for about 0.5 s, which overflows the 64-byte
|
|
|
|
|
|
serial receive buffer. Only run it when no data is expected: right after a `D`, or after
|
|
|
|
|
|
2 s with no serial data. The ESP sends one frame per second, ending with `D`.
|
|
|
|
|
|
- Flip time is stored in EEPROM as a magic word at address 0 and a `uint16_t` at
|
|
|
|
|
|
address 2. Values outside 50–2000 µs are rejected.
|
|
|
|
|
|
- The Nano doesn't send an acknowledgement. Whether the Nano's TX is wired to the ESP's RX
|
|
|
|
|
|
is unknown, so don't make the ESP wait for replies.
|
|
|
|
|
|
- To test the parser without hardware, compile `main.cpp` with g++ (Strawberry Perl
|
|
|
|
|
|
provides it at `C:\Strawberry\c\bin`) and mock headers for `Arduino.h`, `EEPROM.h` and
|
|
|
|
|
|
`BROSE9323.h`.
|
2026-10-12 23:55:15 +02:00
|
|
|
|
|
|
|
|
|
|
## Git
|
|
|
|
|
|
|
|
|
|
|
|
- Remote: https://mangavalk.com/mangavalk/Flipdot-display.git, branch `main`.
|