Skip to content

Module Firmware

Alex Van de Putte edited this page Jul 12, 2026 · 6 revisions

Module Firmware

Every split-flap module runs the SplitFlap Universal Firmware — one binary, flashed once to each module. Identity, calibration and the flap set are stored in the chip's EEPROM and assigned after flashing, so there is nothing to change per module before you upload.

Repo: github.com/avandeputte/SplitFlapUniversalFirmware · target: ATtiny1616 · toolchain: PlatformIO · programmer: SerialUPDI

Three stages take a bare module to a working cell: flash → provision → calibrate.


1. Flash

You need VS Code, the PlatformIO extension, and a SerialUPDI programmer — a cheap USB-to-serial adapter (CP2102, CH340, FT232 …) wired for UPDI: a single 470 Ω – 1 kΩ resistor between the adapter's TX and RX forms the UPDI data line, which connects to the chip's UPDI pin. The adapter does not power the board — power the module from its own supply.

  1. Install VS Code, then the PlatformIO IDE extension (it downloads the ATtiny toolchain on first build).
  2. Get the code and open the folder that directly contains platformio.ini (the highest-numbered version folder).
  3. Wire the programmer with the module powered off: UPDI data line → UPDI pin, adapter GND → module GND. Then power the module and plug in USB.
  4. Set upload_port in platformio.ini to your adapter's port (/dev/cu.usbserial-…, COM5, /dev/ttyUSB0).
  5. Build (the ✓ button, or pio run).
  6. Write fuses once per chip: pio run -t fuses. This sets the EESAVE fuse so the module's EEPROM (its ID, calibration and flap set) survives future reflashes. Skipping this means every upload wipes the module's identity.
  7. Upload (the → button, or pio run -t upload).
  8. Verify over the bus: sending m<ID>v returns the firmware version, ID and serial.

Every module gets the identical binary. platformio.ini is preconfigured (10 MHz internal clock, eesave on, SerialUPDI at 57600 baud).


2. Provisioning

A freshly flashed module has no ID (it reports 255) and doesn't answer numeric commands. Instead it advertises its serial number on the bus every 10–15 seconds. You assign it a bus ID with the included provision.py tool (run on the gateway host or any serial host), or — much easier — from the Gateway's Provision tab in the web UI, which does the same thing with a point-and-click flow.

The flow, either way:

  1. Discover — the tool/UI lists modules advertising their serials.
  2. Identify (optional) — home one module by serial so its reel spins; you can see which physical tile it is.
  3. Assign — give it a bus ID (0, 1, 2, …). The module writes the ID to EEPROM, acknowledges, and stops advertising.

Repeat for each cell, left to right, top to bottom, to match how you want the wall addressed. To start over, de-provision a module (or all) and it returns to advertising.

Because identity is assigned here — not compiled in — you flash the same binary to every module and never touch the IDE again after the first flash.


3. Calibration

Calibration teaches each module where "home" is and how far a full reel turn is, so the right flap lands dead center. Again this is easiest from the Gateway's Calibration tab (it has a guided wizard), but the underlying steps are:

  • Count steps per revolution — the module measures a full turn automatically.
  • Set the home offset — nudge so the blank flap sits centered at home.
  • (Optional) per-flap fine-tuning — for any flap that lands slightly off, drive to it and lock a corrected position into the map.
  • (Optional) custom flap set — if your reel isn't the default 64-flap set, tell the module its character string so text maps to the right flaps.

Once calibrated, the values live in EEPROM and survive reboots (and reflashes, thanks to the EESAVE fuse).


Diagnostics

The firmware has built-in self-tests, surfaced on the gateway's Modules tab (or over the bus). Run them in order — each depends on the one before:

  1. Snapshot — reset cause, boot count, supply voltage, EEPROM OK, current flap. No movement.
  2. Hall sensor test — one revolution; reports OK / stuck / dead / noisy / inverted.
  3. Mechanical test — several revolutions; reports OK / inconsistent / no motion.

The flap set

The default 64-flap reel is:

 (blank) A–Z  0–9  ! @ # $ & ( ) - + = ; : % ' . , / ? *  r o y g b p w

The seven lowercase letters at the end are the colour flaps (red, orange, yellow, green, blue, purple, white). The set is configurable per module and stored in EEPROM, so a reel with a different character layout still maps text correctly.


Next: Gateway →

Clone this wiki locally