Skip to content

Let the reader dim a QR, and give every QR the same two controls - #22

Merged
oroderico merged 3 commits into
mainfrom
qr-shade
Aug 17, 2026
Merged

Let the reader dim a QR, and give every QR the same two controls#22
oroderico merged 3 commits into
mainfrom
qr-shade

Conversation

@oroderico

Copy link
Copy Markdown
Owner

A white block on this panel can make a phone's exposure stop down until the code
stops resolving, and the backlight cannot fix it: it moves the whole screen
rather than the code's contrast against the room. Jade ships a five-step ramp for
the same reason, and on its ESP32 screen does not even default to white
(main/gui.c:88).

What changes

  • A QR's light half is drawn in one of five greys, white down to near-black
    and round again, starting at white — so a code nobody touches is drawn exactly
    as before. The dark modules never move: contrast is raised from one side only.
  • Every QR screen wears the same two controls: the way out, and a sun against
    the code's left edge that cycles the shade. Up and down move between them, the
    chord takes the highlighted one. The sun's disc is drawn in the current shade,
    so the glyph dims with the code; it is built from rectangles because both fonts
    here are ASCII and a symbol font is a dependency for one glyph.
  • BBQr frames no longer step by hand. A reader collects the parts across
    repeats, so a frame held still can never complete a scan — the feature was
    spending both keys on every animated screen to do nothing useful. Removing it
    frees them for the chrome and takes bbqr_step_part and the manual/auto split
    out. The cadence slows from 700 ms to 1000 ms to pay for what is lost.
  • The Compact SeedQR keeps up and down, because its stops are separate views
    (the code, the region map, the tiles meant to be hand-copied), not frames of
    one payload. The sun becomes one more stop past the last tile, leaving the view
    under it standing.
  • draw_qr_nav and its forward control are removed: nothing had drawn them since
    the address screen stopped handing off to a second screen.

Verified by

  • host self-test — new checks: the highlight reaches the sun on all five QR
    renderers, and one press moves the light field to one new colour and nothing
    else, with the ring closing on itself
  • both new checks were confirmed to fail when sabotaged (a screen made to ignore
    the cursor; the ramp made to wrap instead of report)
  • the layout assert was confirmed to fire
  • 52 Python tests, QR encoder smoke build under -Werror, clang ASan/UBSan
    self-test
  • firmware builds at 305,584 bytes — 58% of the 512 KiB audit ceiling, +480 on
    main

Not verified

No camera has judged any of this. The branch is flashed and the screens have
been walked, but whether a dimmer code actually scans better — and whether
1000 ms is the right cadence now that a frame cannot be held — are questions only
a phone in a real room answers. Both numbers are guesses, as the 700 ms before
them was. If the answer comes back "white always wins", this should be reverted
rather than kept for tidiness.

A white block on this panel can make a phone's exposure stop down until
the code stops resolving, and the backlight cannot fix it: it moves the
whole screen rather than the code's contrast against the room. The light
half of a QR is drawn in one of five greys now, white down to near-black
and round again, starting at white.

An address's QR carries a sun beside the code to cycle it - drawn from
rectangles, since both faces here are ASCII - whose disc takes the
current shade, so the glyph dims with the code.

Verified by: host self-test (one press moves the light field to one new
colour and nothing else, the ring closes, and the highlight travels to
the sun - confirmed failing when the sun ignores the cursor), 52 Python
tests, QR smoke, ASan/UBSan self-test, firmware at 305520 bytes. Not
flashed; no camera has judged it.
The shade control could not reach the animated codes: up and down were
stepping BBQr frames. Manual stepping goes - a reader collects the parts
across repeats, so a held frame never completes a scan - and the cadence
slows to 1000ms. The Compact SeedQR's views are not frames, so there the
sun becomes one more stop past the last tile. draw_qr_nav goes too;
nothing had drawn it.

Verified by: host self-test (the highlight reaches the sun on all five QR
renderers, confirmed failing when one ignores the cursor), 52 Python
tests, QR smoke, ASan/UBSan self-test, firmware at 305536 bytes. Not
flashed.
A taproot address does not fit beside its code and falls back to the
plain QR, which draws the same chrome as every other one - so it was
drawing a sun that answered nothing, on the value hardest to scan. It
now takes the same two keys as the rest.

Two things the chrome left behind: draw_qr_control's position and
direction have been frozen since the forward control went, so it goes
back to being the one control it draws; and the gap between the sun and
the code, a bare 3, is named and pinned. A code is never wider than the
display is tall, so the sun's box can never reach the back arrow - a
static assert says so, since two boxes overlapping would draw quietly
rather than fail.

Verified by: host self-test, 52 Python tests, QR smoke, ASan/UBSan
self-test, firmware at 305584 bytes. The assert was confirmed to fire.
@oroderico
oroderico merged commit 71a7204 into main Aug 17, 2026
3 checks passed
@oroderico
oroderico deleted the qr-shade branch August 17, 2026 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant