A split-flap character module — one cell of a Solari departure board, the kind that hung over Penn Station’s main concourse until 2019 and over most of Europe’s rail termini for a good deal longer. A drum of hinged cards, a motor, and an optical index that tells the controller which card is currently at the front. The drum turns one direction only, because the cards hang from it and gravity is the entire return mechanism.
The construction, because the animation is built on it
Each card carries halves of two different characters. Card K’s front face — the side you see once it has fallen into the lower window — is the bottom half of character K. Card K’s back face, the side you see while it is still standing up in the upper window, is the top half of character K−1.
So a module resting on a letter is showing you two separate pieces of card: the front of one below the seam and the back of another above it, printed at different times, lining up into one letter. Flip a single card and both halves change at once. That is why the thing works.
drawModule never composites a “current character”. It paints the top half of
the incoming character in the upper window — already uncovered, the instant
the standing card starts to move — the bottom half of the outgoing character
in the lower window, and then the card itself in between, showing its back face
while it is above the hinge and its front face once it has swung below. At θ=0
that is exactly the resting picture of the outgoing character; at θ=π it is
exactly the resting picture of the incoming one. The animation isn’t a
transition drawn between two states, it’s the mechanism, and the two resting
states fall out of it for free.
Three loops:
- flap — one advance, E to F, slowed far past life speed so both faces of the card are legible. Held at either end on a resting frame.
- seek — the module hunting a long way round the drum at the speed it actually runs, about twelve flaps a second. The blur is the honest one: at any instant exactly one card is in the air, so what an eye integrates is this card earlier in its swing plus the previous card finishing its own. The window fills with half-letters that belong to no letter.
- jam — a card caught on the stop at about 70 degrees, shuddering sideways in its slot against a motor that has no idea anything is wrong, because the index wheel sits downstream of the obstruction. A column of perfect letters with one square of nonsense in it: the failure everybody who ever waited under one of these has seen.
Everything is drawn from one routine at one glyph scale, so the sprite exports and the demo’s hundred and thirty board modules are the same code and cannot drift. The face is a hand-cut 5×8 — eight rows rather than the usual seven so the split lands between pixels rather than through one. B, S and 8 are where you can see the seam doing its work.
The hyphen is the one glyph that isn’t drawn where you’d draw it on paper. A centred bar is split by the gap and reads as an equals sign, which is how CROTON-HARMON becomes CROTON=HARMON on a board that is working perfectly, so it sits one row below the seam instead.
The demo: what the rattle actually is
A five-row board — time, destination, track, status — a hundred and thirty modules, on the real drum of forty positions. Press New departures and every module goes at once.
Getting from X to Y costs (Y − X) mod 40 flaps. Not |Y − X|, and never the
short way, because there is no short way. That single fact is the whole piece:
- The mean is 19.5 flaps per module, and half the modules on any given update are doing more work than a full half-turn of the drum for a change you would call small.
- The slowest module is the one that decides when the board goes quiet, and
it is almost never the one with the dramatic change. It’s whichever one drew a
character sitting just behind its old one — one position backwards is
thirty-nine flaps forwards. Watch the readout after a run: it is nearly always
something like
O→N, 39 flaps. The board is ringed around it while it fades. - Blanks are a drum position like any other, so the empty half of every destination field rattles on every update too.
The reversible toggle runs the same board on a drum that is allowed to turn
back — min(d, 40−d), which no such machine has ever done. The trace underneath
keeps the last run of each mode so you can put them side by side: the mean
halves, but what you actually see is the tail collapsing. One-way runs to
about 3.4 seconds; reversible is done in under two. Total flaps drop by roughly
half; the wait drops by more, because the wait was never the mean.
The counters in the readout are the closed forms, not measurements — mean
(N−1)/2 against N/4, worst 39 against 20, and the expected slowest of n
modules, which for a board this wide pins almost exactly to the worst case in
both modes. A wide board’s settle time barely depends on what changed. It
depends on how many modules there are, and then it stops depending on that too.
The status column is amber because real boards mixed flap colours by column,
and each ink is its own glyph sheet. Click any module to give it a single flap
by hand — the only way to watch one card at a speed the eye can follow.
Space for a new board, D to swap drums.
Reuse
source/one-way-round.mjs is framework-free and has no board in it: metrics,
makeAtlas, drawModule, plus stepsTo / stepToward for the drum, the 5×8
FONT, and the closed forms (meanSteps, maxSteps, settleQuantile). Point
it at any canvas at any integer glyph scale. demo/one-way-round.js is a
generated copy kept in sync by source/render.mjs (ADR-0002) — edit the
original.
node source/render.mjs # every PNG in export/, media/01–03, thumb
node scripts/screenshot-demo.mjs # media/04–05, and fails on any page error