Skip to content

expose the firmware's live LED registers, so a colour can be shown without storing it - #801

Open
ChampionDesigns wants to merge 4 commits into
decentespresso:mainfrom
ChampionDesigns:ben/led-preview
Open

expose the firmware's live LED registers, so a colour can be shown without storing it#801
ChampionDesigns wants to merge 4 commits into
decentespresso:mainfrom
ChampionDesigns:ben/led-preview

Conversation

@ChampionDesigns

Copy link
Copy Markdown
Collaborator

Summary

The Bengle firmware separates showing a colour from deciding one, and this app wired only
half of it.

FrontLEDColor / RearLEDColor            0x00803890/94   F_LEDStripColor
    sets the model and calls sendLEDColors() — the strip lights at once, and
    applyLEDsForGivenState recomputes these from the stored pair at the next
    sleep or wake transition. Showing a colour, not deciding one.

FrontLED{Awake,Sleep} / RearLED{Awake,Sleep}  0x00803898..A4  F_LEDStoreColor
    stores the colour, and applies it ONLY when the machine is already in the
    state that colour belongs to.

Only the stored four were declared. So every colour a client sent was a decision, and an asleep
colour could not be shown at all: written while the machine is awake it is kept and never lit,
which reads as the machine ignoring you. That is the complaint this fixes.

Base: main. Independent.

Design notes

  • frontLedColor / rearLedColor join BengleMmr at the firmware's own addresses.
  • previewLedStrip({front, back}) writes only the live pair. The stored palette is untouched,
    so ledStripState does not move — a preview cannot become a decision by accident.
  • POST /api/v1/machine/ledStrip/preview exposes it. Body {"frontStrip": "<12 hex>", "backStrip": "<12 hex>"}, either optional, in the same colour spelling GET /machine/ledStrip
    uses.

Linked Issue

N/A

Verification

  • flutter analyze — clean.
  • flutter testfull suite 3894 passed against current main, including
    bengle_led_preview_mmr_test.
  • dart format — clean on every changed file.
  • Verified on hardware. This change ships in the Decaid-Canary build Ben runs on his own
    machine, and has been exercised in normal use rather than only under test.

Impact

  • API: adds POST /api/v1/machine/ledStrip/preview, documented in assets/api/rest_v1.yml.
    Additive.
  • Compatibility: the stored-palette path is unchanged. A client that never previews sees no
    difference.
  • User-visible: a colour picker can finally show a colour without committing it, including an
    asleep colour on an awake machine.
  • Security: none.

Contributor Responsibility

AI-assisted development is allowed. The submitter remains responsible for the submitted work.

  • I have reviewed and understand all changes in this PR and take responsibility for their correctness, security, behavior, licensing, and provenance, including any AI-assisted or AI-generated work.

ChampionDesigns and others added 4 commits September 1, 2026 17:24
…thout storing it

The Bengle firmware already separates showing a colour from deciding one, and this
app wired only half of it.

  FrontLEDColor / RearLEDColor  0x00803890/94  F_LEDStripColor
      sets the model and calls sendLEDColors() — the strip lights at once, and
      applyLEDsForGivenState recomputes these from the stored pair at the next
      sleep or wake transition. Showing a colour, not deciding one.

  FrontLED{Awake,Sleep} / RearLED{Awake,Sleep}  0x00803898..A4  F_LEDStoreColor
      stores the colour, and applies it ONLY when the machine is already in the
      state that colour belongs to.

Only the stored four were declared here, so every colour a client sent was a
decision, and an asleep colour could not be shown at all: written while the machine
is awake it is kept and never lit, which reads as the machine ignoring you. That is
the whole of the complaint this fixes.

  - `frontLedColor` / `rearLedColor` join BengleMmr at the firmware's addresses.
  - `previewLedStrip({front, back})` writes only the live pair. The stored palette
    is untouched, so `ledStripState` does not move.
  - `clearLedStripPreview()` puts the strips back to the stored colours for the
    state the machine is in — a preview otherwise stands until the next sleep or
    wake, which may be hours.
  - `POST /machine/ledStrip/preview` and `.../preview/clear`, both in rest_v1.yml.

WHAT THIS DOES NOT CHANGE. The stored palette is still write-through: rest_v1.yml
already says so, and `commitLedStrip` is still the compatibility no-op it documents.

ONE THING FOR THE FIRMWARE, NOT FOR HERE. Both live registers are PERM_RWD, and
doModelAndDiskWriteVal writes the file on every write with PERM_DISK set — no
throttle, no dirty check. A picker dragging at frame rate therefore reaches the
filesystem on every frame, for a value the next transition recomputes anyway.
PERM_RWD -> PERM_RW on those two would end that; until then a client should coalesce.

dart format clean over the diff, flutter analyze clean, flutter test 3730 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two paths, one rule: a write that would change nothing is not made.

setLedStrip compares each zone against the held palette and writes only the zone
that moved. previewLedStrip remembers what each live register was last sent and
drops a frame that repeats it; setLedStrip clears that memory.

The reasoning, the flash cost and the firmware behaviour behind it are recorded in
doc/AI_BENGLE_NOTES.md under "LED palette", which is where AGENTS.md puts
rationale. The same section now also records what the live registers are for,
which the preview commit added without documenting.

Four new tests: re-saving the held palette writes nothing, a repeated preview
frame writes nothing, a moved preview frame is written, and a save forgets what
the strips were showing. The existing four-write assertion became a one-write
assertion, which is the behaviour change stated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cenario

CONTRIBUTING.md requires an end-to-end scenario for an API surface change and
doc/Api.md for a REST endpoint. The preview commit updated rest_v1.yml and
neither of the other two.

doc/Api.md gains the two preview rows, and its PUT row now says that only a zone
whose colour changed is written.

The bengle-led-strip scenario gains preview, its 400 for a body naming neither
strip, the repeated frame, and the clear, and its plain-DE1 step now covers all
six endpoints rather than four. The scenario says plainly that the skipped write
is not visible over HTTP and names the unit test that pins it, because MockBengle
reaches no MMR to count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts:
#	.agents/skills/decent-app/scenarios/bengle-led-strip.md
#	doc/Api.md
#	lib/src/models/device/impl/de1/unified_de1/led_strip_capability.dart
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