Viertes Analog-Profil neben den SM2135EH-Lampen: PWM-Kanaele R=PB13 (ch1),
G=PB16 (ch2), B=PB15 (ch3) bei 800 Hz, PIN-belegt aus der Original-Firmware
(qcl_build_config_lamp.h, HARDWARE_MOBL_LED_SHIELD). Kein CW/WW-Zweig:
ct_min == ct_max ist das Erkennungszeichen fuer 'weiss = RGB-Mischung',
nl_color.c gibt in diesem Fall alle drei Farbkanalgleich.
Neues Bauziel in allen Skripten; test_release zaehlt Dateizahlen jetzt aus
TARGETS statt hart 8/16.
LedFx und Verwandte denken in RGB-Pixeln: Ihr e131-Geraet schreibt je Pixel
genau drei Kanaele. Unsere Belegung beginnt mit einem Master-Dimmer, also landet
deren erstes Pixel auf Dimmer, R, G - ein rotes Effektbild (255,0,0) hiesse bei
uns "Dimmer 255, Rot 0, Gruen 0" und damit Dunkelheit. Von Hand eintragen liess
sich eine Lampe schon, sie zeigte aber Unsinn.
Der Dimmer bleibt fuer DMX-Pulte richtig, deshalb eine zweite Belegung statt
einer anderen: layout = "dimmer" (Vorgabe, unveraendert) oder "rgb" (R,G,B, drei
Slots auf jedem Board). Im rgb-Layout ist eine Lampe genau ein Pixel.
Ein Board ohne Farbkanaele bekommt trotzdem ein Farbtripel. Genommen wird der
groesste der drei Werte auf beide Weisskanaele: die Lampe folgt sichtbar der
Helligkeit des Effekts, ohne dass ein Farbmodell in den DMX-Pfad kommt - genau
das wird dort sonst bewusst vermieden.
Die Obergrenze fuer start_slot haengt jetzt am Layout (512 - slots + 1). Ein
Wechsel, der einen bisher zulaessigen start_slot unzulaessig macht, wird
abgelehnt statt still verschoben: eine Lampe, die nach einer Einstellung
woanders im Universe liegt als angegeben, findet niemand wieder.
Das neue Settings-Feld beginnt bei Offset 216, dem sizeof davor, und ist durch
eine eigene Pruefung zur Uebersetzungszeit und einen Migrationstest abgesichert -
derselbe Fallstrick, der beim Schlussreview fuer sacn_enabled gefunden wurde.
nl_engine_override_active() hat keinen Aufrufer im src/-Baum - die Firmware fragt
nl_dmx_active(). Die Funktion bleibt, weil die Engine-Tests sonst keinen Blick auf den
Override-Zustand haben; der Header sagt das jetzt, damit niemand nach dem Aufrufer sucht.
Der E1.31-Parser ueberliest Synchronisationsadresse und das Bit "force synchronization".
Fuer eine einzelne Lampe ist sofortige Ausgabe richtig - auf ein Sync-Paket zu warten
hiesse, bei einem Sender mit gesetzter Adresse dunkel zu bleiben. Der Kommentar nennt es
als bewusste Abweichung von E1.31-2018 Abschnitt 6.2.4.1.
Zwei neue Einstellungen, beide wie fade_in/fade_out ueber
POST /api/v1/device/state les- und schreibbar und sofort wirksam:
- transition_default (Voreinstellung 300 ms) fuellt die Transition fuer
Farb-, Weiss- und Helligkeitswechsel bei eingeschalteter Lampe, wenn der
Aufruf kein eigenes "transition" mitbringt. Beim Ein- und Ausschalten
behalten fade_in/fade_out weiterhin Vorrang.
- wake_on_change (Voreinstellung aus) schaltet die Lampe bei einer Farb-,
Weiss- oder Helligkeitsaenderung ein, wenn sie aus war. Ein
ausdrueckliches "on": false im selben Aufruf gewinnt immer.
Beide Felder haengen am Ende von nl_settings_t, damit bestehende Lampen
ueber die Laengentoleranz von read_rec() ihre echten Voreinstellungen
bekommen statt Nullen. nl_ctrl_set_fades() heisst jetzt
nl_ctrl_set_options().
Dazu ein Treiberfehler, der erst an der migrierten GU10 RGB auffiel: der
WY-Zweig von nl_sm2135eh_set() schrieb nur Header und WY-Daten, nie die
RGB-Datenregister. Der Chip behielt also die zuletzt gesetzte Farbe, und
bei einem direkten Wechsel Farbe -> Weiss (ohne Zwischenschritt ueber
dunkel) schaelte sie sich beim Ausblenden wieder frei. Der Header sendet
jetzt die - in Weiss immer nullwertigen - RGB-Daten mit.
Die Bruno-Collection zeigt Transition jetzt zusammen mit einem Farb- und
einem Weisswechsel im selben Aufruf und hat einen Request fuer die
beiden neuen Einstellungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Spec 8.2 verlangt, dass ein durch ein Update ausgelöster Neustart nicht wie ein
Stromausfall wirkt: Das Flag ota_pending wurde bisher nur geschrieben und beim
nächsten Boot wieder gelöscht, nl_boot_state() wendet aber weiterhin das normale
power_on_behaviour an. Eine eingeschaltete Lampe mit pob=off kam nach einem Update
aus zurück, mit pob=on umgekehrt.
nl_boot_state() bekommt dafür ein Argument after_ota; ist ein gespeicherter
Zustand vorhanden, wird er unverändert übernommen. Ohne gespeicherten Zustand
gelten weiterhin die normalen Regeln.
Hosttests: vier neue Fälle in test_boot_state.c (pob=off/on über ein OTA,
Sanitisierung bleibt aktiv, kein gespeicherter Zustand).