From 27beeef5ff58069b14acf1edb56d7a4224bee324 Mon Sep 17 00:00:00 2001 From: ewowi Date: Wed, 22 Jul 2026 21:40:40 +0200 Subject: [PATCH 1/9] Fix MoonLed whole-frame stall; harden LED-driver status + DMA budget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MoonI80 driver stalled to ~5 FPS after a second in whole-frame (non-expander) mode: a lost DMA end-of-frame interrupt left the bus marked busy forever, and only the ring path had recovery. Both paths now share one stall-recovery routine, so a lost interrupt self-heals on either. Also lands a batch of driver hardening: the classic-ESP32 i80 driver refuses an oversized frame with a clear message instead of crashing, the RMT and preview drivers report honest status, and expert-only controls are hidden by default. KPI: 16384lights | Desktop:755KB | tick:131/107/2/5/131/21/3/286/73/18/23/169/129/23/7/49us(FPS:7633/9345/500000/200000/7633/47619/333333/3496/13698/55555/43478/5917/7751/43478/142857/20408) | ESP32:1498KB | tick:3516us(FPS:284) | heap:58KB | src:194(45635) | test:137(24364) | lizard:160w Core: - platform_esp32_moon_i80: extracted finalizeStalledTransfer as the single stop-and-clear both the ring and whole-frame wait-timeout backstops call, and added the whole-frame backstop the driver lacked (a lost/coalesced EOF left busy stuck true with no recovery, wedging every later transmit to its full timeout). The whole-frame backstop stops the LCD + GDMA before draining its completion FIFO, and the EOF ISR now drops a firing against a structurally empty FIFO (fifoTail == fifoHead), so a late EOF after the drain can't hand out a spurious done token. finalizeStalledTransfer lives in the file's anonymous namespace alongside the other internal helpers. Light domain: - ParallelLedDriver: added frameFitsDmaBudget + a dmaBudgetBytes CRTP hook so a whole-frame driver whose DMA can't reach PSRAM refuses an oversized frame with an actionable status ("frame NKB over i80 DMA MKB: fewer lights/pin") instead of busy-waiting to a watchdog reset; the pinExpander control is hidden on drivers that don't support it. - MultiPinLedDriver: dmaBudgetBytes reports the classic-ESP32 i80 (I2S, internal-RAM-only) DMA budget so the frame-fit gate engages there; PSRAM-capable chips and the streaming ring report no bound. - RmtLedDriver: sized the symbol buffer to the driven light count rather than the whole window (was over-allocating ~550KB and failing on classic); report the resting "driving N of M lights" status on boot; loopbackTest is expert-mode only. - PreviewDriver: the adaptive-resolution downscale recovers multiplicatively (halves toward full res) instead of one step per clean run, and re-anchors to full res on prepare(), so a small grid settles in ~1s instead of ~10s. Tests: - unit_MultiPinLedDriver: frame-fit-gate and pinExpander-hidden cases. - unit_PreviewDriver: re-anchor and fast-recovery cases. - unit_RmtLedDriver_lifecycle: symbol-buffer sizing and driving-status-on-boot cases. Docs / CI: - backlog-core: recorded the prime-only ring stall-backstop gap (the third completion path the whole-frame fix leaves uncovered) with the sibling-path fix named. Reviews: - πŸ‘Ύ F1 (fixed): RmtLed's resting-status re-assert masked a per-pin RMT init failure (Severity::Error without setting configErr_/configWarn_), so a dead strand read "healthy" β€” now gated on inited_. - πŸ‘Ύ F2 (fixed): deleted a verbatim-duplicated 3-line comment in ParallelLedDriver. - πŸ‘Ύ F3 (fixed): whole-frame FIFO drain could race a late EOF into a spurious done token β€” guarded the ISR pop on a non-empty FIFO and stop the hardware before draining. - πŸ‘Ύ F4 (fixed): finalizeStalledTransfer had external linkage outside the anonymous namespace β€” moved it inside. - πŸ‘Ύ F5 (deferred, backlogged): prime-only ring has no stall backstop; same wedge class, far rarer trigger (one EOF/frame), needs expander-wall verification β€” recorded in backlog-core with the fix named. - πŸ‘Ύ F6 (fixed): trimmed a redundant deinit()/inited_ re-call in the budget-fail branch and a dead false-arm in the Preview downscale ternary. - πŸ‘Ύ F7 (accepted): MultiPin dmaBudgetBytes halves unconditionally for a possible double-buffer; deliberate and commented, single-buffer configs near the budget edge are conservatively refused. tick: 131us, 107us, 2us, 5us, 131us, 21us, 3us, 286us, 73us, 18us, 23us, 169us, 129us, 23us, 7us, 49us (FPS: 7633, 9345, 500000, 200000, 7633, 47619, 333333, 3496, 13698, 55555, 43478, 5917, 7751, 43478, 142857, 20408) (per scenario) tick: 3516us (FPS: 284) heap free: 60224 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/backlog/backlog-core.md | 10 ++++ src/light/drivers/MultiPinLedDriver.h | 19 ++++++ src/light/drivers/ParallelLedDriver.h | 45 +++++++++++++- src/light/drivers/PreviewDriver.h | 25 +++++++- src/light/drivers/RmtLedDriver.h | 31 ++++++++-- .../esp32/platform_esp32_moon_i80.cpp | 40 +++++++++++-- test/unit/light/unit_MultiPinLedDriver.cpp | 43 ++++++++++++++ test/unit/light/unit_PreviewDriver.cpp | 58 +++++++++++++++++++ .../light/unit_RmtLedDriver_lifecycle.cpp | 43 ++++++++++++++ 9 files changed, 298 insertions(+), 16 deletions(-) diff --git a/docs/backlog/backlog-core.md b/docs/backlog/backlog-core.md index 1cfb3028..a539609e 100644 --- a/docs/backlog/backlog-core.md +++ b/docs/backlog/backlog-core.md @@ -493,3 +493,13 @@ Four 🟠 Major boundary findings from the PR #29 review are real but each is it - **Core includes platform, compiled core in `mm_core`.** `src/core/moonlive/MoonLive.cpp` `#include`s `platform/platform.h` and calls the exec-memory API directly, and the root `CMakeLists.txt` compiles `MoonLive.cpp`/`MoonLiveCompiler.cpp` into `mm_core` and links `mm_core β†’ mm_platform` β€” violating the header-only-core / no-platform-includes contract both files declare. The runtime exec-memory placement layer wants a core-neutral injected interface (or to move out of `src/core`), so the compiled/platform-dependent surface sits behind `mm_platform` and `mm_core` stays INTERFACE-only. These two are one change (same boundary). - **W^X disabled in the board default.** `esp32/sdkconfig.defaults.esp32s3-n16r8` turns off `CONFIG_ESP_SYSTEM_MEMPROT_FEATURE` and enables `CONFIG_HEAP_HAS_EXEC_HEAP` for *every* build on that board, even with no MoonLive effect installed. The JIT genuinely needs a writable-then-executable heap, but that belongs in a dedicated MoonLive/JIT opt-in overlay or an explicit build profile, not the board default β€” so a stock build keeps memory protection on. - **A scenario rides timing + network.** `test/scenarios/light/scenario_modifier_chain.json` carries `tick_us` baselines (host-performance dependent) and routes a modifier-chain-composition test through `NetworkSendDriver` (pulls network-path behavior into a test that is not about the network). It wants an in-process sink and structural assertions so it stays hermetic, per the `test/**` "no timing or network dependence" rule. + +## MoonI80 prime-only ring: no stall backstop (sibling-path gap) + +**Found:** πŸ‘Ύ Reviewer, pre-commit on the whole-frame stall fix (2026-07-22). + +The MoonI80 wait-timeout backstop (`moonI80Ws2812Wait`, `platform_esp32_moon_i80.cpp`) now recovers a lost/coalesced EOF on **two** of the driver's three completion paths: the lapping ring (`nSlices > ringBufs`, oracle-gated) and the whole-frame path (`!isRing`). The **prime-only ring** (`isRing && nSlices <= ringBufs`) falls through both conditions, so a lost terminator-EOF there leaves `busy` stuck true with no recovery β€” and every prime/arm/transmit-ring path refuses under `busy`, the same permanent-wedge class the whole-frame fix just closed. + +Mitigated in practice: prime-only fires exactly one EOF per frame (no intra-frame coalescing), so the lost-EOF trigger is far rarer than on the whole-frame or lapping paths. But it is the same defect, and per the CLAUDE.md sibling-path rule (a cross-cutting recovery that core owns for one path should cover the sibling path, not be re-implemented per case) the backstop should extend to it rather than leave a third path uncovered. + +**Fix:** widen the backstop's condition so a stuck prime-only ring finalizes too β€” likely a single "any ring frame whose wire time has elapsed with `busy` still set" oracle that subsumes both ring branches, calling the shared `finalizeStalledTransfer`. Verify on the expander wall (prime-only = the small-strand ring config), since the ring recovery is not desktop-testable. diff --git a/src/light/drivers/MultiPinLedDriver.h b/src/light/drivers/MultiPinLedDriver.h index d0c3193b..b9fb349a 100644 --- a/src/light/drivers/MultiPinLedDriver.h +++ b/src/light/drivers/MultiPinLedDriver.h @@ -95,6 +95,25 @@ class MultiPinLedDriver : public ParallelLedDriver { /// exclusive per chip (at most one is non-zero), so the sum picks the right one. static constexpr uint8_t lanesAvailable() { return platform::lcdLanes + platform::i2sLanes; } static constexpr bool kPowerOfTwoBus = true; // the BUS rounds to 8/16; the pin count is free + + /// Whole-frame DMA byte budget. On the classic ESP32 the i80 is the I2S peripheral: its DMA is + /// INTERNAL-RAM only (no PSRAM) and it holds the whole frame (no streaming ring), so a frame larger + /// than the free internal DMA block simply cannot allocate β€” and the failing esp_lcd path can busy- + /// wait to a watchdog reset. reinit() pre-checks against this and idles with a clear status instead. + /// Budget = HALF the largest free internal block (doubleBuffer may need two frames) minus a fixed + /// reserve for the bus descriptors + other allocations that land between this query and the alloc. + /// On the LCD_CAM chips (S3/P4) the DMA reaches PSRAM β†’ 0 = no bound (the base default). COLD PATH. + size_t dmaBudgetBytes() const { + if constexpr (platform::i2sLanes > 0) { + const size_t block = platform::maxInternalAllocBlock(); + constexpr size_t kReserve = 16 * 1024; // descriptors + headroom for allocs after this query + const size_t usable = block > kReserve ? block - kReserve : 0; + return usable / 2; // halve: doubleBuffer allocates the frame twice + } else { + return 0; // LCD_CAM (S3/P4): PSRAM DMA, no whole-frame ceiling + } + } + // The i80 loopback can't build a 1-lane private bus, so it rebuilds the FULL-WIDTH bus and // carries the pattern on lane 0 β€” the loopback frame must be encoded at the operational bus // width (16-bit for a 16-lane driver) to match. (Parlio can do a 1-lane unit, so it sets false.) diff --git a/src/light/drivers/ParallelLedDriver.h b/src/light/drivers/ParallelLedDriver.h index a2d7d91b..2d9cd8d2 100644 --- a/src/light/drivers/ParallelLedDriver.h +++ b/src/light/drivers/ParallelLedDriver.h @@ -276,6 +276,11 @@ class ParallelLedDriver : public DriverBase { // A checkbox: the expander is fitted or it isn't. The '595's width (8) is the chip's, not a // setting, so there is nothing to type β€” and a boolean can't be half-configured. controls_.addBool("pinExpander", pinExpander); + // Hidden where the silicon can't host the '595 (the classic ESP32 i80 is the I2S peripheral, + // whose DMA can't read PSRAM, so the expander's Γ—8 frame has nowhere to live β€” see + // kSupportsPinExpander). Turning it on there only ever produces a config error, so don't offer + // the switch. A compile-time property of the chip; the control stays for S3/P4 (LCD_CAM). + controls_.setHidden(controls_.count() - 1, !Derived::kSupportsPinExpander); // The bus pins sit UNDER the expander toggle because for a driver that owns its own GPIO // routing they are '595 pins: MoonI80 routes WR only when a shift register needs it as SRCLK, // and hides the control otherwise. (I80 goes through esp_lcd, which mandates a valid WR *and* @@ -1210,6 +1215,12 @@ class ParallelLedDriver : public DriverBase { /// The ring's regime as a one-word status suffix ("primed" / "lapping"), or null when not ringing β€” /// so the driving-status line shows which side of the streaming boundary a config sits on. const char* busRingMode() const { return nullptr; } + /// Byte ceiling on a whole-frame DMA buffer, or 0 for "no bound". Default 0: the PSRAM-DMA chips + /// (S3/P4 LCD_CAM) and the streaming ring (never materialises a whole frame) have no such limit. + /// Only a driver whose DMA is internal-RAM-only AND holds the whole frame overrides it (MultiPin on + /// the classic ESP32). reinit() pre-checks frameBytes_ against this and idles with a clear status if + /// it won't fit, rather than choking the bus init on an impossible allocation. Cold path. + size_t dmaBudgetBytes() const { return 0; } /// Core-0 helper hook (default: no helper). Only the ring driver overrides it, spawning a core-0 /// worker that primes half the ring pool while core 1 primes the other half (busTransmitRing's /// fork-join). ready() is true only when the render/encode split is engaged AND the helper task is up. @@ -1258,6 +1269,15 @@ class ParallelLedDriver : public DriverBase { return (bytes + 63) & ~static_cast(63); } + // Whether a whole-frame DMA buffer of `frameBytes` fits the internal-DMA budget of a driver whose + // DMA can't reach PSRAM (the classic i80's I2S peripheral) and holds the whole frame (no ring). + // A driver that IS so bounded calls this in parseConfig; if false it idles with a clear status + // instead of choking the bus init on an allocation the peripheral can never satisfy. `budgetBytes` + // 0 means "no bound" (PSRAM-capable / ring drivers) β†’ always fits. + static bool frameFitsDmaBudget(size_t frameBytes, size_t budgetBytes) { + return budgetBytes == 0 || frameBytes <= budgetBytes; + } + // Bytes per bus slot: 1 for the 8-bit bus, 2 for the 16-bit bus. Keys on the PHYSICAL // pin count, not laneCount_ β€” with a '595 expander the lanes ride the shift cycles, not // extra bus bits, so 48 lanes on 6 pins is still an 8-bit bus. (In direct mode the two @@ -1382,12 +1402,12 @@ class ParallelLedDriver : public DriverBase { if (!err && lanes > kMaxStrands) err = "too many strands (pins Γ— 8 through the expander)"; if (!err) { // Distribute over this driver's window slice, not the whole buffer. - // assignCounts clamps each lane to kMaxWs2812LedsPerPin (drives that many - // rather than choking a whole grid onto one WS2812 line). Its own warning - // (a clamped lane) wins over the WR/DC one only if it sets warn non-null. const nrOfLightsType bufN = sourceBuffer_ ? sourceBuffer_->count() : 0; windowSlice(bufN, winStart_, winLen_); const char* clampWarn = nullptr; + // assignCounts clamps each lane to kMaxWs2812LedsPerPin (drives that many + // rather than choking a whole grid onto one WS2812 line). Its own warning + // (a clamped lane) wins over the WR/DC one only if it sets warn non-null. err = assignCounts(ledsPerPin, lanes, winLen_, laneCounts_, kMaxWs2812LedsPerPin, &clampWarn); if (clampWarn) warn = clampWarn; @@ -1525,6 +1545,25 @@ class ParallelLedDriver : public DriverBase { return; } deinit(); + // Pre-check the frame against the driver's DMA budget BEFORE attempting the bus init. A + // whole-frame driver whose DMA can't reach PSRAM (the classic ESP32 i80 = the I2S peripheral, + // internal-RAM-only) simply cannot allocate a frame larger than its internal DMA block β€” and on + // that chip the failing esp_lcd path can BUSY-WAIT to a watchdog reset rather than return an + // error. So refuse cleanly with a clear, actionable status instead of choking the init. Budget 0 + // (PSRAM-capable chips, or the streaming ring) means "no bound" β†’ always passes. Cold path. + if (const size_t budget = derived()->dmaBudgetBytes(); + !frameFitsDmaBudget(frameBytes_, budget)) { + // deinit() above already cleared the bus and inited_ β€” just report and bail. + if (char* b = failBufEnsure()) { + std::snprintf(b, kFailBufLen, "frame %uKB over i80 DMA %uKB: fewer lights/pin", + static_cast(frameBytes_ / 1024), + static_cast(budget / 1024)); + setStatus(b, Severity::Error); + } else { + setStatus(Derived::kInitFailMsg, Severity::Error); + } + return; + } // Pass doubleBuffer so busInit allocates the second buffer only when the double-buffer is // wanted β€” OFF (default) costs exactly one DMA buffer, no async overhead, no second alloc. inited_ = derived()->busInit(frameBytes_, doubleBuffer); diff --git a/src/light/drivers/PreviewDriver.h b/src/light/drivers/PreviewDriver.h index c31051db..4d44974b 100644 --- a/src/light/drivers/PreviewDriver.h +++ b/src/light/drivers/PreviewDriver.h @@ -59,6 +59,10 @@ class PreviewDriver : public DriverBase { /// affectsPrepare path). Lets a test drive the buffer alloc/free without a control write. void setResumableFramesForTest(bool on) { resumableFrames = on; } + /// The current adaptive downsample factor (1 = full resolution). Test-only β€” lets a test pin the + /// coarsen (additive) / refine (multiplicative) recovery cadence. + nrOfLightsType downscaleForTest() const { return downscale_; } + /// Preview shows the raw logical buffer, no correction. bool hasCorrectionControls() const override { return false; } @@ -93,6 +97,16 @@ class PreviewDriver : public DriverBase { if (broadcaster_) broadcaster_->cancelBufferedSend(); if (resumableFrames) ensureStage(); // allocate the staging buffer only when the A/B wants it else freePreviewBuffers(); // OFF: release the ~24 KB (readout drops to match) + // Re-anchor the LINK-adaptive downsample on a geometry change: a rebuild is a fresh layout, so a + // previous grid's link-struggle coarsening must not carry over and hold a now-small grid coarse + // (the "add a 16Γ—16 β†’ 4 blobs for ~10 s" bug β€” it inherited a big config's downscale_). The + // memory/display cap in buildAndSendCoordTable still sets the honest floor for THIS grid instantly + // (a 90Γ—90 lands at its 1/3 with no ramp), and downscale_ only re-coarsens if this grid's own + // frames actually stall. Reset here (the true rebuild seam), NOT in buildAndSendCoordTable, which + // the adaptive loop itself calls β€” resetting there would undo the adaptation mid-flight. + downscale_ = 1; + slowStreak_ = 0; + cleanStreak_ = 0; buildAndSendCoordTable(); refreshStatus(); // surface any resumable-path degradation (alloc miss) in the tab } @@ -191,7 +205,12 @@ class PreviewDriver : public DriverBase { slowStreak_ = 0; if (downscale_ > 1 && ++cleanStreak_ >= kUpscaleAfterFast) { cleanStreak_ = 0; - downscale_--; + // AIMD-inverse recovery: coarsen ADDITIVELY (+1, gentle β€” above) but refine + // MULTIPLICATIVELY (halve toward 1). A run of prompt frames means the link has plenty + // of headroom, so a coarse stride collapses to full res in ~log2 refine events, not one + // per unit β€” the difference between a small grid settling in ~1 s vs. ~10 s. The next + // step still measures before refining again, so overshoot re-coarsens by the +1 path. + downscale_ >>= 1; // guarded by downscale_ > 1 above, so this stays >= 1 buildAndSendCoordTable(); } } @@ -596,7 +615,9 @@ class PreviewDriver : public DriverBase { uint8_t cleanStreak_ = 0; // consecutive prompt, fully-sent frames uint8_t framesWaiting_ = 0; // fps slots skipped because the previous frame is still draining static constexpr uint8_t kDownscaleAfterSlow = 2; // coarsen after this many slow frames (fast react) - static constexpr uint8_t kUpscaleAfterFast = 20; // refine after this many clean frames + static constexpr uint8_t kUpscaleAfterFast = 6; // refine after this many clean frames β€” then HALVE + // downscale_ (multiplicative recovery), so a coarse + // stride reaches full res in ~log2 steps, not linearly // A frame still draining after this many fps slots means the link can't sustain even one frame // at this resolution at the slowest useful rate β†’ resolution must drop (not just the rate). Set // above 1 so a normal multi-tick drain on a healthy link isn't mistaken for struggle. diff --git a/src/light/drivers/RmtLedDriver.h b/src/light/drivers/RmtLedDriver.h index 826a723b..f5a19808 100644 --- a/src/light/drivers/RmtLedDriver.h +++ b/src/light/drivers/RmtLedDriver.h @@ -111,6 +111,7 @@ class RmtLedDriver : public DriverBase { controls_.addText("pins", pins, sizeof(pins)); controls_.addText("ledsPerPin", ledsPerPin, sizeof(ledsPerPin)); controls_.addBool("loopbackTest", loopbackTest); + controls_.setAdvanced(controls_.count() - 1); // expert-mode: a bench self-test, not a normal-use control // loopbackTxPin / loopbackRxPin are always bound (so persistence can load // them any time) but only shown while the test mode is on β€” same always- // add-then-setHidden shape NetworkModule uses for its static-IP fields. The @@ -199,6 +200,17 @@ class RmtLedDriver : public DriverBase { parseConfig(); resizeSymbols(); reinit(); + // Re-assert the resting "driving N of M lights" status after the full build. parseConfig sets it + // too, but only when a buffer is already wired (txLightCount_ > 0); on the boot path setup()'s + // parseConfig runs before the source buffer exists, so it's skipped and the status stays blank + // (or shows a stale loopback verdict) until the user touches a control. Re-deriving here β€” once + // pins + buffer + counts are all settled β€” makes it the default resting state, the way MoonLed's + // shows. Gated on inited_: reinit() reports a per-pin "RMT init failed" at Severity::Error without + // touching configErr_/configWarn_, so the `!warn` rule alone would overwrite that error with a + // false "driving N lights" while tick() bails and the strand stays dark. Only assert the resting + // status when the channels actually came up. + if (inited_ && !configErr_ && !configWarn_ && txLightCount_ > 0) + setDrivingInfo(txLightCount_, winLen_, correction_.outChannels); } /// Preset toggle (RGB↔RGBW) changes outChannels without a structural rebuild β€” @@ -403,12 +415,19 @@ class RmtLedDriver : public DriverBase { // hot path. Grows only β€” keeps a big-enough existing allocation. void resizeSymbols() { if (!sourceBuffer_) return; - // Size for this driver's window slice, not the whole source buffer β€” an - // onboard-LED slice of 1 reserves 1 light's worth of symbols, not the full - // grid's. Derive the window length directly (windowSlice is independent of - // the pin parse, so the buffer sizes correctly even before pins are set). - nrOfLightsType winStart, n; - windowSlice(sourceBuffer_->count(), winStart, n); + // Size for the lights this driver actually CLOCKS OUT, not the whole window. The window (start, + // count) can be far larger than the pins encode: `ledsPerPin` (or fewer pins than the window has + // lights) caps the transmitted total at `txLightCount_` (Ξ£ pinCounts_), and tick() only ever + // encodes that many (n = min(txLightCount_, winLen_) there). Sizing to the window instead made an + // 8Γ—8 strip on one pin (ledsPerPin 64) inside a 70Γ—82 grid (count=all, window 5740) try to alloc + // ~550 KB of symbols for lights it never encodes β€” the alloc failed on a small-heap classic ESP32, + // symbols_ stayed null, and tick() bailed β†’ the strip went dark even though only 64 lights were + // wanted. Bound to txLightCount_ so the buffer matches the real output. Fall back to the window + // when no pins are parsed yet (txLightCount_ == 0), so the buffer is ready before pins are set. + nrOfLightsType winStart, win; + windowSlice(sourceBuffer_->count(), winStart, win); + nrOfLightsType n = txLightCount_ > 0 ? txLightCount_ : win; + if (n > win) n = win; // never exceed the window's own light count const uint8_t ch = correction_.outChannels; if (n == 0 || ch == 0) return; // Per-light correction scratch: grow to `ch` bytes when the channel count grows (off the hot diff --git a/src/platform/esp32/platform_esp32_moon_i80.cpp b/src/platform/esp32/platform_esp32_moon_i80.cpp index 73eb2419..6bcd39b4 100644 --- a/src/platform/esp32/platform_esp32_moon_i80.cpp +++ b/src/platform/esp32/platform_esp32_moon_i80.cpp @@ -566,6 +566,10 @@ bool IRAM_ATTR moonI80EofCb(gdma_channel_handle_t, gdma_event_data_t*, void* use } // Whole-frame mode: pop the oldest started buffer, record its wire time, release its waiter. + // Guard on a non-empty FIFO: if the wait-timeout backstop already drained this entry (fifoTail == + // fifoHead) and the lost EOF then arrives late, popping would read a stale slot, hand out a spurious + // `done`, and desync tail past head β€” so a firing against a structurally empty FIFO is dropped. + if (st->fifoTail == st->fifoHead) return false; const uint8_t slot = st->fifoTail; const uint8_t b = st->fifo[slot] & 1u; const int64_t now = esp_timer_get_time(); @@ -1417,6 +1421,23 @@ MoonI80State* createRingState(const uint16_t* dataPins, uint8_t laneCount, uint1 return st; } +// Abandon the in-flight transfer and return the peripheral to a clean idle β€” the ONE recovery both the +// ring and whole-frame wait-timeout backstops share. A lost/coalesced EOF leaves `busy` stuck true with +// no interrupt coming to clear it; without this the bus wedges permanently (every later transmit blocks +// its full timeout on the stuck busy, and the driver's give-up retry re-arms into the same stuck state). +// The single owner of "the EOF didn't come, unstick the bus": stop the LCD + GDMA, clear busy, and mark +// the strand as idling LOW now (the WS2812 reset begins here) so the next arm holds the reset window. +// The CONDITION for finalizing, and any mode-specific residue (the ring re-links its chain and latches +// encode stats on the next arm; the whole-frame path drains its completion FIFO), stay at the call sites β€” +// only the shared stop-and-clear lives here, so the two paths can't drift in how they leave the hardware. +void finalizeStalledTransfer(MoonI80State* st) { + lcd_ll_stop(st->hal.dev); + gdma_stop(st->dma); + st->busy = false; + st->lastStopUs = esp_timer_get_time(); + st->dbgStallAbandons = st->dbgStallAbandons + 1u; +} + } // namespace bool moonI80Ws2812Init(MoonI80Ws2812Handle& h, const uint16_t* dataPins, uint8_t laneCount, @@ -1649,17 +1670,26 @@ bool moonI80Ws2812Wait(MoonI80Ws2812Handle& h, uint8_t buffer, uint32_t timeoutM && st->lastWrittenSlice < st->nSlices + kTailBufs) { // kTailBufs (file scope), not a bare +1 const int64_t frameWireUs = (static_cast(st->nSlices) * st->sliceNs) / 1000; if (esp_timer_get_time() - st->armUs >= frameWireUs) { - lcd_ll_stop(st->hal.dev); - gdma_stop(st->dma); - st->busy = false; - st->lastStopUs = esp_timer_get_time(); // the strand idles LOW β†’ the WS2812 reset begins - st->dbgStallAbandons = st->dbgStallAbandons + 1u; + finalizeStalledTransfer(st); // the shared stop-and-clear; the next arm re-links the chain // Latch whatever this frame's refills managed, so the ea readout isn't stuck at a half window. st->dbgEncAvgUs = st->dbgEncCount ? st->dbgEncSumUs / st->dbgEncCount : st->dbgEncAvgUs; st->dbgEncSumUs = 0; st->dbgEncCount = 0; } } + + // STALL BACKSTOP (whole-frame path). The EOF interrupt is a latch that can, very rarely, be lost β€” + // two firings coalescing, or one racing the next frame's reset β€” leaving `busy` stuck true with no + // EOF coming to clear it. Without recovery the bus wedges permanently: every later transmit sees busy + // and blocks its full wire-free timeout, so the driver's give-up retry re-arms into the same stuck + // state (the ~5 s-then-dark wedge on a direct strand). The ring branch above finalizes its own stall + // on the oracle's condition; here the condition is simply "the wait timed out with a transfer in + // flight." Shared stop-and-clear via finalizeStalledTransfer; the whole-frame residue is draining the + // completion FIFO so the abandoned entry can't be popped by a late EOF against the next frame. + if (!st->isRing && st->busy) { + finalizeStalledTransfer(st); // stop LCD + GDMA FIRST, so no EOF can fire during the drain below + st->fifoTail = st->fifoHead; // then drop the un-completed entry; the ISR guard ignores a late EOF + } return false; // the caller keeps the buffer in-flight for this frame; the next frame arms fresh } diff --git a/test/unit/light/unit_MultiPinLedDriver.cpp b/test/unit/light/unit_MultiPinLedDriver.cpp index 212de901..f7dd8c43 100644 --- a/test/unit/light/unit_MultiPinLedDriver.cpp +++ b/test/unit/light/unit_MultiPinLedDriver.cpp @@ -100,6 +100,28 @@ TEST_CASE("MultiPinLedDriver frame grows on RGBW preset") { CHECK(d.frameBytes() == expectFrame(50, 4)); } +// A whole-frame driver with a bounded DMA (the classic ESP32 i80 = internal-RAM-only I2S, no ring) +// must REFUSE cleanly when the frame won't fit β€” never choke the bus init (which can busy-wait to a +// watchdog reset on hardware). On desktop / PSRAM chips the budget is 0 (no bound), so the frame-fit +// gate NEVER triggers regardless of grid size: a large frame is never rejected for its size here (the +// classic-i80 branch is compiled out). Pins the "budget 0 = no bound" contract β€” the gate is inert off +// the classic chip, so this refactor changes nothing on every non-classic target. The hardware behaviour +// (a too-big frame on the real classic i80 idles with the clear "over DMA" status) is proven on the Olimex. +TEST_CASE("MultiPinLedDriver: the DMA-fit gate is inert off the classic i80 (budget 0)") { + mm::MultiPinLedDriver d; + mm::Buffer src; + mm::Correction corr; + std::strcpy(d.pins, "1"); // one lane β†’ the whole grid lands on it, a big frame + std::strcpy(d.ledsPerPin, ""); // even-split all onto the one pin + wire(d, src, corr, 4096); // a large grid, far past any real classic i80 DMA budget + + // The frame was computed (a real size), and the status is NOT the size-rejection message β€” desktop + // dmaBudgetBytes() is 0, so frameFitsDmaBudget() always passes. (The desktop bus stub is inert, so + // the status may be the plain init-fail, but never the size gate β€” that only fires on the classic.) + CHECK(d.frameBytes() > 0); + CHECK(std::strstr(d.status() ? d.status() : "", "over i80 DMA") == nullptr); +} + // A bad pin list idles the driver with the parse literal in the status; fixing it recovers. TEST_CASE("MultiPinLedDriver bad pins β†’ status error β†’ recovery") { mm::MultiPinLedDriver d; @@ -292,3 +314,24 @@ TEST_CASE("MultiPinLedDriver loopbackTxPin tracks the loopbackTest toggle") { }; mm::test::checkConditionalControl(d, "loopbackTxPin", setTest, /*visibleWhenTrue=*/true); } + +// The pinExpander switch is HIDDEN where the silicon can't host the '595 (kSupportsPinExpander false: +// the classic ESP32 i80 = the I2S peripheral, whose DMA can't read PSRAM, so the Γ—8 expander frame has +// nowhere to live). Desktop has lcdLanes==0 too, so the control is hidden here β€” the same compile-time +// gate the classic build takes. On the LCD_CAM chips (S3/P4) the flag is true and the control shows; +// that path is exercised on-device. Turning it on where unsupported only ever yields a config error, so +// not offering the switch is the honest UI. (Before this, the toggle was shown on every chip.) +TEST_CASE("MultiPinLedDriver hides pinExpander where the chip can't host it") { + CHECK_FALSE(mm::MultiPinLedDriver::kSupportsPinExpander); // desktop lcdLanes==0 β†’ unsupported + + mm::MultiPinLedDriver d; + d.defineControls(); + bool found = false; + for (uint8_t i = 0; i < d.controls().count(); i++) { + if (std::strcmp(d.controls()[i].name, "pinExpander") == 0) { + found = true; + CHECK(d.controls()[i].hidden == true); // hidden on a chip without expander support + } + } + CHECK(found); // still BOUND (a saved value survives), just not shown +} diff --git a/test/unit/light/unit_PreviewDriver.cpp b/test/unit/light/unit_PreviewDriver.cpp index e365aae4..64020785 100644 --- a/test/unit/light/unit_PreviewDriver.cpp +++ b/test/unit/light/unit_PreviewDriver.cpp @@ -436,6 +436,64 @@ TEST_CASE("PreviewDriver gates the next frame on the buffered send draining (ada mm::platform::setTestNowMs(0); } +// ADAPTIVE RESOLUTION RECOVERY: the downsample coarsens ADDITIVELY (downscale_++ on slow frames, a +// gentle anti-stall) but refines MULTIPLICATIVELY (halve toward 1 on a run of clean frames). So a grid +// that briefly coarsened on a slow link snaps back to full resolution in ~log2 refine events, not one +// step per unit β€” the fix for a small grid taking ~10 s to reach full detail. This pins the halving so +// the recovery can't silently regress to the old linear crawl. +TEST_CASE("PreviewDriver refines resolution multiplicatively (fast recovery to full res)") { + mm::GridLayout g; g.width = 16; g.height = 16; g.depth = 1; // 256 lights, trivially full-res-able + PreviewRig rig(&g); + + uint32_t t = 1000; + auto tickSlow = [&] { rig.cap.bufferedDrains = 5; t += 100; mm::platform::setTestNowMs(t); rig.preview->tick(); }; + auto tickFast = [&] { rig.cap.bufferedDrains = 0; t += 100; mm::platform::setTestNowMs(t); rig.preview->tick(); }; + + // Drive it coarse: a run of slow frames coarsens downscale_ well above 1 (additive +1 per event). + for (int i = 0; i < 40; i++) tickSlow(); + const mm::nrOfLightsType coarsened = rig.preview->downscaleForTest(); + REQUIRE(coarsened > 1); // it did downsample under the slow link + + // Now the link is prompt. Count how many refine EVENTS (clean-streak completions) it takes to reach + // full res. Multiplicative halving needs ~log2(coarsened) events, far fewer than (coarsened-1) linear + // steps. kUpscaleAfterFast clean frames per event; bound the loop generously and assert it converged. + int refineEvents = 0; + mm::nrOfLightsType prev = coarsened; + for (int i = 0; i < 200 && rig.preview->downscaleForTest() > 1; i++) { + tickFast(); + const mm::nrOfLightsType now = rig.preview->downscaleForTest(); + if (now < prev) { refineEvents++; CHECK(now <= (prev + 1) / 2); prev = now; } // each event at least halves + } + CHECK(rig.preview->downscaleForTest() == 1); // reached full resolution + // log2(64 max) = 6 events ceiling; a real coarsened value needs far fewer. Linear would be up to 63. + CHECK(refineEvents <= 6); + + mm::platform::setTestNowMs(0); +} + +// RE-ANCHOR ON REBUILD: a link-struggle coarsening must NOT carry across a geometry change and hold a +// now-fitting grid coarse. A rebuild resets downscale_ to 1, so the memory/display cap alone sets the +// stride for the new grid β€” a grid that fits renders at full res immediately, no inherited ramp. (This +// is the "add a small grid β†’ stuck at 4 blobs for ~10 s because a prior config had coarsened" fix.) +TEST_CASE("PreviewDriver re-anchors resolution on a geometry rebuild (no inherited coarsening)") { + mm::GridLayout g; g.width = 16; g.height = 16; g.depth = 1; + PreviewRig rig(&g); + + uint32_t t = 1000; + auto tickSlow = [&] { rig.cap.bufferedDrains = 5; t += 100; mm::platform::setTestNowMs(t); rig.preview->tick(); }; + + // Coarsen it under a slow link. + for (int i = 0; i < 40; i++) tickSlow(); + REQUIRE(rig.preview->downscaleForTest() > 1); // it coarsened + + // A rebuild (a resize, or just re-preparing the same fitting grid) must re-anchor to full res: the + // 16Γ—16 (256 lights) is well under the cap, so with downscale_ reset it renders at stride 1. + rig.preview->applyState(); // prepare() re-anchors downscale_ + CHECK(rig.preview->downscaleForTest() == 1); // did NOT inherit the stale coarsening + + mm::platform::setTestNowMs(0); +} + // USE-AFTER-FREE GUARD: a geometry rebuild (resize) frees+reallocs the producer buffer, so any // in-flight buffered send (which holds a pointer into it) MUST be cancelled in prepare before // the buffer goes away β€” else drainPreviewSend would read freed memory. diff --git a/test/unit/light/unit_RmtLedDriver_lifecycle.cpp b/test/unit/light/unit_RmtLedDriver_lifecycle.cpp index 338fc6c8..7c34e262 100644 --- a/test/unit/light/unit_RmtLedDriver_lifecycle.cpp +++ b/test/unit/light/unit_RmtLedDriver_lifecycle.cpp @@ -46,6 +46,49 @@ TEST_CASE("RmtLedDriver sizes the symbol buffer in prepare") { CHECK(d.symbolCapacity() >= static_cast(64) * 3 * 8); } +// The resting status is "driving N of M lights" after a build, shown by DEFAULT (the way MoonLed does) β€” +// not only after the user touches a control. prepare() re-asserts it after the full build (pins + buffer +// + counts settled), so a driver that built cleanly always advertises its consumption. This also +// overwrites any stale transient (e.g. a prior loopback verdict), which must NOT linger as the resting +// status once the driver is driving lights. +TEST_CASE("RmtLedDriver shows 'driving N of M' as the resting status after a build") { + mm::RmtLedDriver d; + mm::Buffer src; + mm::Correction corr; + std::strcpy(d.pins, "16"); + std::strcpy(d.ledsPerPin, "64"); + wire(d, src, corr, 256); // defineControls + setSourceBuffer + applyState (the build) + + REQUIRE(d.status() != nullptr); + CHECK(std::strstr(d.status(), "driving 64 of 256") != nullptr); + CHECK(d.severity() != mm::MoonModule::Severity::Error); + + // A rebuild (the prepareTree sweep β€” a resize, an enable) re-asserts it, so the resting status is + // stable across rebuilds and never silently blanks. + d.applyState(); + REQUIRE(d.status() != nullptr); + CHECK(std::strstr(d.status(), "driving 64 of 256") != nullptr); +} + +// The symbol buffer sizes to what the pins CLOCK OUT (txLightCount_), NOT the window. A small strip on +// one pin (ledsPerPin 64) inside a huge grid (window = all 5740 lights) must reserve symbols for 64, not +// 5740 β€” else it tries to alloc ~550 KB it never encodes, the alloc fails on a small-heap board, and the +// strip goes dark even though only 64 lights were wanted (the bug this pins; ParallelLedDriver already +// sizes its frame to the driven count, RmtLed did not). ledsPerPin caps the pin; tick() only encodes 64. +TEST_CASE("RmtLedDriver sizes symbols to the driven lights, not the whole window") { + mm::RmtLedDriver d; + mm::Buffer src; + mm::Correction corr; + std::strcpy(d.pins, "16"); + std::strcpy(d.ledsPerPin, "64"); // one pin, 64 lights β€” the physical 8Γ—8 strip + wire(d, src, corr, 5740); // but a 70Γ—82 grid in the buffer (count defaults to all) + + REQUIRE(d.symbolBuffer() != nullptr); // allocated (64 lights fits easily) + CHECK(d.symbolCapacity() >= static_cast(64) * 3 * 8); // holds the 64 it encodes + // The window is 5740, but the buffer must NOT be sized for it (that was the ~550 KB over-alloc). + CHECK(d.symbolCapacity() < static_cast(5740) * 3 * 8); +} + TEST_CASE("RmtLedDriver keeps the symbol buffer across a rebuild (reinit must not free it)") { // The regression: prepare() does resizeSymbols() THEN reinit(), and a // bad reinit()->deinit() freed symbols_ right after it was allocated, so the From 58b9cae67fe74310cbd4ce01b535da05d3993656 Mon Sep 17 00:00:00 2001 From: ewowi Date: Wed, 22 Jul 2026 23:28:14 +0200 Subject: [PATCH 2/9] Add serial log level; installer app links; P4-shield RS-485 reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a serial log-level control so a resting device stops writing the once-a-second KPI line (an S3's onboard LED flickered on that serial TX); default Warn keeps warnings and errors, and the first 60 s always logs at Info for the installer's IP read. The web installer gains WLED Native and Home Assistant links with official store badges and a browser-access chip. Documentation: the getting-started page gets those two how-to-control sections plus a fixed right-side TOC, the MHC-WLED P4-shield hardware reference is rewritten from the builder's schematics (the board does have a mechanical RS-485 direction switch, and the loopback works through it), and a Release 4 scope plan is recorded. KPI: 16384lights | Desktop:755KB | tick:132/105/2/7/131/21/3/288/73/18/23/172/130/23/7/47us(FPS:7575/9523/500000/142857/7633/47619/333333/3472/13698/55555/43478/5813/7692/43478/142857/21276) | tick:3522us(FPS:283) | heap:58KB | src:194(45709) | test:137(24384) | lizard:160w Core: - platform.h / platform_esp32 / platform_desktop: added a LogLevel enum + setLogLevel seam (ESP32 maps straight to esp_log_level_set; desktop is a no-op). - SystemModule: a logLevel select control (None/Error/Warn/Info/Debug/Verbose, default Warn), applied to the platform logger on change and at boot; advanced-mode. - main.cpp: gate the once-a-second KPI printf on logLevel >= Info OR the first 60 s of uptime, so a resting device makes no periodic serial write while warnings/errors still surface. Light domain: - MultiPinLedDriver: dmaBudgetBytes on the bounded classic-i80 path never returns 0 (which means "no bound") and no longer halves for double-buffering (busInit downgrades the second buffer on its own); a starved board now still rejects an oversized frame. - ParallelLedDriver: corrected the frameFitsDmaBudget comment (called from reinit, not parseConfig). - PreviewDriver: recovery comments now describe the multiplicative halving the code does; reset framesWaiting_ at the rebuild seam so the old grid's drain count can't make the new grid's first frame read slow. Scripts / MoonDeck: - _moondeck_config (new): shared active-device-IP + logLevel-toggle helpers (mirrors the _net_probe shared-module pattern), imported by both consumers. - collect_kpi + monitor_esp32: raise the device to Info over /api/control before reading serial and restore Warn after, so KPI capture and monitoring still see the tick line. - preview_installer: stage web-installer/ recursively (+ .svg) so a subdirectory of assets (the app-store badges) is served in preview, matching the deploy's recursive copy. UI: - web-installer: WLED Native (App Store + Google Play official badges) and Home Assistant links in the "control your device" card, a vendor-neutral globe chip for browser access, and the Step 3 heading reworded to cover all three; the help link points at the getting-started page. Badges committed under web-installer/assets/. Tests: - unit_MultiPinLedDriver: exercise frameFitsDmaBudget directly with synthetic finite/zero budgets; assert the pinExpander control's hidden state equals !kSupportsPinExpander; US spelling fix. Docs / CI: - gettingstarted: added "control from your phone (WLED Native)" and "smart home (Home Assistant)" sections with images and store links; fixed the missing right-side TOC by demoting the two Chapter H1s so the page has a single title H1. - system.md: documented the logLevel control. - architecture: removed the 🚧 designed-not-implemented tagging now that the two-core render/output split has shipped (the clock-sync/light-distribution items describe themselves as not-yet-wired in prose). - reference/mhc-wled-esp32-p4-shield: rewritten from the builder's schematics + terminal maps β€” the board has a mechanical RS-485 direction switch (SW5) on the GPIO 3 channel, the RS-485 outputs are a range extender + DMX-512 output, and the loopback works Tx=GPIO4 -> Rx=GPIO3 through that switch; new images replace the old pinout SVG. - backlog-light: reconciled the RS-485 DE/RE note with the shield's mechanical switch. - backlog-core: recorded the MoonI80 prime-only ring stall-backstop gap and the whole-frame late-EOF serialization hardening (both need the expander wall). - history/plans: added the Release 4 scope plan (effect-breadth migration + rename runway + the deferred hardware work). Reviews: - πŸ‡ MultiPin dmaBudgetBytes (fixed): starved classic path returned 0 = "no bound"; now a positive floor, no double-buffer halving. - πŸ‡ ParallelLedDriver comment (fixed): frameFitsDmaBudget is called from reinit, not parseConfig. - πŸ‡ PreviewDriver comments + framesWaiting_ (fixed): comments now match the multiplicative recovery; framesWaiting_ reset at the rebuild seam. - πŸ‡ RmtLed zero-txLightCount buffer (skipped): the window fallback is intentional pre-warm codified by the lifecycle tests (their wire() helper sets no pins); forcing no-allocation broke 6 tests for a non-bug, reverted. - πŸ‡ MoonI80 prime-only backstop + late-EOF serialization (deferred): both are ISR/ring changes that must be proven on the expander wall; backlogged with the fix named. - πŸ‡ unit_MultiPin tests (fixed): synthetic-budget assertions, hidden == !kSupportsPinExpander, US spelling. tick: 132us, 105us, 2us, 7us, 131us, 21us, 3us, 288us, 73us, 18us, 23us, 172us, 130us, 23us, 7us, 47us (FPS: 7575, 9523, 500000, 142857, 7633, 47619, 333333, 3472, 13698, 55555, 43478, 5813, 7692, 43478, 142857, 21276) (per scenario) tick: 3522us (FPS: 283) heap free: 60224 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/architecture.md | 14 +- ...wled-esp32-p4-shield-gpio-terminal-map.png | Bin 0 -> 147217 bytes .../mhc-wled-esp32-p4-shield-inout-header.png | Bin 0 -> 105748 bytes .../mhc-wled-esp32-p4-shield-pinout.svg | 125 ------------------ ...hield-rs485-gpio3-switchable-schematic.png | Bin 0 -> 63458 bytes ...-esp32-p4-shield-rs485-loopback-wiring.png | Bin 0 -> 385352 bytes ...p32-p4-shield-rs485-transmit-schematic.png | Bin 0 -> 46994 bytes docs/backlog/backlog-core.md | 2 + docs/backlog/backlog-light.md | 2 +- docs/gettingstarted.md | 60 +++++++-- ... scope - effect breadth + rename runway.md | 40 ++++++ docs/moonmodules/core/system.md | 1 + docs/reference/mhc-wled-esp32-p4-shield.md | 62 ++++++--- moondeck/_moondeck_config.py | 46 +++++++ moondeck/check/collect_kpi.py | 11 ++ moondeck/run/monitor_esp32.py | 12 ++ moondeck/run/preview_installer.py | 19 ++- src/core/SystemModule.h | 38 ++++++ src/light/drivers/MultiPinLedDriver.h | 11 +- src/light/drivers/ParallelLedDriver.h | 4 +- src/light/drivers/PreviewDriver.h | 5 +- src/main.cpp | 11 ++ src/platform/desktop/platform_desktop.cpp | 5 + src/platform/esp32/platform_esp32.cpp | 6 + src/platform/platform.h | 10 ++ test/unit/light/unit_MultiPinLedDriver.cpp | 24 +++- web-installer/assets/app-store-badge.svg | 46 +++++++ web-installer/assets/google-play-badge.png | Bin 0 -> 4904 bytes web-installer/assets/home-assistant-icon.png | Bin 0 -> 6142 bytes web-installer/index.html | 37 +++++- web-installer/install.css | 50 +++++++ 31 files changed, 458 insertions(+), 183 deletions(-) create mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-gpio-terminal-map.png create mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-inout-header.png delete mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-pinout.svg create mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-gpio3-switchable-schematic.png create mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-loopback-wiring.png create mode 100644 docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-transmit-schematic.png create mode 100644 docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md create mode 100644 moondeck/_moondeck_config.py create mode 100644 web-installer/assets/app-store-badge.svg create mode 100644 web-installer/assets/google-play-badge.png create mode 100644 web-installer/assets/home-assistant-icon.png diff --git a/docs/architecture.md b/docs/architecture.md index e8159115..61c4aee9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,6 +1,6 @@ # Architecture -This document is the agreed-up-front **architecture contract**: what projectMM is designed to be. Most of it describes the system as it is today; a few load-bearing design decisions are settled but not yet implemented. Those are marked **🚧: designed, not implemented yet (high priority for release 2)**. The 🚧 marker means the design is committed (this is how it *will* work, and code should be written toward it), not that it's optional or undecided. Anything without the marker is live today. +This document is the agreed-up-front **architecture contract**: what projectMM is designed to be. Most of it describes the system as it is today. A design described here is committed (this is how it *will* work, and code should be written toward it), not optional or undecided. Coding conventions live in [coding-standards.md](coding-standards.md); how to build and run lives in [building.md](building.md); what is tested lives in [testing.md](testing.md). @@ -164,7 +164,7 @@ When one module produces data another module reads on the hot path, the pattern - The producer exposes the struct via a `const`-returning getter (or a `setX(const Foo*)` setter on the consumer). - The **consumer holds a `const Foo*`** received once at wiring time in `main.cpp`, and reads it on the hot path each frame. -No registry, no subscription, no event bus. The consumer reads the latest value when it needs it; if the producer wrote nothing this tick, the consumer sees the previous value (acceptable for the kinds of data this exchanges: small state structs, periodic captures). This pull pattern is lock-free **for a small POD struct overwritten in place**: a reader on another core might catch a half-updated struct, but the result is one slightly-inconsistent read of a few fields that self-corrects next tick, visually harmless for the gyro/sensor data this carries, and cheaper than a lock. That tolerance does **not** extend to a large frame buffer the consumer copies out wholesale (an LED DMA buffer, an ArtNet packet): there a half-written read is a visible glitch, so that hand-off uses the 🚧 two-core double-buffer swap from [Β§ Parallelism](#parallelism), not this lock-free pull. +No registry, no subscription, no event bus. The consumer reads the latest value when it needs it; if the producer wrote nothing this tick, the consumer sees the previous value (acceptable for the kinds of data this exchanges: small state structs, periodic captures). This pull pattern is lock-free **for a small POD struct overwritten in place**: a reader on another core might catch a half-updated struct, but the result is one slightly-inconsistent read of a few fields that self-corrects next tick, visually harmless for the gyro/sensor data this carries, and cheaper than a lock. That tolerance does **not** extend to a large frame buffer the consumer copies out wholesale (an LED DMA buffer, an ArtNet packet): there a half-written read is a visible glitch, so that hand-off uses the two-core double-buffer swap from [Β§ Parallelism](#parallelism), not this lock-free pull. **Push through a domain-neutral sink.** When the producer should hand bytes to a generic core service rather than expose a struct, the core defines a narrow interface and the producer pushes to it. The producer owns the data and its wire format; the core sink (the interface's implementer) knows only "take these bytes and do my generic job"; it has zero knowledge of what the bytes mean or which domain produced them. `BinaryBroadcaster` (`HttpServerModule` implements it: "broadcast these bytes to all WebSocket clients") is the example; the producer side lives in the light domain (see [Β§ The pipeline](#the-pipeline)). @@ -274,7 +274,7 @@ Services are **user-add/deletable children of the `Services` container** β€” the Two domain-neutral services let several controllers act as one installation. They're core because nothing about them is light-specific; any domain spanning multiple devices uses the same two. - **Discovery**: devices find each other via mDNS. `NetworkModule` advertises each device today; this is live. -- **🚧 Clock sync**: one leader broadcasts its elapsed time (millis); followers compute their offset, targeting sub-millisecond accuracy. A shared monotonic clock is the foundation any cross-device coordination builds on. The committed design; not yet wired. +- **Clock sync**: one leader broadcasts its elapsed time (millis); followers compute their offset, targeting sub-millisecond accuracy. A shared monotonic clock is the foundation any cross-device coordination builds on. The committed design; not yet wired. What the synced clock is *for* is a domain question; the light domain's use of it (synced animation across a wall) is in [Β§ Multi-device sync](#multi-device-sync). @@ -373,7 +373,7 @@ Each layer references the shared Layouts. The layer builds its mapping by walkin Effects produce light colours. They write into the Layer's buffer, which represents a logical grid. The Layer determines the buffer's dimensions (width, height, depth) from the Layouts and its modifiers. Effects receive these logical dimensions and elapsed time (millis) as their rendering context. They compute light positions from the buffer index (e.g. `x = i % width`, `y = i / width`). -Effects use elapsed time for animation, not frame count. Animation speed becomes frame-rate independent: an effect looks the same at 30 fps and 60 fps. This is also what makes the 🚧 cross-device clock sync work: a shared elapsed-time base means synced visuals across controllers (see [Β§ Multi-device sync](#multi-device-sync)). +Effects use elapsed time for animation, not frame count. Animation speed becomes frame-rate independent: an effect looks the same at 30 fps and 60 fps. This is also what makes the cross-device clock sync work: a shared elapsed-time base means synced visuals across controllers (see [Β§ Multi-device sync](#multi-device-sync)). Effects know nothing about hardware, protocols, physical LED layout, or mapping. They only see the logical grid the layer provides. @@ -497,7 +497,7 @@ The result is a memory ladder that tracks configuration exactly: module-absent ### Buffer types - **Layer buffers**: one per active layer, holds the logical light data for one effect chain. Allocated in PSRAM when available. On memory-constrained devices, consumers may read from the layer buffer directly (no mapping, no blending, no physical buffer needed). -- **Physical buffer**: when present, holds the blended+mapped output. It is a *blend* buffer, needed only for compositing (>1 layer, or any alpha/additive blend); it is not what provides producer/consumer parallelism. Under the 🚧 [two-core handover](#parallelism), parallelism comes from the consumer's own working copy, the encoded DMA buffer for a clockless LED driver, or the kernel socket buffer for ArtNet, which decouples the producer (filling the next Layer frame) from the consumer (transmitting the previous one). +- **Physical buffer**: when present, holds the blended+mapped output. It is a *blend* buffer, needed only for compositing (>1 layer, or any alpha/additive blend); it is not what provides producer/consumer parallelism. Under the [two-core handover](#parallelism), parallelism comes from the consumer's own working copy, the encoded DMA buffer for a clockless LED driver, or the kernel socket buffer for ArtNet, which decouples the producer (filling the next Layer frame) from the consumer (transmitting the previous one). - **Mapping LUT**: flat lookup table for logicalβ†’physical. Read-only during rendering. PSRAM is fine: sequential reads are cache-friendly. All buffers are raw `uint8_t*` arrays sized `channelsPerLight * nrOfLights`. There is no pre-allocated per-channel array and no fixed channel layout: `channelsPerLight` is a runtime value (a `uint8_t`, so 1–255), so RGB (3), RGBW (4), and multi-channel DMX fixtures all use the same code path; the buffer simply gets wider. Channel layout is configured via offsets (see MoonLight's [LightsHeader](https://github.com/ewowi/MoonLight/blob/main/src/MoonLight/Layers/LightsHeader.h) pattern). @@ -548,8 +548,8 @@ The architecture does not assume PSRAM is present. Buffer counts and sizes are d How lighting uses the core [multi-device runtime](#multi-device-runtime) (discovery + clock sync) to drive an installation spanning multiple controllers: -- **🚧 Synced visuals from the shared clock.** Effects animate off elapsed time ([Β§ Effects](#effects)), so feeding them the leader's synced clock instead of each device's local one makes a wall of controllers animate in lockstep, regardless of each one's frame rate. This is the light-domain payoff of the core clock sync. -- **🚧 Light distribution**: one device sending rendered light data to another uses the existing ArtNet / E1.31 / DDP standards (the ArtNet *driver* already sends to fixtures today; device-to-device distribution as a sync topology is the part not yet wired). No bespoke protocol. +- **Synced visuals from the shared clock.** Effects animate off elapsed time ([Β§ Effects](#effects)), so feeding them the leader's synced clock instead of each device's local one makes a wall of controllers animate in lockstep, regardless of each one's frame rate. This is the light-domain payoff of the core clock sync. +- **Light distribution**: one device sending rendered light data to another uses the existing ArtNet / E1.31 / DDP standards (the ArtNet *driver* already sends to fixtures today; device-to-device distribution as a sync topology is the part not yet wired). No bespoke protocol. # Web UI diff --git a/docs/assets/reference/mhc-wled-esp32-p4-shield-gpio-terminal-map.png b/docs/assets/reference/mhc-wled-esp32-p4-shield-gpio-terminal-map.png new file mode 100644 index 0000000000000000000000000000000000000000..33e87abf8e9219b47163679f541a48666f4aea3e GIT binary patch literal 147217 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

R3q;Z>}z^Z&gLXB@qNVJ%a-y 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�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

Xz%1&u6wZv9v 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 literal 0 HcmV?d00001 diff --git a/docs/assets/reference/mhc-wled-esp32-p4-shield-inout-header.png b/docs/assets/reference/mhc-wled-esp32-p4-shield-inout-header.png new file mode 100644 index 0000000000000000000000000000000000000000..7387f00df0e99b11f3764fb3a4abdd7baa6d1c09 GIT binary patch literal 105748 zcmXuKRajh2*R|WYLqi$~?v}>g-JJlz-QC??f?JT_jRkjyAi+X#5AF`ZefRTz|6YfE z(ATP3RkOw%4hQgDF(zk;n*6YJ zpBG4zCFi*Mw+DB;=GJ@Re=ybiy4uSWyS+D_DW&%E<^9+wecZxe(aOq-WVn$2*emeB zOT8kk<|IPg#KdIl&v${?BLCMDqeSUqPNmNvE)EV35fK$b#Uy!~#0)$v~1bdh~q{!Mhj*^9yGYUAsT17r(mrght%Q=BuMeYpSY!)tFC`t~*jPmpI z)6{$&5P6XpcHvF13&a>GaMykAL{hQKew%!|em^>E`~q+Iuuk`WUK@0CFmDTaOm8_` z!Ycs&BTdE)vHa#>NX`H|djm_>8Le zy{NqZ2=Y8#I?UTxi^3u^vUXmqG1%cfpH&fo(4)4a)!Jl_bjwiVpd{>&hbQcOE3G)` zFd^vf?oOe`h7}7e*^3rT)KW-Sf)6d#@sv3Y5#`{FCVzbT?&j3%cJA=+w(MSb-rd2) z!zIvW!PQ=z;a9_+r98IAAS;Vl6s}H8_Udv^*4mcUUlIXgnsMx z{bz}BqvwOGPqy!>&w_CoaOyXnNZ|l(qi}P|ipt}j_4WS-Y3`hX=B2O}?6A69>bgCM z5}ss}4FHTc9N%_W=mZ1=2u}KmT<|JilSJ`bey3zsv> zv&2yoJcH491%b7@NiP+)2_5HrnX3e?Mm9~HVxStXR zUVYRh;hvZB$+Ku*fOz>;RoA}d^gbBG7OnFJD&wRpHgt+`^tp90B8AE)nJm?K;}5$! z<##t=K)y}>*+-L_yNS`xz=lsKI;zx>1n!~7%{fv1G*Kldpk64#2)GNoppnTVS% zyY5V9#@|(u0{hNlfjJDIVPx@H&wl8)tfjd8v)ai9WdGR!eiYBxQ?D>z<*wM(%Se}{ zh7AdBRbo?WjPP_O9>Z_4!kW1W9MGbX9%v zF4b+g#*2|{R~f;{vIRLN9L}OZsMkn`VH~LAoVe*u1g&QTl4zFD}joq7qqzxiv3FF+!`JIF-D-yjEKrvP;3^ z2|FVVRrK!qXOhHo*?oUD*QcF zEq?u5^1-)r?P#ky@mcmd@zjV|dPFc9LFAtXOiS3q<%2EWXtJV9>~;U0>Vnu4V0KRh zx&$D9QD!44NYD?a@qPdGB!0o}ocZyYfe0|wvEGmqv#Ag~9><*z*BHmVrHm=N^X@Ke zjP^+(@^c|Mp74K*w0S54HF)0_4rYKAT3$jg6{EB(G_p^ClIUu)7%Ds6QIvxao|>01 zqo*jdMimb)yq$&AoXA3(NUcR%VE^~eu@^5lPVU8HXvAR$V*I&?!}UP^bs=n3N~QW7 zP&WD+37XFSuPG!M4%uCu1aVHlLvXAueiLD^Y6`ACw=-KeuZ52ExSvV4xf@nzH6o^N z_FtA>*|)K+bdW|%{=fl!x#DA}JejbepZg}zd*=_UkdP2lDzYT{bQfuDb+rRaWS`v@ zvyTKoKjA z)BEz1hw`VaCzn7gr`>9XfSyUKYHY#RC}E&Ef>;s5uR`OVN*F*?R3wd9DSf5mT&A1O z>Uvd__3H7KqujNo%?8`E?^wXjJoG)k4+vN62g0X2J^jB|-3Jm6#}plMagFS3Ir9>r z`x5taPGqcN3>S(w5}4k5L~C>YtdIY!t7GI6Ts#)yOg@)-d?t76Sp>>Il3ptYbyV2s zc1so2V|eFTSdYP64vvi8v-FZB4tAFbcY9UWEM~YaFP}mOr7@L{5zq#A$ufV~Z+pS6biBb0G5V zWk0OytfCJd+$ksA{^F%k3UqSr@ZSAT;+^26W^LH%RlOj|z*%hgW04%*1MYLibcmWxzelt^vz>sqYRkvAscA~RReuZe z(A7`O0jEZtm#D~$tCL%9AdO0K+2kt`O)_Esu0MTv>ft;|MDRUqGfmWTg}@eb@>|46 z6L_%#n+^>|G33sU4*S)bdD|R+assew6;UZ&q;;#PH*-oo$fiK>d%(Y=v&2t(MfY<= zWz38z$7-=|!;@o_hAm378dA5vFPC+zJvlild#bf=k9*(t-}$%%5VvS!8!;CC{dnK- zdM6lX;C<^KRfsLAY#`K-AceFwWT}H|z{*x-Osh|)TN52x0^GbS&Y6s7Lk5*ns_m;7 z%voq_`rGT9;k8WIM@_py(+KHj2Xzv&EpXTxEpy}vmI)qZo%b&b!u}85Tz$(eO5R~I zwmva2sVQi zQs8xfI(TGOzWdmchi_(MtW0WY?~CtOK__SZkZ678)~+seK%3uvjR`@PqNTBMfx=N< z6CLre319Yl7T=I=pa;`N$<)_QRHcMo=j{~AR`u9*cPA&p-e(rW$D#eO(~18L=+k)w zc@xRzQchyc*#}reSzFK>;1w z+E2cOS#ffp_?36pP%3sCtJ2?7D+6!O4EQ2IV}vWmkEJtO2Euqh)99;Zm(`X?_Gzjs z^ou;X7VSt-0e#x1Or+<;WJ-7~>Nyu46HCker`wZe-3fv00Rd1LZ;T~;wk2?a%d-%D z)kJ_WezTQ1<6lDA)Ttx`e4Z+*;6T>bQtyP%C6Q5<0|sM073b>6l;i!~r5W=G<0w}_ zPBILJ4)X}ik=?Q!!;8wQ%bs#F3B>Wkc}G$H50_U@#}v8?tWs(?F_N9NZfN<|KB}OQ zjMgryGm`**uNO*e3FEz=W0cOP-m3LVHC1xJ8B~@l!2+AgG7*=j8wAaiE<%)WXA296 z6yWDFGYMOTbg^j2?j5p4_@@u(QXGyE!D8KOuNOv-Lj^cpue%wRbGH}~mNN1#JC0_D zJ9G7ol~tu5)?Ty3LhvzL*C51JAE1i(XTx_(yFU)}2#>H|YKZ3T zp3)0JNG#>{Wj?jR1+GC~3Tn$li0}U2XNV9ll!t7uQAnx@2EKR;l5Wh)A`Fn{MNO#b z`2i*98|3W^@)Skt?NfJ_>L}+?DZ?K`TPBuT1W?ruKGMqV^uyvwBykw&=-A*>+J{Eo z5O=4`9EGRBvCmaqHVL5@0m7Se3_91=GHH$h9FK*~=X2jFkdc}k<7NU5J z6m%W-ym)bcf1fWL@btIct)WWaXU8GKBIs=f2_(f-ZGi&OHZ;mJ%4;SOFw#frvnd3X z$WLP~4!a6mmme@Px5A50h4d9Mg!|2R*BhsO@e5N^1084Ru(<=abP*0heA4hBAB(apu3-Pv`jrL0IKhpfM&O6fak2NEKz?o?ODr3yaGc0(N?2rcgsBC;G|z zVF9_Kvi0aa-zCBaOll{^BW1L{eDOL*na2La3=}V-M}!UGu=+FND&aK!{q#uLQJ%Kz z@i4MC2Mfw(3YEXlzBth^k`uG| z#I_V)FauSW!pLo-k0`6Z;_?Y`$vIE_9}f>@8SfH0$0yU}$AO`CJhjZV%%V}aNx_%L zp_!MK@;_ZhY?$Frg>CKXytF~iHZae6B5jU@9hB1au{M9o$O%YEX{C@eeT+4J%&*~6 zw1|HBfzlu4M}%}!r$RF)a^7>O zCGkgsWSXIqYVaS6i4-bS^ot^GY6p;;hsQ+AnK`>$jS6`%Zo#y5u*Gz}q_$>zhYgOr z8qY*!jl|!7b$!}5#Zs@W@1?&#F_zm4Y$mYSuqUf)dKfufK$Yhg*xa*CS-a@? zqymdjmR^q-ZRQSvHx1t0BKqUwflfC_?qE?JVSFiV7qnaw_JYgR( z%}e>0{UaXD+|#{3KJ1DdkaD6G-9U)$5Bm$|dCGG8jdh1TW*WJFB9Do0Cxz#QkY>m- zBukv)J!tJIKozNJ>d91`;n<_fVCTvLoMTh@)ZQI|auTNe0|k-{g6+Y>*r@{8oAe71H&gM=OPa? zwJ#cPa@{ra$Md$`gqWPPxH(r_xB1nzwcZ=FW)yiAp$!CT7LkP{)S%1NC0Y1L=AWUp@L==z9W8lutPUQ$K<RcX?2Cb#0RW0-6LYr}iXyZ1W)y{6a`x0O1=04H}!t@yIlE)Uc z^6t5|Lm)H;i!pXX!Y-#v_0GItxs=MvaEYqg>U{b8VDqk`9L>*RBP4<$2^Ja`f^9Gq zV9nStA&DbNd?~g2y!G|o&N*(E?*=hV_kJJA$lk+59>V;E^OeiI6c%N{+|K%0P2X3lL1?XTizo@x53K`|MI^_u?YRH>8yY%bWB;JLEu^Wv%b0 zExx~)1)6%HA~o^af#xmrWB-70bm1aWol_;B%Rjo9ylL&-K05sXaG24!W5k%4x=~W# z9XFN9H~0=+(pEfwA%bl1@FeJr>{(y&g$-*LvBeWfg=Rdyukbt>$foQ<(zmg{cA4v- zOEFN;^i640($QQ_l^&CcWKDZ;q#o0rJn6c~oU1e46ucr-`{XG_%cO*xsex|&dhh*y z{P;l}b^rYQ_uMZn6vViHaNw|-K`o~Snza3DvZN|&N^tDWPCwpdnPuU0Xoe=gr44vr zS}3fj%`Cv7uy_5{fV`SrtR<54on-48q~X{DJL=3%fPDT8|DRxB41P}SeJ#$bSub3t z5*)U``KZ7AtLKkcq@%qv-2t67A`0w*JlW>2b3%_25T}IOi=*_POJi7Hvzx91W-0T? zfGbwkwmWHQFE5^p1vMBzN93ooJgGrpmw&sX=jZ49ZPx-`=e!9Lq|?p6o+eo7zeiR* z!^B*0C2Jl_f5wJ2@!jN|WJ_F0@0=S-%?xGiabaO%Qc_Y%-sO-|6E9S4)(uGD`IR6x z+eD5G6yJW(sa+%)w#oPmA13B>So~cbROvC>FdBLQXbbWh`68+s11JI0H~K3A?K5Uz z%K5Y{{}mym7tu4s9`m-8&adJQcj9QY=))MP9t}icVf}5M6s9y{1G^pl)r+liFY`rY z4Fgx|t+IbMVF!>PC}lirR{cJ70QRl$L#3Es`TFb zA6gyPLV+zmFnBRRwjM}*vYbB~<2?fGeX9(sR}-M-N)JfcE_g_I4YE!kgr7t-zmuMh zOG%C^5wlqx~> zyqe_%8E{JnXhKF*Vl=SPW&{ZX9zu$pFeUcU-WOz}%9zvbbhNQE%OCI)F}{~C{J0)( zEVW5vL>T`SM6_pn)jv9ZVf2QelZNq`MeAR-*2a18DxZYCZ#_%-&DMYn2k#fzN%xzs z&i4oIW{xTJ2@YZ%VF#o(2r{7>5HQFZUm>!11?)u#=CztxEtM&j3oHh(^6|hVeE_CH zLdBmDa{i?62tOTCse$}_eWP*ew852?wgizxq#^aKJ<|N&4YjrDGsnwR@@dc2^{P9; zai}yebB~|#;m-T4lxkU+S(4nWbAFS5LHf+u6?-~wP^p7{HAY3!{ zv!u&!Ie$B(OdX|8{;Hk9#l=MVg({+u2 zqm*eUyiJBU#-fx}M^V6&>;!GH5q$8ZA?r%GMQf@!i%$fMq)KlylL2N;L34gDZ-d?9 ze2MW(bYx%AIbDya)f}@T&izGwWga)7auF(?CN?FLMF?I6Yxp+bJ*t$_-D@Q``AA#P zsr3DK8cy*jF6kw0BFq?K;-@r__(JWCToI?oXy5sKcbslK8d*zpI@CW8;pIBP@GgrzTfsam9MF^ z_42yEysR@J2qpg-AAi(wu7*17GIMmZxmjSLQ$(MTn0PJtF3x};r6xTOEJCH*l)9Em zLSDQ^?U19JB&BZo8y)(`GO=oayxiP^beYqb!G0jL00w3$I%(}uu1Qc-w%vpfx^{#r zNHuMjguZ{|Q|R%YY__4}6?QkRhN?^u#^=czX2OYnk_)q~cl#~Zv;Q>*^<0>i0IaP} z{&S_Kjf)i$EWLsen4*o}xUMC}6znNwhxUl$tW2Ghp&F<}CO+f~i%_HX5YF8|26>v( zf#8=`T4)^-)Co)}wjrFnCJ~}L=AS{&DXRFNaq-+WG+(vj?oGqoJH^T3?0v8jd9b45 zlSG~6A|L~jdL1=-o%VIXAj>!i`&m#~>E`BEM4!TpKJcHJMGBeXbg-~M0H{J2N;0z2 z?8Ib?Dyq_~EQ5uJD=HvZYoT9RHAOR$4{$K0taG4TR(1X7;u+*^ni%$YprP!bE9{e1x8P0L@FJoju2UuhY zYxNG*d%>%>?A%5$Qd&Mgd7>_%+YD|}Bis+Me*jzgN4T?9!N;eEDYntuuN_yH*(Szk zd6<`4F=pDyRz8?GG7iHgmCf1ov4WFMy-w%H{gD`?uIG`JDwbVKKq& ziz*w(?4dcP@oppd3vW*{Io6U8t+(Ct$&~52b~F4?+qx|EaM-Po^TN^gdRxfCg5>J4 zM6=;>^47FBxMx^p`#^p-x@~ zymTz$Lohs_auGQial|jaqG$^p0AP3;_+$0Tr1f6sUnS_sop2ogZw6BMR53^9+n*M^p?WNEY(gDc6=H09Da&s4O8nGx2cpXAVS zD&w0dTl4&&>r!o4mFlA_28* zL|u|qjUI%DhbJfx13-p{H83!!(2!3lDMCxw@swgf9|#7{1i$_Ad*7Oxf@W^5`GHy$ zTBVJj^Vi?XwSJt_X~E^x^I#)OB~$0M+E?v({B66wqntfpE*Atey$>wEI21`06%eZ9rh9a{HY#u|o*UsJxR7&bS9}p}zfF~gEcyNyHdNy`_qK`caY-Z;S)N7*6EUn%KV{~p0HXEQ|5 z$3FTSf`;t56;9KkJ#nip1BtO3NS=-({C+N8`sLp3B~AYhKz_`6EvLwp&7H|aa4sN! zL)l8Y0p3>t8sp8MGjp-AO}{vBK-!$Q#Hn#yh^=gG$5_865Gt}S)VH;@b#>*+QX_9! z2WF_oj*gD{cCWh}!p%~(V!E8IG)F{4yuAfxSg;WHhFg7>sL#1~()OJGu#{3#W6(^5 z+$)(B3OM-s6_buV`N6l@k>8W*2u^&!wg@C3c)peJ;^<&*kIa~(Mql%K)cWr1=yRUg z`*OQp(^ISen0-Gtn>D<65dckITM7{b@HH64Rg;NkXrMymVTmQ`upp#>XtzL0e8d4g zXq!aD5*~v@nwQ`%`?dG(=LVgTzw1Gz13C6g@Hl zQ8Lm5u*nx|MK5n&vFyLxB+5QF)F}8UlKo$z=!~#5G+U;EAa;0iLPZ&7*@?W(Jj7aV zn+b5gEC~P9nwv|;;{c{wLi{Eatek+YRHIMA^#MN1Jn@iQi4lV8Os+Ir6fN>_=d_Zn zZXB_8wF3tS7tR=;n8;(tDkKj>kw#syw`?hIqO)*w(?lOTfvRLmB9@U0-9g{^{Ah6! zlDv$@n2xeBPpvrGz8Q7&g7jsbvX_@5)s3-mkoXDX!7KHJnjwt{3P5kUG>v*}(u^Nk zio-R>yhj5rc}G4Z=2V%Xr>NhXcvy(eV9CY%SBxG>h`<8tg{wWmR93eho0u!SKe{P{eIjaRFqKT)w{mFKIq{NO?8*a-Y%m^qrTU&F-%0NR&9kp(q75jyk>MLcqP0Jksnl_Y4{o#u)c>xoeOb?c zyNHqe@}(=&?D3OTEqzK6BQ#GIDh3@8rfqkRdz&)l=;a#baw}dxy`FTaExJ1h_3Hlk zGG&QUVzPkop|&kt-Iyv?HMY22l759mPA$3&_;z|0=hCc;3tt$3H0EZk`AItgQi<)9 z&m+uXSc~0kTr9j{{piFL;9LtbWEc43@3_Yd`Kaq@@w4Gl9xOLQnxdAI>{TxWA+N?r z*x|Qj^)R@P6z<=uv&kk6A)o)g&-iDJuJ!m;Hr$(l3gY z0e0R58ZWA0chymxFxRAg$%HWAr(=wcv%J$t3tmiZ=<_YVjQ)7VO2k7mDXZt4BJZF! zx4nq5k`bvNMqf?!FL`2~hLcKVW>I-<*DEgZhvtUMX)BS(^TcQIZ!U0YWG{}gvVV)^9LQ{xMcQ+Thjb+dN4_S60~`wLgjk4 zZtn1JAXyP2p-{lcI@s-(w86Nh{_`qh+EQ3xn;uW2gBhfN*4z+DK6H%)Tx^$+-!d^b zm(-lMlviWUluI`?H7#mw^|G;vv1S@Qd47J5St}FBb{Y3{SHlVZ;YMBj>0I*CGi_UT zqmGhC5bOB%$>?p*hG3c!Q7*{jj{UnA3r?lHQqN^s)O08O@{ah-=@*+{kgd*y1B8G{?COQqo)h^a}91 zzjTj_)XE>f{Cm0CZaQ0P&0inPd*6Hc-9I;cIdI#*ayVrpr|zpR1l3r`p>=g#o49bE zp|_?GOWvJ0JLG;zPHJaGRXjH6C?ry?2YETExrf8=G6oy54(L@j;M0r%B8ql9$A80!Oez-iQZSHyu^9Axi`napQ?3L z>EL0?jt^^71)oaokIWrZ7@#lGATTYjHkTOmvI9l01R(0r%{HVkRT%pYSq3l<$K6{hLz@S!O_6H!|e5YJ9z4NTJL>9 z+r9GJ@j~14uSv==%HvWjj!-|(Q{a-=8 zufrWRHvFV8Yg;x74Ku4ktV zt?B7ep@1a|vt+3&HO17t<#06BgtCEMg^AgY3yO*i$B{PK+&U=^<0g`MHckHw+X~n_ z8(4b$`F>F>NB@69B57~JH zZ`=eMe&{p51RHW4P%Fu-F@9AINdyI7;+3lR>NZFgdGKc2yC=z-%E`SC2BW`&?i1gl++lMhjG5NQ`seza&a@XVj23VB z3qi<5ou3u@>bnaQ6~Tg?x^)h$zBg^HB0VCW<1n-=&Vz!}%^&`DjoPJ=c~S>h%kU@D znp;%2S<7T5YKXAu^ts06fTQ1z>8f*3MbI=>6DUMWbSKSx171pA$F^ZS@hK1 z4XE_uqYXoN?Hy-xHR=;~Ovp0Dq(>A|OudaG*^ zt^H5J@&Yh_URBMz7rWS@w}@VWhsh&n=nHfTq{Nol$Dnn}IqjQL^}gHte(l@sY)n*N z{bXJbF)E@TM|apqaJ`~*3i0@83ZZ%!B^Bv~fa9tsW4bGGlyoyu;sw*L*4z0GnLW$b zDR&3gz!}d|cgg`beWQ+A7O06WfTx95ieJX$_W=R`3K@WHeM!W=$=xP-bURvylX-tU zJSX*?HSIU%_}X22e78$8vI8nzbAiTS(G)&KZvt*n(J=3JJQU0CGKYq4jtp$a@!mXH?{vC}}0 zltx|(+G?YZrg|L?4Z++`Ip5{#mJr)ZAHTS{yCd#9_y@Jb;f!8Zrfe- zBcs;7>aafq2#-+e5X%cF9A9+uP-svNcV>{3;JXY zdUTwtKcJot8XWJzi62Up;Cx8Z=2iZ-P)(Pw*?d;YFR=ah3N6{V7_+{kLw<~aco+r% zWgSOkN2ZHqlxBB*0)2e4zV0Y1Db1gFn2uvm2#U&YVFV(%JFR>8+;omnTsEj(<_$%!8 z{}DH4LEY$GOqMR0%{I^R9?olXdGzoBX;o+&;UxdPko{%!uWG`PJNG&<63y29H%0sq3cjH^w^j5aOT8zm)n zD9f8P4HwUVm>0@|0Y$vLUIsj&RAktYt^WeVG%cEN)HMJR#vXe&(F`!4qW@!YlA_k z;PD<_`7H*{t3KyZW69XeB{&u-!NvbA)zY=E4h&Px5-MqKre1lm#2e9%3rY1HPF;zjKP!dp4;UdQL`K82V@?cq8!e*FV}qA`D^%CL|p4reBpU(2mSsUTK19BP|`(> z+mz#q(9&*o2@j@`U%SJzDjdNau`( z97!0xocojpjs3)E;OpAkzI~;O!5jRKGsynmJk=|h`e=c;CzGA1opE}RY=_B(6(-PPqJr@Ftz@Z*xp%L{@&t3%!)J+KEtB- zzWZXxwBDVc3Az99@DSR4Q_D4gRg{%+cFt^@2~i_};%jSbR8&-vCYOR2P$h_Lvg&DM zWOUt#K5!Zjy*Y3>UG&=frqC-E*JN^xMSGrJ37Nm$gPL#lzw7)2qf(;8w+dq4eU~u` z6Hhobn;d==`&bk=O`R(C#uqf4t<~xWmepdZNI|VRXf)H7keb0{O=dvVt%*}%;ouqL z9XWAN?>bJ&J;@ZY%%jq)r1iZ+;5jJ)p>V*-4Q|q$-CQulzH01I4!LCqXdp!A{kE*F zTdnncxsX_TomyFR=YETRi;32i6iefiL6;V4@{LEuh{CNT=yi)H=;i1h4dT&Iw7c-d zm1zDJAC;$OmPA9xpm~jE3#jao(%nWENgg^zB{UFQa&Dw*^Q{9SFtP^)GLuDUQ`8bT zc+b~qsBlOj(bB~+lA+$#zM(P3tV_xamR44{Qp?9W*`=S-$CM+56=x-pl@t|6a$Vnk z`#4=bc)hoP{gY9&$~U|=+PzQ5}yiF^5E`9&&~~uKAX)Zjx$kP z@`R4vdENh4wh}f4VJTumDNzO=wT6F$c22m~O%)1dt+eDG{2uHq{WCEXS^f2eGMQkQ zd*uMSPBI)^s!(&8@D;>>(Nb(%G})!Ni)Eur{aV0ug2qA>>WY-Y0#?3jp!m)5+Ak|X zw`27%^&8`ll8hPXNR$*@4?iy6h1RA5-ETK8=2HGaZ#KwuxBW>Bx^rm`Ez`u>(kN@i zr?X2S?hhSPY{>a~g!d_84bwAH9DAMQkX$#m*`Bn`=SpwrD-_hi!;KG0ED6dsN4eQA|* zTgxfHc_(rSdZv^4^B+Tuv7H|JUXktFY>0t0K*@qrR&mer-j5~x`gZ%A{~N4G7}%DBRlw*wPfIk|aRQ8jSo)F_YzoODiL;&i5cnQA@DbcKHBz zM6grhH68P)BX&{gV&kW{B`|x5s&y(((MRfx>>b|RHkiKSe;Sasj(}ypHNPxQc4TO% zpkmdLsfi-0Iv?LrArZd6PpSv_>m!<#5doD(7y91!idzgM>2mcIK2$WYLdDktW}wZV~OS1>WL0OuJW zJuWUATfMDGg?u@I$W5xKIC32w9fa}HaJg%&w z!otkFf30m8=I8vS*0969qL*y75^v0BmD?z(fIVF{=(XF32A(o!9B=Gox%u>E=C|{P zH8|9PA|=_Jm*DYu)kr|V_l_m-;e9>O+bm4_)IgOlg)i@D?DYD>e~vot0Wct@P7U9V z3r3v3uf%*mb}-YMX5)+MOUA+yAZlWC zSDgR~_1iV7Z12f7Vux{@y00=Ae+X3=IuA0F+K+Z0H|+2GH4Ib$f& zqP_3tB9dYeUa~7f)>MQ>iX;WOE%C}w?P!oMYY7g9FK!#5Wsf`PM3bSTvon!IK-#`I zTD(!c0*FCd2!gIw;^B08Xf{MMz`By(9q@ej@WA_c8e8P8bKo_6u3=jpv)Uar$JI0YTc&G z$hTyKyyO^Z#Q~{vkTHMwJ{8@{JqR@8P;nSXtw2TK$*mVC)cP?oIce3nq(+yesGJ}~ zkI$8CC7B$d?L7h%{@I>ZL_-{WnsfcwmBUZ5#J#@K(IW<$R4@^ioIO0WzBzvQt$VeM zs0+Ol;@&vX3iu(C=TCih6_^Suve+55K=1{gM7BcwqyJi3JpIiI?%s!|<$R zq=1=?OO33LBj*e)%#+qXm|0Qx>4tUiuB#zn(u}p_8=9I*qK}m?HQ%Zlq7=<;Y`qx09Fu69PB!$rNJ zVO!u$2eIDj(bsY`1(ZWS?)E_RvoHmh|Asj-#nswvtTIvnwpW=?9_Hodesoi4sA zq$0GQ<54=Qa)J1{(O;gZNKr8^gQh<$3Z{-ep7{>7)$r*QUv5N6eR!`5)EPWpuC6L%$PlQGyh{a^ zNic@$dP)pbTAX|N(87|(GT^; zwV7>Ri++bC6qThCTgl7(L)a-**w0O^Y@bN641q%(@Fu2AQq{?mqw9$2l&Dt+_yIK>Z@!X# zU1O@kkN)%vDvmSd7(#yuZ#@Qt@d`0UI`6VhC zue`sNTAvK5$CRCYZ}fSC%lNrIb2u{~e?ZPI6=9)}eV&Rco7(05-Gvgx>*)$==xb6+ z#z))hkNcp(y+b7OZdaBF_38q+dXEwPPxfr58yv(LsMRPNm7y7HcI0OjJ<-p4DxQwN ztnXva-R}d16QEnmu(k_boS{+^j0{b2she28|1w$5u&`kNm@!lh14TN;p`0m5Ro|Po zcy(*6Fb9J!Uz{Odc}s8pbnMC9Q%P+wiIRhJ{sY!Ev4TW`*phebj`=vFHr}UkMkS70 z+n?-A**{U0t<3uC5K@TCKEAMd7#RJJvKg!^-+5f(Zmd}aD`1iF)!5rJe_6hh^7LuG$f>VX6!v*|p>1S@#Fq5C&T zC9xqs#J91))qw&_pKTCYK9Dd~3Q+*`cyYUpBH#V~8E>zTTt<(?c?~=E@`_nhsOvIR zO>vT73`0wKjW<s7! z61%M&>zU;t($^mT{(oJFdjWJyv1BO@TfB=lYN9wP+c7vJN(uff}b&}62+7V{^ z8T5#iP>2VnHT+gSh|4Z|G=LpEP$qmfxLnY(KG&N_VxHaVqj+9%xv(&EcK1$>~$(Q6D9IaQomQvz@%9_J6YlH-1K)7Rr0?lST=` zL46c;SlfjKmyomUM3~aaj90U~pWdnT-2GvpDH?rK3<@fJf92UIqqhz8$%EI{@AcAj zlZuF#>A>hKjtH$;w21LyKp;^cjAnHEYObc9fRfdOP{>qYz=DH{_El>>Bb5AJ9p&FDiI#U2TlC+di)v3bc%DTJzU;VPRU4_-a;hId!rRgQfFTr5mHT~<7a#ToV&Pt4HT_xms- z513*PLe*$M=~V0p2uQjeYB=85;#!Lsaw#o11un!5de1FQS;OLLv?Q7-909vc~!TEAJQ|fM#~AAP}CUSE}GpVEXu>1jsT=jsO?3*BG)Ou zaYbwab5ytnJRG6A*o1?%%Ddz9Vw29Y^%i%e@@)rFUy^vkU(o!Z+Dc|U?>{X6ooU`)alXsKrMVY zzy1-ic}W{u;$~f2%;;^udC-8gi5?y}3^qJSOed2hp#ftSwUKV``({tgNq%v;^TD}# zQGX(OB4YY4e>3J@^g<5of^un5ZqoXcj8SAHX9{};Ys;m$=Qa4{|^GavT z=&3krop@KK?r|R}BSV~nWVE*r2`f)#d~axc@@-JF#b3kWi#MrMriYp&OL$?oR3M?ymQEf1mgFCu_}GbLQ}gy|3B~e@Gl&d-82T z7|uimt7Xa;>ng}3ud78$UkZ?*a9sbiHyb%ilm$+?x0YeD_uzk4CPZuH6xmsgYRJNG zf7xyJ@{06T{-@$`-5|+v3%?bO)iW9^XRQ|=yCUgT<0`Mw)n=D(mB@bROl#jib;K{k zD?pvr*VjoN9GkB*ps!p)XG2B%oS?{Kb?M=dw1~km$eD6DlJqySN#y-kmFz9vOim4D zJ1nsIAXj__`*K9|iO5GzJO6dw+x>OKL5AK>2uf!Oml9JVk1&Xg9)=KzD#%qsl`sfl zK(YZJj-tz{&THYD$<^Ka)_HvON1*F8b3p9w2;xT5g2LLnar4DtPW2$OOAi<{md%E9 zS8b&hTIi;8sr*}`>+EFw&2IPT%!`Up0mR;;`qQrdR22bh&TVV*X1R;Vmb{zo#BeKk z)Ic_-;dPa&gg9Li4xG3YxWK0xifXqtp|En~$BybSVAA&+QuPFn%-Ec>5imbak$;$A zZK2n}35B=c;7|qSkwk%DT{>rpuU@66WLDGie~+1OkC;OTi;KtrjkvN#O{jv&bGZdrg?xPowT)`RSoqDrFIBK1{b%)DYz^DA3*;qwE7w7*_o8LGR#AZ;;r|22Ok(BBK!QKsZR9 zv8C&yAdGs<_W(bvx0-S&1`rl~(yIhloD98iy+9IVc8<_L;5I-ZU zB6rIO?kOig`$m4KVZ|HI#@T?|8|(a#^Hp0?p)zt@=;es))h)kiO~ZH(F_>zV=@n4< za4HDT&mZB}Mm3c_p9l4Bn@1D-4H;~7h067$Te;hns8+AaN%q ztKxj+mE5F`GB(H>R{#;JnA$co(^A(J;=KP+UH=Ylp0M|cn>6z2Kc#z%Ai9WrFi4bX zd`QIZL#b@_HwL_XNmuX&UsSQqZ7LeH;*7hS1)#pctuM`xxh=zYxEgkl8@^(#4&P{! zGdN$)Pt>fcJ94$N*y0~#B|?zC&65g>Hqle6C;S5jboL>e9}&t^jz=D+s`DaPeIcs6 zY$7za5RG3@WTer=R~#B6bH4Oc0dCveTYO8($Y1aWFb6*fMPDddydd0<=@|hgoPYbr zjijrJNi|rx3(MJf9%j+q0IlS7U7#()F665`qC`n-&4t_gYrMeBUgS3y2CO-m>FbSS zv-!FcB*wL;si*cECGQVl*%Mjig^0EhUq-Hx;zX_L%#a&fWD#x@MuZuEY<0~!Cv7v{ znHXQ*)GJpr7Sc*P61p&eCi$wPi6gPuT&obXp+x3YbTiOeW2@hC?yB4|7dbK&Ht8o31SZ|@-s>xTcg#7g93I^00Qru-5qNY)3?$I z(TJ*@$~5ILT{OL*gyEf?9kYJBuYU;o?dq)Qu#iNl5aY>>V3{I5dtj?aIcM!Fx}5F( zhjcl0bUFY{)Z3)bZ8QP`!WyshuF>3o8sSX{9|K1J{Qiu}!;Tpi_y zNh#q{&3`S2HKsL1c=~|1>&cV(cuQ;uwe~NAA+ymHn|>hx^cfnE6jyfR751oxsG^7A zukt1j*z`LNH4{{@T^MjDiQJ z7V9)g{GAjdo;xVd?KJhpUvR9F!m)+V*Jgm}UjW*mhCBMQ>D4cL+4$=3Fl3c=1~i#g zVl|w`$x@V&13<>OwYq5GhB`gcsJ<~;Izfd5co&gZUY{g`q_)^eUjNy4$XNZwT*p9U zp69cr2rd06l=`@S%B(SAmAZ zlwO_ZCawOb`ge`->^OeYdEo7o;S7+Ut}5$P!eYmW{KdaJ+T}&p;f0vekuLpD@xlrg z`-~Wh8UrZSyiUIVf?CZo@Hh|MUJuKsbO~%O!KQVn)_OxXeH4 zEa?mF-?D%e(*J$4Ku_oKElEE`f!Hsox+q$V-C?(!)MeZz)fEvgQ{94!ISSDrAQ-65 zi@w7citaL9Y?<$(9z>b8a`0QmXB;%B523emw))FC(tXUbV~41?O%OzSN|?Cvt>+Uw zcsg7yej3{lZ8t{Xd!ygbFal-KOew9cZ`lBAf*5%K)VykrKdk!yY9voXlCJNj>HJQz z_6q3qVNEaR?{u)7qilH}kJ>NO%%#T5ceTD%P1l*2IV?Qv=q&vSPmb*nlVj+Kkxl`z zCHS|tWQRf}B)_*0$zC;<=^&vr8ZvQVxRY#;WZl?ni;AoCm(f5g5i;^d-`5?@=ZSVR0VW!WecQ=XZme- z!Q~fHK_#>LTq*10oI+D%##??35~J7u9tgPb>Ug)0s?En`D_U3XpVfvJZX&txqN*#B zf0j4wf|h>BAT>><+GH)@ls^E^m8xPiWVV<1t@LK-^6+bO%It8k40Lro*WT^EBG+=h z)ee!P&+|kWMJitaQEc<{3Nc=Mppd?gn;4=hJ$^|bf2OsaNgsM6gd_O}o;u!p^Etnv zFKpLo?YBmmg7$}LYtIGNygkH+f%YNRVIaV7owzGhiuJE(oF`ot;S&R@tNnd?LPp}O z_jh5d0{!5RXGN!Nw+LE3zgy}8$PZ=i(C^;kx_%;5xFo?xk_R1K445yQcJ_WA1Zo))7jZdU#WG9K>V)ByIx9F%PwZ zGB!fbezHL(IU59LlHO}>k2;M_-$ix?bIre2B#KVk;-1hnxMSlEE3W2#n0b#RWwbvC zAnRM;PH0<1K-Kzwb9*p8li;hn@z;71N|LB5`7KY{Z~dg78pA<(mMuy-AbywKQ48MZ z;WJO6ydbwse2G7*o#A-5DqmcOVG_+8mOt7x(+{p37*=%=7HlwbW*ZX)7v723p7!*j zxiEOyxvkn4!eJCPt6wPxk;G|7HQH`+5FRg!>C?%`(D-Nc%1#y$i(lLYg47K?@gA&? zfhCGAIUwIZKd)UIMof5OiI0F75VOUr_p(rr$f!1{PQNekj~m!BvqKy=I0U%s9zxNN zHTf$%_$=uy@~KBoV#5_oyiqIhVH}*5Dg5FV_Ls(NINnd&&741&D%M_3U7(>*yXXB3 zM(0T4?JYX&L;6_IX3p2weXfY#tT|Gt1H)2|Yj(8d8UY%pY)3mEFmc!t&`ZQO&$t5U zJq0(4aQab^xkMO)?&lcXUSgRQF@1A-g5A`SV$EHxP{^fim`oZxc(5XmiKpRmITH@N z7nKnm_y=Wsb2F#nXwu?Z0>g|q%Ae|#ANSDnzX*a)Jm{0@nG>_K61+Y4%WXX%rNXS_ z#KEfL;#Zb0a1ziQsEq0-6(e>Up1ZzoZ?7+++3V%COjM%ipHoFCAr`W}_UuN!coE{1 zLdC0ifxER&S$`uJjUhNmN`TQ9uL@9_N>V=tuNj2lH~v~R_ZynM$zSPn%KYT~X%m^z zNsY%TTt0V#(`x`8{73uP-=!_?@omAQnt-p0Np9qL;b)u2F{yw*Du)d1$HDE?k&%)^ zUH%VT$)}`OY<>a4&|;WK9fyB`A@ZEFQj<<>4sLF23=D2Hxy$rW{2K5nlljLj zV-b!-sDsdY^+K6tD&1$oVu&hgc*}(0i3P3G)y{YFr;4i_1@%=rM3+5hm=0$MW30$?TGG#lwa3-mX0#0DFnqc3sUtZrdcH?knQ#cwK5BJaopH0&CE7^K zPkeRB;O?!h_)j7<$9l?*4Y!Q-nzqZ7aN}1t5Q46?o<^smzZjqHlesx$XI072!CSd% zjs;slCf(?cJsoXPL{FFB3{mn1h+=wd1?WY|Kl@_ufDE&o02U~I8h=QrSxzQyzsAp1A0u=)}cE%z>=ocnt zasz%JK91}kIGQg$yr$IMQj{Tzyof&x4A?f~t*W)YzQ?ki=6865d$!c+3*I3kj4f((4jS{=htrKJy&rX+W zeUcti$cUvbez3o5A;HEr45OMPrNw#$I{`T}Y44ur=ac&>hITH$@WPZgZLQCRNB`JP zE^ykrGU7nJGI}ce5D@zm+80pgXsv^bvUQsbh)c+W~9bBtJqOl|lw<{3_SqBx!fe zV3Y}0?qOFcc8jMY(F}|a;}8OD14oqCq8#Aydsc#7Mo6`Af{YcFMyL6KKeGsf#-OuP z1ph?-`UPF7m2>3&M_N4w;WV@T<>LBa8q>}8Q5_CS|KoK@ajWk5ESEvTcFGKDE9VIA zRe^EiUdi*mPru)Hd>d5}v(`sRAj5-K9U1Fw?BPQV;$%H!O74jh0MYLwBL!?6 zicsGhDyIzZD9S5`f>P7c!uv!0xLW^AO-K)qNPMR`8!7$>E7N5I1MsNp^Lzm(IchVS z@pM^wZc)~$ zw2$!)mv!_TR|qbp;BUccThQHAP`|f*`ad(|O!6{|g5dYH6kLk22W$lM zzg8KE&^%bPRJ4xeqeMlnnu?gEiRDk#L+romDL*W&z22I_fd_g4N<064VKZ^g{0F9b z-0IqlJQH5B*uMuB=MCVQm08ZOOWI&1yI~5lUCB>5*#zwRZDvLKdfgmN(=MK4zg1_(G%;@3fjGk^2tl1zIIf)vo|aiyCb zk|=LBg0e-3DTyO#-M~&Y@A{I<3ZQ)LQ+Sc}5^&pi(s@tZ}b9aW2RpmCZRPTh(r zVwO;8NsPP;-H)`1QJomDX@Z@M{Y`EsfEQnzxy4T-V?X^V&2Py4fGh$M$E$9*XjgPB zrc4;!qo}QHse>nK;qCn?R+_1j^?``6e66T@Yfmk=*kmOISnkhMus+lWNCGN)AI6{P z&jF=sIuP!_h+R^q0XM#GWZwx$bBBYBVHE~FyVyF)vRbnn>{=&*?Y|V6tU`sK z~Bfm$Y$ASH2GZpxDdfteWU zGdxMnuai)X;;ERi?-MkMaY(|!7L6Wd=wK^(_q$DxOv)+@z447sb}K~*c&Qx0yA ziy(1BMo~9ZYDq_~f{Ok>7;CF)U4|^ki%>!29fNj=HuGm)fhdkl@j;)ii2{#hQPPIb zhj;L6A};KOgh7@)VvGpdOA%lzZv84;84V4M#9mu%Xy4xCBx;C`vo!j&+LbR#$vEUC z+>t*+ni{Cp=I4J~FZr}NN<7m3k-kIlbPh|?y*dk6DgmI;N| zmcXUh=8w{1)i7h*>va zLY}C0R?p?R6=klNKl(b&%*pvtzF4*9eNB2fu_T^}Am}|7Z?@?WawSZn1~p_T#Eei! zx-WjSdgSl+0E149gou0ql`k~Yhl$w`7h?j++)039tzz;}g|)|wI7Ih1E9Prf`9Vx) z$-t&8`)fJfp^`(S1d|&_C-dYF;#s5ILBUUA?&06eYSbRt8LG;}HjK28)@VF*J84;w zUXbH^TU=A#B>Othr2Ti-|NED`<9lfuO(&{9vxk?eew%UQvUHERc z_J_;*)K%>jeFH@4yUPy#{AC&y-$^QmAc0uVvNZ^flz)iIn1a^Yv0N1o~{nZYa}ZrOs=L-_jMq zEq&x2J{sQf1f&jY^5}n(AXUOW&M1sZkW%K;_^$!3w(1x94epKQGtK5#Wa1w;Fst?uEo8it5d0zn@A%uJ6^7*W+}x~o&M(esk16W^cb>w_A(`&CQn?rIOk{jJewaY=ek;UT7m>T&Fxp+iO;im6kgSO04 z=s7Vd$3Qe3at9-M-)ORR+FPGy&3g=nT3NRFrf|OOzb(?k_d5vo)dfE5$_@LO9^oM9 zNZoJo1MzWIK&H@u<1gX!F7>!PZ6--#vI5J)CYG=qGaW#pw$-^NmE9Pf-ept+F+y_Z z!AVlfWl+L&BLMUYx@EY;h;cmb@$cJ!(>hN{`N4KWq_*EM2#~iDygRAQfC>gohzcTR zUP+L+m@jLrLMhUZqw4=^76@_7&fCQn-RjH6M)sdSe*o9NT+-_5@^Z=CQCeDBY5{bI zrEd3;yX)7GGw-`*;O>0^k_3wiru_b%k-eS1&bb^=o#{8oRytO;dws|Yz>z^3G=`ct zjUeEYFDxijn=anC@ByU6!>SBtWW5Qd5;z*&&=K7URX2N*cmiX#9E|5A**F!V@nRfQ zyuI$Q6#Y&~SVArghfpGa4d%Efx#EH4nh8rHg<8eg4X$)#ub5A@wcr^QC?oZ)!oU~76kRXwzjse4llYNty^1Pf5emnp&;?D zWI`O#ZL*96BQJ(Gh5*F7aqc(tq|{EojqJKaxH*ci9%X~Vh&BxA+XgDxtA}SE@*@3t zC1tm#zTo(H?EdQ z=G3LH<^m%BzBY#~4+@&+-Yt*R?6d-a0XlrNuhkVrTzR?Vx#o*6Cj5n8Vbp@FnwId@ z`g?CDqOI>9wCGO*ypJ{+Zci)qEYq4^?jKug>MWKt8+B*Mt+H|Q88^hdT^LG74Uh#0 z8qrWpsSLLzjFWH!=+6sGnycS8EA}B`u~fAq%^vrpGsVpoX)~mv=`A)#oC!})-_R08 zauY?ewm)NuYFExNP$=Wm|BjG_Y{;f`doWzgR3 zqwExoTr7jH=1ed-<{$W1FoMtFz(K`&O$vIVInp>RBWWZqr`YN&W`<|184E_rGIlVh zsx`42F3d}E$_L(h{zc_Lt#cg#t4NZd>iKfh{Y`zU7iH4I^ykmhgK4^JlI`flLlcRI zy{zXQaD4@G%jYMYgYwz@+Bv+Mc2`Fw9?ot~N3~oHWa0c|*-=6Fi;keCvKR+`)`l%C z^fvpA%e$X1>^E4q=S!8|dUHevqq95LIq>E7`FRWUSTdR=`FCqCzD;ti+O#at` z=l%oBcN%?+ubz146hsgf(Q6X=f8}DXxD7s8&5?2Hw?=(S_IMUebo8ko{XGK-d#?Mm zHVO(+AlRWZK%m`!=a?a`3NEEV(KTvJ=xTpIhN~>7=gz^;%g@KrYbVH{)qp&TQF*Lt z@p@Z|NFo3KasiZ%D)?Vk{RIrgjM-n1DTr+$xkx>Rnjm!o=#@UHW?WpZ?5<=>hA%Ny zw*%B@46~e(d+>=T+0X#-0_5#ydG86Vxn1v1HahHab8`c&<;29q`udkz-Td$EW;)Si z!k;{Df0S!hTQ}>L13qh=#QwfMz-&bnNm`N3PK&;*UP>X|Vx-)da>Q5Rz)=gln)xAD zR-cc20Y>j|LZt+^VqW3E)5QzFiK8zU%(Hf`+^iPHNQf;02OWx@XJ3pGKJ>Q2fxAOv zEvQ2lk%7ixd|pHO#C~-gyYy)#|5UhXu9TqbjOE7jA@h$7wWGFb64rw1@fdXMRS z_d|?cFOyKaf!xsG)lpLpd=~wGnY#s;1rh=ZC@3hQaD>ZV!2M;t=jr37U;zDy9gWp`*`-$oUz^rV65@YP?%DxWp9C z)7Z$xMC1qYcK!T-C@lOL#D$>g9Q{N3=U=+kr&B#GOZ~#1hiQRMqZUx&kMFNPKBfd@ zDNRgDwHukDWC|`|_D#+8ef{$_Hoy;Q1K;JLXKCzPuXa9wAty@YLbjt-N(uJ>UCBLp3+f96gL1kqxJjz%(CM2t5U?>267Z;K6c=hMJW$~4J?!Ji$8l+Yu2srrP?hau8yP=+t;xMp>?c%Q^4lhl zg$Mig1}Mg;whwpnx=?oC%+F_I&Ql|n6~^!}mZ$wxcxR$vtgfgWpZl24>Ig4%k) z4;@xp1xJ4R=S3BDuw#Am%;MivOG10mqN8^;E;sN1Qxh#bTy=GI<#R3NlUKsncMnkR zH||1dqZQ@lZvTu&y5)aY*Rs9Pbo0OHaPQ?58eto(=Yzxfeafn5I)Z}(7g$mTynFY~ROcrE(FCQPA!11M zeN_=X{;x*Ua@-g5xbjwq?A>7QhmtnNC#a)}1f%FHY>HMoA#PUJoIsT6@ktOO(ZuPt z{09=*zNt-j&z874y%J^oq7MIi$pK#Xy6D9>bu#bSZ8Qu>?oIB_^06B)I-FLUj+G8L zz3Lg*?inzplf7sxz&2E^NR(}T{Ayi!wEeZoqQ{MbBuQP-6k6}&ydVd=Z6pnEB3zOO z3(ADCxN6mTvmEY_gh4gIFZDz{O$FVvi&i=hAg(Aon}V^S!TE%!RRoS8N{j)%?|v|z z?#3O6C_hA=Rb*JClMu);GpA3(q<+n~8f_Q@&U5^6L%@1003`mRbYHd5hs}_6QGuku z*LHb+vKvKk;6Txh26(XH`_0>vB_K7783@$bB1B{adb$Z7^uJZLBTsI{*#E-Q#PRG` zWD)VJUFWR`46PzeOVi*`v(K*?Wg6^IW_#a6b${-p(}BqFy${8b~-KICYw5{TOH zx{lrA1*+=<$JD5A$6^dkM#&5=5s?AilWa7fUyvAaWeOxCy#WOQw!b3d*g0zDGyHFC zMZPsT<>DbJh9Y_D%}EPXla{w4>orJk7jV&`+dngsNvOJRD9qHn18}`jskgnTjSb_) zIU{Yi)nJ0n>ls27YLXmn2B;`Zac|Bh~qY9;^2ZW!_-@ljYvy?Jg#wL{R zc#NMN6x_Zx*LPQ7^!Oe*7E4=c)1><9oh`FyhQFPS`>0oHt+<8#Ezhn?Y=2|$qqh~D zl>E(sgNe4LscJ4pK1y{o3%rSwt(KCVxNj88MR=c<@!>I6AdVm=w?e z!=#f0-)~^}Nbl$#wB^+O4@WjP@0u-@#*@rW{pW;}0qE9Dq-fGUZJYA^}&3NsU$H(aWJw!u>x z!0CPiO@JIkDF7`$gl#8Hrj*!XKtB}c57R0><);WeR5zm z!^5B{(l`7IfNKH0y%GjL(&^C922R4Ubn^z?vX24hua#snbIY0k$29O|q#0TI9y z^-=BPAMG#bm_UEMwFg=~Ft?4#Grl?b7yW#_&nd*3R6^4)f=RJ~1i#4FGc~2kvvQYs zEvK=&CmAfiR7NbRF>Q_5?)?l5wwbhezTLr~4|e@?ougUqqP8)g4O7Ht+9@GU4BKr+ z1ma8W_{xzbf{q=~T)-!|?0)w`>%xAsE66+?hRiw|BgS4#n_ckN%Dq!tvz8%)|Bgj1@-hiZ+5?k2T8l6Lj^&>aG`r+cB5=)L2)? zF;5_MNl(8agz;0Gif`;)uarHVQf;GR)5BCiCg4>o31em3782vfU@Ub!UahS4YQZ+G@q#-#hlbb=HX1h%&e(PwgCxyZeBdB!t4Pxe@Ol z9MRuPp{v-l_V#+$9c#OGsw$4U!OgKxQeeDaf^$<3<(e7Y`;|0!zW`CB3e0MB8wSd& zjI9V*Fjem>4xtK*`cLK4c%@>vgW7+m+B5c=ya#)~oza>klo}OL;ACUfHg)UOawtqNg zN3w&RL+_r@WrFKReh(lnxN=5@On7MBznO-qK&u2H{fvUN*?rp|Y>dJKLm;a4*Eh@@ z7*o?C9v*ti#d<+zG0CW@Teiu?iX|`$!K&Bg6W3uNb!7%u0Q}Bp71@ywhg7|&;TyOf zxBy*olqA(pM7+`?q5umsvsoG*11F*VR~KL`it^IK%)^XD$($0-zxO3%8{#Y^9Qy3s z3+k24jxH*{*sxn|Wt>HggfrmfWh#E<7iW^hF$V#A5U``H*dqEEFSDW6U#uN-HGE*- zU6uh!P@j)>|&uVd27yVdV;we%3O)%rjzYEkd}nZBaMi;Bn!FOui#C|RV6 z$(0r3%5FFYe$DA&U;wc-R+{>G3iNp7%d)@z!QizxBH`W72L||Z)fybe)0O6bc2@9| zk@vY8kh^KUq@tlIy~vyG815xu?dCVsTdURR*!fEviGft=_}zxB_M8)|NQu{B9#y^t zp~|Uh_5r?n+<*-L&TQU!Au+0XiWtv1#;6k);7Ht#SF$L*sjd`0p@Ul7 zW6>!8i)kOUnO@Gmn$uyYpD&8sID-icQ~O0Edgg=4$IUG%CVs$FM2@(clCVWG{>Rw+ zTPC^`$OySIe6r?0*j zDl6ggalGg`U%rM6C|hi%IT!snatFz79J#OSvly{xk=LyBA(YI?*s$P*Pfi|Ld9~M+ zKQuo457=(&e490T(co`Irg(liYp-JhjGu|J`B8J`t5iT(D4kX5qS8#_9?%CKG+OHz z>!{-D->6`AvlVqK+5|N_6W^6mEt2@JicXSuh z=ns^Xi#1SXV)Vj5Pp(=K(a}cD&gH7b%0z#vs<0v@frTU}AOK8k5>v94ZI91nSHDA6 z7*Fjw>p4VXH2Z1_QwI;Gj@pg^iY9*XN_#X}24@$c9Dr&^9o|nxr|<;Q!WW6!?6&#< zu}?Q!G#;rYV}1q?%73elm;YQ%4fyC5!AC&z2i?8i{`O?_yt4L^QE>2jlA&X&dDtfF*p)$9&f>tSlPy{hM%?rnOnXJQ?g!tE|z>fm~q2l{Mq)LJ1Vx5B4 zkYujN&c5TgL~Py)dV>uVs%(P6w6F$ymAII@3#|~&p(s}Tag5O8pOfk>`w=vdJ zBab6&BG}CBn`cnTXU1BNWrdcIT=Bxt393JS1?>X%;3fk{V;yHFr`hVq`6~@3s$Mr5 z+P+OYV*$G3&g!QdcZby6r0*B+0rK}R=+{jCAnp+<{}7_(cUrLQ?9q+U^CrH}W1)}x z&EYH%ojzk#+u13yILd&7T&v3*D?PEH@d)0R$v)soR?VF{NSRg_+5&V0PbKj-l}BAN z(&a~Lr?v5dc9O$(`(V`?7oj5N0H$HV@p@jd&*EYmsfhX&K*ee+eI6>lTsLSzb&?H? z0q7=2agh6-K85&rHk!sGMiIxEo#t+&qQ}!xR9+j&8Bk{|LQI^#{X5+k5B!tUN!(DK($46?!x83iXqm^gf3lRF%Q z`(aTjEN0`Sx=p``ywi-W-V%9N>0LP61O4gjxS1=DtV7QyeKloE?I5$oIC|LmZr(oN z>j{G%{?@mFN5B1(vLu@Qn~w7Q@Gpt}`626#?*vmjQKMWlchZ8F#F=F8aJKY2%a0{z zJtu^>M?t>8EN5v7JI}I(;i8!jpqn#gx4p3pK*<~3&pcdZy%gV|dK|Aj{XH~CozXJY z`E=JS6#S1$18oxCfSrQ zI#ms|hzp}goYRuFA@D7SnJm5_2`Q->l0c;<*8BGD1GegH3<-Lmwn_qJEblmMurWmJ z9X*X<0^C?HWr1r@M{!D--k9-PUmwmK*eR z;xr2z^T;)aF%4o3I;N0zRXFQdL_y2=JjuS|W*iDb>*3#U+pUKn=94Q}eDF`{AY+2+ z>gqvLED8WeTQ(Ac9{w5tF^iR$fmZxMO+8@x+7o`{nc=+<{M;LUq_6J*R>EgL^h9dI z$o%A$I{K}@zkmAR8W0vz%QSgD*i&Q46i(ObD&X|Gx1vL_DX2}?m~uP-vykLzw|Er= zNelf`g-+OL%F>~7Omk`vN?vcm*R)DoQ5b`PJAY0lsWVIYaFB~$_nSFT5Z0LavuFN4 zvbUXej?!yy@Yk>tP++4YdE41df-kT;-}jB&-;3vq29YmU1pxB*tw*{kWH`}%rPpnx zuYbN-h-Rtioq2xl1(lR7yWYJ7=I?RW41?n=bHCOFDQE79Xh*;%nmYoLpm!wkCXJCT z9am9NwmRmq-PF0TRH3o4+6l0X-7%EhQp$G1UShru-17yejm@G z@O=HLZ|>tK%UbaNd z&}wh-4l$eRtjf_%qT85Lie(QcRnSrnp4iBZH)YxKiZToUd*^#?YE3z{wG>Le#bE1_ z`M939xE#YL5wl*_BI-@jwJQWH841hXNr1f}|4g<%eZbj@8fWHaVnRh4ZPf0a!NQ1I zePdx(uE{oVUeGP=M}j8NLK)zp(KOL25RWitI0(&@EHnCill8*obv}3JGtEYH5IH;Y zH_TrpUsDoYrK4N}55KC3QtnR-s&-vPT5X>q-^&s(U8~4}i7KcYNhN_d%3OzoX_E3P z!Bl&;8nm!so3K>Zr7z!J<>jBDxq=*uHO>{!LV|!@viT|Lgn@L>41+{z2t&Xm3)SJ} zL~qG1!?M|$a8*uO<~uNsZRY4knwm0~kBZRp=Nj!DXG$<(Ozwxof>W4Q+ zb5%@Il$cPTY2z2<#1{QBCjT1v4b7#lRzohkQd|IqzM0O7oZh0tnV{?j7oNahd-4E8 ziY&&)YBh_rZGRzyJpk!p~;KHaE~6_)}kc-+mUW7Q71=r{?=;*OWbrHavk=uFCvT zyu}p?2{E{vz@)@4Peym&j5Z^fSS^E&S5n-O~ch*npfd)7uj>nYF*;_x%_WrlIG~op+?KpO!+Fq$}=vs z?ZC9@^2rd83Qlv9ow9CURT+TbD^j)teP^B^gTJ{}L7ToULC5%TG& z$=I&!m@>8`l>=dn*s^v{D;WFn?LJr0#rB&%kHT;L;MqB5*vHDL1+4?7gJbj_@yu}g z2UG10A}BG!kg^UWR6K%_Fv>+HO>*(78P0C+KhG_?)&xy7(t^wc=g8ypO!g0ck?*mo zdbntiIgKx&evdA~u7{kc4`Xai=ItrFT}_n(!b&%tZQ<7^vd$nH6yFmGJCP)xLyqD` z$R`kh5)wrYRmtm-Uh~&xsG_2w)$Wzqlc2#axCQiuMxy4Mx}@i|H;l!0vKOaRiF`*Q zkY<|xQpDJ$1piC|17-Vgx%2Sgrn_B8l?1eJoWjQde5NiXLnR}iifmInwqw77!upH? za3nfH>5xmHJ5jHne06>aH9b%cb(zCfO)dxp@dG5w|1>N}zFHb!Np=xLcq2Hr@eNU# zt7XibNpZOkE>0%Br|f4-(QCr5T|V`JfJqZ8P9qV1P&*EGS>EdLF+XkLIH(|gSeC~m z{&;?3!h%8@8SFR~r(8Z1V6}bvjQ}t-YcJzTW9?FvvXw?H zn3`0{IHc!YNBC+ovAxfeyIN{HaKlvzO29#D%X>T}4jcec&cjgaC3W8q@-g*&=O<6W}Rog&UuO>Sm zTO)`2Bi|m^uCUK}N;c2p73;GB;_;Ud<-PN8>jT(~rQ=I6AxN+x1$FQlL*V9#;xwH{%FAa$MSC*=Qho#7CS=9t<;nU zPn?UEU+bWPLoM-JF(_-UkDiQLj1EvFZcbG1VIFY4pkU^Kecj$3wcs2=8 z*<$jzG^;b$sVlcUqxkUs8X&)=7ycnf=5BPe(iPNCx~!o&KTNnu-C3m#N>|8&#JNNR z%8|yD@oTG^b$s=oyBvvTQ@KQhYLHW?0pyr|#Lv>YmfqbThO2-%2tctS9G9^7aGT)Z z1MV^^vL)GDto?q?();ps2jmWu;Ufp$hBydY^h-q!0X0lt%_F9|>Z{|^?Fre-z7)Ww z3-=zbZFrqJN8j#W{V*P8OHCg?_%ZiSJPsAyrHJ%0TRJDu*3P76nLOVq9yMW^^D^eY z=E%q3Qg%Pc>iryV^qg#*?82(AhD%wPoRNG*4}Vj=$@i0=ODKb~AQ30a%d5Xi0q-}n z4gtb@%&&y$W;iHcY5?(pqoLBdNBjJm)K+SRgFJZjx}5ss7u zvqsgW9aIsFUoKjhqUr?y!C}GBHaZ2wDXpbCA7loY76?ABH9cB8J@HqWv%~d4Ra5`P z;w;ZiG3oZFYu?5=Gi)enl2qkcZNt^J}j5!qntTtY<4Y#mU^z$elzC6kXNe!hL>J8*>A~`SVSv8S-%qv%9Wj>CmdmnTa}1 z?!Meu1iW$6`ATzE$tmj`sVU3YNad=~C;H@04m_Q$5s{F1-X81ZtFGL3f4<=l z^;SPAnX$D&u^K=%XHgVH z@(+fv-fwEw`4>?xq|See#ER~J5utluUDeXTruz#b@285aTXe2ECL{~YOKD*%$K&&B zX95U?1kh@$>kgZrERU39q3>Nc*{dy8{hx*!X)C_u&ODpyE3@RRthaUlrS5JqGH+L6 z6OM?crc`d!mxb!R9gYo_pI%+u3SG?4n7PbSeL$m&uTHsre^5nP+G2zF0oW9IZYX$s8}n{!G7;<&2Gd3)q&m<2W1P$9JWD|dt^QDMp9`wW0G{R+E zp7!vs0p$k$dr2p!K!C2Qze!G^=_X$|T8#z4t)3)0-mjk+%0Kxk(muVYGUP)T_9~)1 zs_!lUT~E^RPGV9$!KW&waDq)Z#!`h3vH2r8tIZI5PscFb61C+vucy~dd^6>uq$6=j zD>h0z5Va9TgdM;qi&IvWfwF&Z0YjrAqoO9lU{+dz4lr>zU;f)mr$5516+$%YnfB=D zsLF@O7kIF_Vg{i!_vq$-1ggz>plIm8qqM)X$2(Q=(!i=TquSfG7uL7PBV1;EkGn*s z()ir?LfTz!dtwClTMCq>ppjABE;}}@VBRXZntL=@li?tb3bo+aPcg-q@=O^5V~+PA zq+(y_o`Oqa_+cz$wYl;bA{lDHpz?j+3F;i+_^ES|9@8WBh5ckTkZS=)1QpdF{TK0O zHR#>XS)+J0ztIpWY74KCQG4icd=pXYqKG?DHRE&QViXld-TY*8T|{;U)|2N3AoBy( zp@-=01vhl|?(j{?l-oRVN zlJLFx+LQT(^z-SQ%XeJ>Y6O54*;#uszahe$e)TkVLcmT0j{xPT-wzY9gvgs(iClhu z)MQAHgRTi(jjEh7@VhHq-%4+EA`8NS6*d*(7N%PJGU>IedY7Yf7R%ikc zw>~GKf+Zo6n6E6IU(>OJO$`St+N{mwmNT6AisD606lvJv%1#=sb@&7zo`(Me%z3dK z_d`|L1L$@a_fkPrL3y7YABzdFbmEQOe&JJRZh?X}KPOOq`u}J;2Zz4D_x-13+qP@3 zxN6zfvTfV8tz}!wcFVS{2+Srcg&#ABpi+l~ z7XhY?Paq#lMK|Zh_h5+0#yt6C`Gk3gb=@8Xb_^mEIQEk@kw>QTuDj(W6Pq&4`uaxF zXlZsHotji47>G16SVgp$O8QV?r4?8E_n{+HGOvYH7gTkj)M8csbGg3X+N?>GzBk@G zovs(^+=Scuik@!!!vDM8H#oqaGava6T}U(!(vs)lDkqnuyS{=?vJcH<9*9wm7;_d< zLsLNVv1G(y7!z(1&y6)=)u`6uRQ#Q6jv$y}Yk=<<5y=h_c47QVSoKgqVN_{D+|;Sc zwabmTRUGs2_VL!s8Y}@Lkvs==Gp#aI1Q(M3Wp%Bou3bOAoyfc4eqoFl@Qs?DLG*s3 zwB*u{amy>9od8T4r}NoUW^xOQpc?h6#%kRfYi!Ca5jtvEaK&sJ;}%u$|Iyw01hF^)YQ|HYOhe^ z=kjBg-Rdk8GFlOK%uEi?{p~18d`wL9jl%zb@;FAMl{0x+Zr`TjvXw^}&hg_!A<|%k z=Hxq!CkC3hIMDMj!5{8dd}8{vn&$k+$!=UcZIoVC=0|}mluu#%$lx?qka6|~A1W#j zU%Uo(rwpB^b;xQmiwrR3vT-}G|9j;>1MzfzM8M{rw|^dbfmHLf@zz_-1TAiTN3y%r*e{K98UMS`i7ysPvC%kpl z>R4B@=bDI4kf>oP{cA6o8jQzhuiYcIZ`kW3Ie1x*JG#?M$CYc3?@@cpG{0XwV5)C@ zHPzpKbmi9f|6wB?t>63Wue4G#4r%g^fFyZBbbO4YEQBC75b1G&^w1CX@0( zte5dDKlc}Y?zaS-bT0iTc?x8$gZRb9j;~#M zlihlgi3|rOsxBvwG|)y#eTLyD2?1;+m_vb4%JAr%Ziw>eS$o9fB&4Dyt^(wS2mbGW z{CnD-DoZV`v#n?JzG_ZZOG4b_*HUZIS=QTTmxcn~n?XsU(E^NYmkj5+l>6hh(hWSz z9d59URceo~>wZ_vLR9CPiga)_-H7lD>eRbTtrk}Y3W-p5iZ+s!l)~SkbGmv(b&6F=eH%V62`YkcjGTus$u_W&Pk(fksCb^SD+_+~J$4GhGOk7Ql|W?IMkIl2qd9W2#}&DurIn zpeauQRPi;H^tYR;n64%!P+$g{>P1TKSOguGS*mYROnntbksV10g~el(+rD<^E|i;~ zCF(!v0BL8L(AIWT(F8nySX4t@PS)5B;@%=c4gFh08Lt%371BBacc!WZ;7dknOiHF>Z$>E`rBc+!v35EZ6Wn{rI!1mV(7%BlApvxUkn>00 z*fV8JKx-gICZGfs5C;|1W>ml0o$v0mIe>0OQ9d?yPF$u!dqYRH`JXF!3Zlw!o@>EMuY5b)M+1t^-8k;x|O z%`7-W%1Te_blQ}y7g?ryF_N+c2y3xM!*-CW#U^-@2xG+|%>Oww36Wk}YRGlVH$#fs z?6mxv2D*n(73~|Cr~z;`s5t-NOUrD8NMn@1^2^|iEwT7-2g;OzK}B|YxOcsjfeT+3 zy0Y>OQ)mOdU9Fs6CWI(Ny48mt8}WG`dF+vU{d05uQs?P{AaJcr8RVh^$K@!|F)W^z z!Mj6DqSTDSh={XP|JDVjPC{kHv(bgnI;rlV`Y!Gti;4p*pgBzQiN{|-jZcG{d1 zh|)59AQ6+SBSqzsq8#K4Z4H<)&J}|u zI4_lrBq7d_y{tk-$-%*_HL+ufTtAe%P=DnzF|yQw@TZ2f{{e$suyAph?}fS2V}&_tXwUU%V~g#-Cy))fm47DOBxSg>Uu=##{qc(w~Tn0kt& zB_*T8zExq#40~P%I*+m}HWZnPbaui6LZw!_Dhn_2BH|W^30oU+VR7~i8~=ysdud@& zPLSaX?AM=7hl00)CV0ynoW?Io}f*!6rfJkzzfXciPbo{^h05iH^M(FfzS^@sL+ zl@A#}G_%ERCN(=ku*62PBIs-b3BmU76%gXMqGg3sLYpexYWw;r6{Dh}zN4tfH|az~^jOBDop9_%SaAbY0dW=>NVni6B3D+G@zL zr9(HCHOCylf6kjYSLn^16eL=kK!v8sXoy~k&inQD+QFpQ_;Z^*{@m2$ffZjZ`rFCp zq7y!8Ly@+&zw0ik?xk|dWT;a1t=i-Lt&G9tvN|G^=rg+pR?a?2vIC9zLrJeGzIh_^ z3L32~ny#=f-x}-bb2IWADJaEM$M3slu7an}oO|02Lw+YxwxKz+PHLAY+x_%VFV1u^0I&5txfr> zLFl|GiIOU12n{{Lw~_C+pv=u+5oU>3-~k>%)>J#nq={~k13DK(00HLs%OlJVA8*W$ zhu+;@%OGia(xhAqc1*eJ_Z|=N4%at$1C7K~*D`3_`UJlyO$l|%$>!%=hHHT8qC{yT z291@iBW$)7%%2;Ep8q{YKQkknYS}QI}O%sJbQFfzbYpD<}de;}w&jf2)1 zpQVW~MS(P_8H>}!33GFG$^dVI%Lega;jAG&;Dkc$>GKLPv!0aK^Ro6fjvI8 z%E8{}IP?YOE<+^*@SaJA{4DkEQGU~zeFmlP=}!~HhS7MWn0nSx#wFvZ67v{Y@g38H z_^S`oYh!vOJfR-{-(u9-e&Q*R?zlBPjhV@xFawbaREG13U{HZ$) za!WL1f5OCKCT?FpUc!yYvU7sqV94O$>wv-7=dlF&p5~6UIXUOO;VP{baXudWj<=1* zv4>dWH@f`V#-Zdeu+M(H&Qxhu2TI z)_^2v4rh97g!xur13GjOLWrzt`R#I(MhUYQjx5ev6@ex8-Sf2!-Ij|)Pr8z{E?*(M z4h#f+3&ABM3_-QRzn$Sh7jRV7Bp%&6k zM-9))x6q5W&o;E^sAy*>Pk-Rdh?pqEdFltJHG~1&Uq9IWF}vdh_O&_%eOS>*CkmaNG1H#K&uS6Z}M?6haE0y3`b$niIA)q3RUMg{~^a7Xuf?%XG|kSjs5 zb<;xP4$psqn4tflK78S)f~1&Y(jiOZfr0%FW3$66k4dyqDI%AtadY9Fs-w~YrkZ(w z+^CZcHPfEhEmVRJxP?$P(yk(v4U!6uYzS?gE#aRc94nLKfWC}* zvdw$Y`}Qy{T%kH`hLG9fy1>dICxI&6Xn-p!-vCq6m-&q|C~oDAlq1Hrsp5)yZrdC6 ze>-r15aNm&l@LZ%llLnJHimHr^-&|?2qPG!R3<%bH?Jrl{4L`h67UTH9FlV&a4&aT z+t_Wud0R|3Gj5V}(1tB7r2C`dRV_Ls&s1}xm5$?ff(FDSiz?|D`U(?t)?cwV3-kfb zguPnotMOd-`?fwM@3ukWV@NQRKP7mxMV74ylbkLT7|VIj$eQsKRqIw8;p!>qM>j| z3P4+!;gr+(t{cCrx2t(ti@3W%}mwG#gTE zewbYi4gq(7^iM2QB<|eZ?0y28jztn5wvan<59b;XE+CacH$@>1{{=e~Xur%*(&m+# zBZ7m219&+0Mp?9JLw^WWP7soiaLFY@6Ls(Xib5swKQ~7YD_NVp8{v}IQ(S}5@<{-E zlXBQG*(z;Qxer$iL2*b4wDm~d={W-mbm&E&uaHy21A{lKF=E7&PAi&b-EWM|Pm7e9 zFrzLmva#XfTjT}@R_8d14sbkJ`S7E!vj~y@`+W~l{fbP54$H!mwA7q*`1w8w*Q-w4 z@y#)L5f+wcH}p=a`nP#KTCr#P{C#iVAfaB-!!_QZ7E%v4!TQ_Hj!2O!FF~GYze!st z1JUp`_E(1JRC!J6{HxYL&3au7}`?NlFfP0jr&^AgS* zU4*3h*$}t1Y_@s@v=I~=7G@(%Ck``WG`HGtDGkiR{?-ct7ntidUtW2n5w=6y=$~_* zV<$}vRV-?u5!f5Us4)1luJ4xVRdaMWpf42PXGCCuKs|x)60mqfgtI*8(n3dt5_ZO} zvfVMvUu{I=x;Wf=(#lPx&wTht>str8uL@yM^uEd{k(Z6mltL>HHjw3EsNYY9*{Zfk zw<`r87cLa1+49nCbf1-@{?vN9Xl?pmS9j1%$RTCdj3 zG=`QYD9M44u_?Z7d&W`WY{ZHkDKTKEmO@qeRbW{QIEYu(EwI0-FC%VwJh>Do*RHoR zO)592GGfalN{XUxpQ`KrTeV@J{f}l9sO?5A+xL~_w1x#t%2q_v7dTNFw0#S6LUiW$ zct&RCtWr^CR*NmS$}Ww7D!5su zS~n1R6hscW(u{tKl+n(XeSUOhN8f4hz#f%@d*aA@kV`6Ti{C3=)tk`l+ry|9iP z{AOM|6L0|^T~z#J)TusSHQW)LtHI9BD}WwFOPE<^Adfyc2s!xG!L}XFidW_B{oD6- z-l(wsGIRMV@REN;Y3~Ac+c)s#wVo+9rlkdI)DcRk^eH8;Gi7K0w;)4Aav3I2#{gsl zOPNI(Cf^JYbcKw9(z{0(r2gq$CAXWLGE9ML#v-v{YF!*5nKW?cn%Y#!E;Dr%rsCzr z!sVx9j;v*k;!GO87y&*uCHmLnmwt$}6P`;mB~KJ#ghVAhx6u{+FWjk~>Gp#Erv<=Q z!EB$L0#-cLQp0k?7eWmmPSIfDV?v6BLd8A%dLeY7*Y(Aou0E+xii}x$JS5Zw!#dSS zZYAc>!N`EMBJ41kPVzETW=CKvQTeCbOsKG-REjFckfRQJ=H=grPyf#Q43XwYGOaWk zxdps1Zk|>y_9v%wUe?-ss9N>z?NM#}ZoocTo-*%9sF{{Le%NBYB3wWrY0QhPcrN0v z@&}9T9q9F9xn+m~TtngHg&}epeDP5 zWCL`<84kMCnKZO@*!pUkn1Ha)e9NgKREgxv%`<*~J7brsD?1{wsvsTS{ z2asW98N*bwbSwBUCb~9(*U{S3yjBhhQxQqj&_E648v6NDg6^DG#s8gESI?d`gWvu9 zeYa0hkPf)u)}y?n^>CvE*kUMHe*|Y|TL+OgG8Q0ji;7FQSH#if+DF_QBmC>g{ToOW zb1e>_2(Maz;6sDHIQFUFOUTiq^g2#Za;I%n)@IHYJLVSB2Fr^@FxyUw2x~-^4;D1k ztdDq6)nsy<_W7#jNITW-hBSKj^oDFnQg;NP8TV$ zhz7!TI2QipX8K}vJOKTU0zHEJOQGKWDjFQ|b{COVK%gn-Hjye3xcP2UGRrk~c2ruA zuQNQy@b|FxyfhXTl0TPJHdgKz%uZ0Tf2L1o$@ADb@y(lX`~z4WvSm)poV)tuMp+IB z)AX~3^@MSlK5aZJN2#*M8sa9YI1u8D{rhVQuJwhPJC*qfI4TWYI#<xGnL2LEz=d;$@wkA`Xu@;Iv+H3xGe>yj93TM& zr{xTY&?&C5B&Yx{xC2LdijjpR^3M;R{ohKI+2wW@$)>qOE{bNA6g|6_hbo5G*YTCV zrbq*n2>O3pjuByUj5|&{t%NozJBSlGSu!${<08^IVpL@hB;!iN>o7M>vu>JqN-uHe z={U{aFLjSTEHM#x^PBXT+b1pu3$OC1~78k@(SZE3!!fS!Ztp_#)7RH(3UWX6yVCf8s6J7V`%2hIUn^@%M-->l)j*C-T0 zRw;8(n+NTugof_Ao=s*P0&elP6k$}+s6q&7G}68)uq7?q+!C>Ts&~F{R=FmRtcTSSEerUEw= zgv%w#lgQ;5rH%*!wE1BeqJ#|VPY2aB6R4AKIhYe)E8+AdO-(g7#>$vweep*`x>awnfqCM+(U_`oNsV-Md?Ys}dd=6b(yWB59 zgAH-vMgd#pU!%9Xj!c^E+?dBnv!rWO=VeZfw|?7r%Q92M9A{+|Qx=th_Wd0k`e9FU zldh4MC|rn&o{&ua9;uI;DX8Jc9nH^IgozvW=eB$2q7e_fNalW$jPAcrzZQpf0V)Ih zn|4+KrP9igvy%3s*A$2e1RKB|;%#stNmM(bdoB*qy%bF7t|Z(MuUyZVJ#&)SgOUiR zT4mwy(V`{h8PBgF!v!uX@ieO!4hCkCb!<+YpoVBp!V|;_K`gw%>%#o^VcWdHHmNki;K?6>+c%?>x}PrF5OP&bJ9oM$`=Z?h1P=SWperUZ5(oRP$)`S}u-GIq5_O z?$${zoKukR1#P9M^;O%Wzut9AJt;9 z%q^q$Hs*t1Y@PNA2N+`NnY`T^W)CoX*A%a-yJ#Esq|jg`!gS!m2O+cKipkrpx*Pxg zF{31o91>x_cxR{T&ANyn z#Yq48`FR86N|}>M{_l`z;9DN^8gx8(U-V`ISWk32=H+siI-N1OVI_8OFshH zbi#w!rxJ3*ko9`@HB~Ml(<18LyJHb8xIKLSesWPD3s@%}9fgWYpsQ0eN1slHEU_5c zH{UX2$>~pYd=K9$PpKp?n!-u)XC*qJMBPu+S*7jL)Ip>cIR#Q9j`JZVg@$PtfaugK zZJZ`K6Kd2M(|7HRSb&i~N0ax;7u2xzS-Qc8C7HJfGcX5OS=GRr)93GTbR6s6<@2DW zR@>9t6ELifZZ^E@v@0`}Ej<=g5yUtR#wS46_zQsL04W-kmE=nUq_2j9K>xNCE=Z8X zpG#HB!}B=K4ZzYPZoF@`zTPFi$E&)K&o zjOZlgm}Fc_SC6^z{%`Fi!NY4uF62096x)GW#NWTjEntcj#1rU>n*@=yg()dj|L&i5 zJZsC69aU~$RL!(>E5byB>rf%(5!)@mBkjX-fW>VwJs5fA6>VrU&7vN?#r))rx6K=( zpm^pxlK;di1Po8Pwmk-Mo(e4SrKwtMy$|#6pWX&pDVLD&Rb=4z~%>j zMayvy!oBxTx_iUYZK1!A-4+@CxQikm-AWuXUir4=oEYzy?e=V~o_Pngnzo@1hKmE=t$bN0F zHZJAi;4A!GV(};-;AJmouk~M{nxEAgLZ~Tc+Stfh24Rf?gxX*2GOw#5JEh_Q2oop( znCvvD)DkSfkv8d=+ zG9g&)riz^kyUX@}F*q1kXHM1E?MRn0f#GU);0FPM+l~?qM*OfqZYT)3dP~1n%jL<5 z{_A6Ku>AUjUXy|&Q9jTHUFgOeAOQ$sEl>0Wo~2&9m!h+*5pHZD>HIG_HDAujegj8z z24jf>pjIuYv?@{N;o)IJgj9krt|JUlPM~aWYg?^Bo}<7S^zN*K*qe5ykD6x=YvUFw zK`>bBCZbo&+vF(LeCh73!PsGtjqb&2x+V4KXjlB8Zvfn~T~_KUv<_t>5Ph_JckTE$Q2Y z-vuA?fbbJ$rsF_U+qxTYu;VmyvBX|C&_Hxa_~)`~%vOf7KDPbP;m&p!}>NIN9m56PAAmJuWhL|xT*a$G~iFfXQUP?XgZtTKlgl5~H_+6xa>9laho&=UT8yh9(Mj<%R3Vfa4paW9^G z6Vdy271ZUkpIXSm6*g!rQj|H+ed=Psmn%`mZ0m&)f2x!~D@cjAy8X8s%V zG@ZMos4-9rC#<8|Z@qQB#Bs3G`}Q%xaa8B`uyU(tM4nt;OJ4}15j7)m?4rA|#VcvD z&o~<6&;3Kz0JpUEtPes0X0)<8ky44b_B1On4KIk)sDgI1$pSobgrci25z|x1WMFvk zdk&r+NBxKd3Eu*NpLAg1Hsrth1zSTQp{9_nB$DTwOK9ZZ{6)Mg8`n&*m+6Jq3~3 z)ZxTG%RJu*Aj&NwTcg&4NcIc8ORn~hi62JNUK$YFv1(jYflc((itHj+gcs*Ft!xo> zY&jSC6o4SxRLEIX*;LqU(>|Pls?g8pm{lOjZ62o!BL1reBMly_jeULi*)z-Rlg4Qw zq%_(tXVEYjXsZ|xVRWXZ%-K0QR(y~Ob-TQVxXTb#0Btv`Fg$v<6>Y40 zqZu?&$^y`sRQrDl_dJ8!-;cXRL?PH>wJ`|MldxF6>GBMXTyJ@^Fiuy`9%7Ag?JGAb zv()(B^Wn$;WSNQC9k<0-FIr|KO8=2}m4eJbDenZ}sdZFinm`Ju9uct~AE05Y40-%+ zOM;G?tSqHDtCAx4Nw!;65Ptj}gg1|DAx23b{_6F}ir8o_#IquNU}1THGE`eEq0vp- zoiLeLQlV*X4RRwR#UmuTpoeKHMVrj0wo;4lt-rR8K8OFpB11J05B|&))bmvqV$^{) zx~*-#x#HQWTy%APQ}gGY$^h9aZJ<)F@i^kvqMEIzDaSxqF62c?n3td~CWXntXQcMq z_i=Sbv{>p6Ejt&{B5IOLV!zwDZ&O)}5k`zDK=*3gA*`g6oi8tCcX65yb9S*h3|du% z1Nd(#AWz<^GA2gdk{^<+su|o08Q%8uNIN#_4zfWgMF|$*?WXNkBm6D)aABbVBh93K zm(xlsx!{FYKRrc6Ym?cccPT<9x_Lx)>zHCmGsO~{bKM$Y+caUt>Jyccun8_ap+V5w zeOtGit~S9%STB@?du}0`U-EnFzn(+!e+uhSAZUs7)O^5F{f&x3^+}ykfMuE)M;Oi0 zLE+k~<#lw&x1+m9VnLQSk)hb^V9x|aMsBhZaS#lwtwkY;(o^^lPVy0R)&`eKEYY3o znP5qr_dC3V2xx(W;o6B#%v!OvWY)!tgp91Qu^t~e6e83tfMA;JDULy=9cpwT>Zb;_ zQr(KKHf&wK6UeEu)h{51yv5Qw}CxaIkrOD1e4h}Sch(*ewDrj<39a7EPdU6PqNCf zn8H5suypa}bdvS0k|4K{*wKI>=^-*5c5twIMg)#w?#R%VaFvV>OP)3C;P315qKc7* zt6SgF{x-j@vc@t1L7%2z*eCEqoc1EjrML+#n>BftuA=rEzPPFV z+idIAyN`T^0RG-^@ICxgtbG)XHpfqDJ&ms98El})?Pdj$OKq}iU-*frf7Rdcbo~?z z61Lob$>cAI7kQ}Vm%V4<=_`Sw->QlbY|Eh_O8muIi`!wS716uix9l3+Pc2R%i-dU$ zWI1%88Z#p2ve&ldDy7PxeIEBd57J}oX5HBw2;iIhM%b7hh>9+(z|~X7Ur96X3)}xB ze)|IeAz3YWTPJj)7Fm~CVl9gX(v>t7TNkXzD@%gjLfpvb+M%lIOT@zdI#FN*3niHm3A7arP!UjdT( zYIFn5i0n3@$q-`hwIZUS+y$T0Z4l#5=|N_ zS)Kq-k4>~w`-l{njB{x#uElEP+v-!V%(Wte$oHv`VDrZc~V4 zC{SEHPX${<{=AqQUBicMEPE!KLb`;w81qyOHH{sGFIv57Ho0X`05!>0tLN{j^>Lx2 zqjY`EOzo1$$(JJBsL2p>#D!HI2KXe_PL2H2$TJ0`t$-aJ1dTKdQW}O>t>n@Q2M{6; z$+puX8C_JV6oi{!gG_>o&qM#`8oLg)C_#C&-O5?=OLGv!YWpQ(olMJM){O4N8!L(H zDR(2Lo4E{=K>OQfW*xTB#wAP(zV_bb#r?PtA2< zeNmMHUh_Lqpfr0<})Z2s2&3o3FlI zja}~p`??c7eDWj8I`k<^Ak(W`XT4p6$~O-pq)DjC%FGVWdT&}TEVa3;7HWJJaw6=| zJ+YIn%9c~H{eKVhP|-B=z5Kb*#K<_}EP@?OnGFsCR2Ig~@soeY_T-@E9LgMQ7}`hr z$C>}1m5+0M$SRKSS56U6v(rMGB|+jNQ-bj`4Zea!RF2%;m(!;CQ{C}3ORJJllSAZ< zwRpU$ZySBB`CNUcC9pMiKYt!U137*gUaG6V_lFW(vy8-x&{CzT0H(v29Yfp^3IF%O zFCUK=Ms4Zek5|6?rNiOu-@+Z*#G<5`XN#}!4vqHyVZ=-`YrF@sWgbuN9y0zMHB$CH zv9Rv-z>N$0WI4o!Ew|)4Rh~kxJrhL(Lq$kofzRno7e$4aRN@(kZA)k&*uZw$319P# zty6Oef5~?PdQXFv5J4ts?5-Zphi4!0yD-K$okNUHrhe}D6mQr!MfrYKSyU-}gGTNZ z?jgAS6Z;RGQoDSYU?6j$8|Dinz#1bjf3UrTr{9{a%}=5nH&HIO+%!b5xrt$1aBs|X zDsr@0w%yH;(&!@w=D)2?uRlovI!K|j%~_^V1~-2aD|xCk(i@Os?H0As5W#5Xd^J}Td#lVQVlAJmZnZ@ND*^M0%fG(Z*Dh$pb7c+`w+styMV{X^H}n#tw|el zs$SIu@giA1CKn|C&zf%A=qGTbZ;;^W-(bpy;k1|HIAYD#C>=Wp37`us4`tcazp1K) z%1@`k+2D6*#qRC6*#-)F!D-A@dsw1pP1g--=P`Lbo?4V(lxovH&HnRf^ z71g*+H=)%HUJF$MBA%hWzqcD7mvZv4@~rawiIRvtY@@KZig&MiM`tTD#R;p=v5y0w z>fEUISzSgBC0C^GWXx$rN{S>yQEHcb3&C17{HQ|Uhk3Bm zM+`t+DTwz4|CsS2ajl*!#1!^0HKan1iz*y*OehH*+#^i_^_>y|RM*h=`DOPnwZk@C z;S)~?;C4V7V`uDz;#urZL6zJ>$z&+zNvfn2Tyd9~IKWIW$$Q=_ssCZErPog>8Mwl~&3E}!))<@l3-V$a`4N>&nh3zn~3 zL>0mY^|97}EM;j@Slp(_sy-Nt*kP&?0g}SGox<#lw`s z2i{-4j&@`k8M=lRX12Cdjf`Q2U4(`1>gGU`i8QP&G)VfJ&{)jG7cF>6uS{aR6)+l z0?Jq|KO#e;ft%^x*FTO2Z%lzWH_Tfs#pafkz4(~NsS7R@s`H@OQp>mlQKb}0xCRDz z^CTO+27Ih54YllyU{?|6?OqsHRZHWyZyT717bUUuw*ANUM*CJ^P=+jl?1gyD}vW2|*Q81P-fAAKtXf12pA2&Yh3ZuhsrPQe#R;w!As8@g9zZk%8(@zi)kJvY9@S5(NZ3)sc*xeJq zyl;qm7pBcKp3wG3u@VwOrlW20b@}tI?VNJSh2+VB6@;-E9v1oY=_>l-u;ssJmp?1IgQO9Bm- zU9#z;gS#_HmL>Ca#C-EY1aZoMlEuJwxPm;IV$??DeRs^}fcMAF8*{irIJ?&(+4^@j z;Lw4-ate=IEZ8uhX>4=5K;@KewTrd$3fd;!b=V9MT*b(qEaT>TBP~u7y6{&rEd@4 z{2aKjNrYo}aCBnwxz{ZqT1+x4ZAF+v)*Ob4Ka2yB9440KLU#rC{8BJRdEdj?ZJJ=$ zR>!R3*_7-7JxT*{4}!k$ovrlGSk7bK3UO!%WD5fWn9k8Ana|2?gF-}u^;0cZ&mZ@r zlK= ziWZy~8uzaUTgf$*ND)h~IA#dWpeYAF2^jb(f~Y3f_bG|5$2@-S?f{DEd#9=d{+@Fd zJUuEG0nu5|4~V_(qug`RENM{+C?Qg*O_1#*L?P}S{F^2IWeRL&|*ex0K&0<(4?{`z+SO5E+qNiqOCyDL>J*S<$NwF&`Epas{f~ z56Qk*I7fdX%Om>T<>P}JmY5Owt3Z$D!lEH#H#)2IY&s1k6v*nkS?;M#v&yP;Jw$a9 zc?EiN&aam~ZkFUwMhUud5qMyiB26BOd{NZogz1@*1BCSfh8i8EkYJda6{#0#mOQFQBPVs0J z>ol8JdGyEjp`0J8&GU2&r9)G+Z7`=i>}J}On;;_%gSW4~&>A^V5H${cfuH&d@_+~y z`QOR!A3yvb&lNs;{@%Rc84(JZ+A9*uJ5t`naFm-GoaL$!@hX;Z%QR7j$+g`ibP}Yy z+h`MP@fn*qN7U5Rpo&X1IU_Eo_BThvkBYWv5!Iv{TC%QCs7S&opO6oI2db%ND#?~V zKcgsh;oj-o*e`OdiFHm|V*7qJRHajf*GnXe>q>$pry3`nwG9D96K*m96>KG1JtD1xJ8cmJSP4@{NXapM-(n5!QTfs4xdHquN=V9>qZ@wiyy=O}_ z8E`>_uHF|fbU*w7G~ky+@~b2j>7o#Y3`*f}weIAE;e#~4ggMTiT3L@1;0BRSA7Oi@ z`FA`$)Zplw;o@t|hO|9~c4c5CMWZ>)H(-d$b|j<^)k_M`({oHhWN@5ro{9b>128=! zPru{!{3s>6kx#Drc@O$PQyPq%PHL8hu6BRr({55s%ubJ=My`Poex~U3Jay41=wh5;g+S>*bS@>wywAY|aQ3;?2$Mdg?Sj(VBk&n58neq*>fHulHZGK9( zax@?eClGg^6PAAC=B|=_)}V}`)`aKu#hRx=Y#SdEU6s=Wi5P#5NyKVOujko|4>30j zXeu!rNf#lb@XFhXG#|s-^Bg_;TYO)+D3M{kCAJjN%I>F=o zon2rVL@He}U-i`s&Xc4a2~#9|!FP*xn69a>7N?l-eJxIqLY!7Oqf~QqYrL-bnosL8 z+sM?2zK{BNoIedG?VgC6>;2$UT=*+4IQL`@Zg_xPVBol>tTc%H@xJcXj!l zI--};sOVV~e>;)1<8guJAb$OGgW51y1A8y;w~R7cd`}DL6r&DqsLA>zX#hsGqB}wJ z-3AC_=bg|Fvb)Ctyl+n#h~E@5r9*MUKyrh|#Crl{Jqavr7T17;@$Cil5up#4`ig zGZ8b+P_=O>Pp5dsa+g1#FL^rz9dNw{a+`UCfw%=%NioH7(r=@0N8;T)q~VHKHEr$B z`cEdfVTH7D2eeVb#_pKYqNl}@p#3BZ*UEkZ z*|MW$qsg7YIs4iY@{ZDUIqIdTZ7Mqa;TpM}_kX=fPCKq$!z`YEJS`Cfb=?re7eJ+M zk@q?h!hlU%XkZ&?&V5;mWdGrkOiG(Xl@BooZLs=Sm5>)$1mBjcKlW=taI)d-X8^8- zxwIpb7fFP;1(gBqE;(Z-NUn;5!6)s-+`e}z8q$-d*c^Sw))oyLD>8-(i?BBx{0|7{ zU-=_z^-)HH>bIHAf~ze~4D4$%(uk_D|5}k|eWv4Yw^Ba79qYEG+(Ih?OU3MT%+^E2Marytz^p#;zc5T-*LrEju z4U$76(j^_z-Q5jJ$4GZ~mvp0acef1Poucqv_wya^0l#79nmv23eXeT1zq_;DX7jKE zNV((g=vv@1CrK@*8eVyVp51+yS6o?&Zt$LTyFU{LmHKAlYsbUh?DQpIOew+=kq;75 z@cpxorxv?o>S;DSLsFz?>=EjC^upj*FW`6(240p+UBQl0&;XGsRn`b7vBSq(cElSG zyxWg=XRFB8&g8An9j}W)e~&{^2+~dAnXhB)(ApmYSAY8ZCob-ncV=`6dG}vku2k|R ziTQv}svg6w7|QZpl$y;+iLPy!AKQN!qsOsLYtLn3@<%yu%R~fyc)I?nQX>GcWo4!X1506JQINYL|>q3kj{sME|G0 zxEpxsU>|Ij$ODwWaM8zeoJutCe{5_$U?n?a3dS%7XE^;`zh;JDT6kmQ^wEkr)H)nm za*tkI*MvKYeCuew_5VZ+`So|FN&-95bHSD;c2{sJUwQ=rW=6ry>9hywVdEy+8)Fh2 zki4_|shUO8JG@S~m5Z-YG>;h!FVD%;V>ElR!CYs&K=5bZt1dYybDkITc=zzKDLo0q<6O&DQ31u>8B-`IU}L}6xlM^Tb4 zE`SK0-?O=2nXByKlCF^Jam7|NzS>n80kwI3b6kaURH<~{j4WD)BjQSIk1l)%Psin#7Fm6_>fa;2JZ$=ZC;b$~I~kl_ zJmi-tJaNM9aU_01Bz~!gsTZtw-XuQ|4gb#S(Ar?E`@WuUjani$j+U(MKd%l3swqTD zO#IgI>#$sJ5n4QUYxit*WdGds$&6#sC&ZxE?}!Q@nysv?=;Z$FvwwSzdwcqpbuX>s*FT~y?*b_lWC!m!+l22V&d9le^c>-6KqGJN z>M;X|Sv;oKBOn)Y!@WzoJu-VznrcoGqS4hztc&w90Xd5AF2d~+rbk(qe4l0ZH|(uk zDft$iMBct0hlLH^p%rrmsoeiWB;Okiu)c8o0m%9}*e8?*6mIR2(T{iz&!YDKw26`^ z9=?sF_EN?A^VZ9mK@Ae}TnXG|Q;i-#@44^zXhb@9Rl`Yd9>-vf}uH$1p3_uz(|| z6VPl~HM-U2s}U-w2)HQ3W$!G=-DZE_OUx9NcR4|X;Kp7c49gM}Nr`{SYIl!JBCPI2 z-rtU-6~A#=RbeHzk`Y0V-WUfi{)81bl&k&9ZaaqBG_3}G1&oTbGeym4B5zmh_pWAC zjq>YflC=3BeThVrFS_R*E|!AuQWKA#p2#pH_%x;93HSwAc}Td#wijIu5;S-20z+Qi zHrfPI%}U}&Zdj!f-b>PB9b6t9T;{5xqW6ou_J^zS(26weFak?`_I)yFvjpU{@C8%M z!Whw|YGzWYvYQh6{Z#To?Fddv^}l+aq;U&95sbq$-AtsHlFF~T<77((uJnBDu635L z{&u^)b2rw(V^LC$H!3m_G(R)SQ0GrJ6+jFl0l6Z`m`|Qmb*at3*kfbGTlpFC?S$d}?ge=GPxt#4{7RttSLw|$Yb zmb)&sBf;7VWfLJ~i#k*RCvhJyQqwps*jXG$vi_&T(W2@=12Em#E{ihJcJX59Opmnsqf)5CD0w`Q z!pD{WN=aTo)Ik#A{de%O%Ik|Ov|SE6vOu1GRlA^q7hoIJR|l+%av{~^=M)s@X^`nh z_dzTKPI7s9|HxA9*aL6rV$io`1w_UEIj|nDy+Q5q9W&78ZPF_ydAVb*fe z?chdAn>VhiFow2ltgc>*WKj}oO7SYEq<@GQGkH+Qp@kF!HE?IHV(4*nJDqUy0F&Ty zk>)Wed2I#k=-|)G^{Unb)>43Sq~5LW`N-;V?pZ_^qE>-Ny<5ni!9JmFs6ExM>QYV? zJaDZRO7kS=5~*7=)NmH~jsNp4Hs_aBmP`9HDboaJchDo+c$0?I%T3bo>2HS}LbfYY zUQTt{sT+mEH0e{6*xeCn?$BP-C{**sN;^>=u!EaJnY;GXl({%|)X5IHC(6}>NM&sH zj&)J+>Q}(~7tIJk=T5CX>InREZ1?RvX6=OFfehVkOWfTY=VK@~$WgycOXc|KD%t-~ zkKa+tVo^9|G|))Kl|N#PkK!kO+`#XE$Ib9B403!UhnWRM;`26l3e7@;gR_y?2tYvk zExXY-&RbJ@p?QV{c=Bv;m=y!|l7J_B(eSV>@lwu9RkNZxi{b>D9Y8#Omt@qe%&q>o z70FOkaCH+X<2c>~$@2UCZ~u5yjE+_^X;y)dm zP3)X=G7O`#evdTQ9I6?_L|VXWjid4UU-tixv|f%Ld*3dg-Ck)H9J4$19>0~M>nk6Q zou*K&5LQVW!3ExXNdSX3E~B5nSp8<}%I(%=3`qVj1g8zJR^Y3|s zTH^5yS3~ndihQXJFpqa3l}l72MN)7K?q(1iQy1?q=WQChIOv^y9i1>0$x&2-k2#WN z;;2>~B&PV*G|PI*m!+lx9_)I1eJQm;4c;yaB3n!jLfT1vPv!sSiKo#)8cZ4aUl~Ax ztht|`m7ClAiw1%TZgM*xl~_qr6KTIAC?Z`+U@#qAC`Rau0pmuw3+eSEO0}rS^qu4P z-gUZQxDDwDse{uKu;<|ayaCj#&HlP2QslhE^5T zIE#{>_tn<$LP^SsBr#XeEzI|RDv&IyvV1(9QbyD$sx_(PkN%W!A}%zuE@y>$hlSlD zP)%{|)Ik^hX5D|2PG4_(ktu+Nz>lzrwA~B#ga|s!hr!+J*$q~O z@d2WnUd#*kF20=4ORb9gO^hCN-RR|`+mfl+v2l-?_w-BL%l+W$AD>n>PezzhiIPfNs6rKuh%;OZ}qVSCC^g6{&{n2_7)W> z5`ZUz?Im{dOy!SXk^hrpN%Qeo{D-L5i8kScH($fn7ev#rV~hz8@?MYg;=h%oiN@0! z`~2&yNjwm|gU)DLmYZ#P;At2lu+BHFF%II5F%7T|N;}*SsEzk%i1HD0%65~jq#`OT zstgK0CsA}yp-5orn5W@R7V`XLctm6G;Hk93biFXl;|1OOt4`(F59MRPpeh zcY|rg_zOw-Y)d+#Nl#Uf~Evk3`VB&o!Mr zTu5I^Bh|qwts#{z)r?JiKel!qK>AXMC9<|w3jT}}PRN&jrh-IanSL?f68Fik?>NES zTi@-}1(=$0FmDb4s->8Y4F^Gqgy!a95^%4G?{kTQtA3~U|9Y7OD`O*XIK!j*6;7M(ndG*;EV9i-^b3i7Qg-a|R{TyT@ ztWV0c1O#-w|Cm(qJX})o2`qWCFzh?T?qk<%GtyhzKO+k0@sWhQNO+%OjpWXGl;3>_ zMleY#p8W2rQ{~^?en^K!3vME-1wm1n`SSB!_e)Wko$9jtti~}|^?ty8esq%Nnu#GP za!{jT|)mbOG=7TMlOJQEPlDy7Ve4sFGh-!!_Lj{cJ+_>IQ*KD}) zwWYPIj`&~)x4z+j<3Fkri<a(R_^b**69DxBp$I$D-R(A!)7wH__Cel{%!n}K3N64l9Q*IuHCK^&GY{Z^s2QaBY z#1>#~$Z0lXq^ycSs~Q$Ep&lkjcs5+FmO@Cj=?- zEbXg?&|QR}qTjRWmDAULL}eYvOVeFs+-L%7*!&QZU*Ci3+S`dx!)~5msTooa`o)`E zRRG_D)NX%iIODmt}X$n$M0u>WZiYXNpH3yEO=fX(~vodi!epT&iWl7fJ zuH}BYbiE9K426k8KBd<4;8s?fJ@7mQslvcOZ1-zAvO9)B(xSwU@V;3R?zkEq2UxP0 zL8>>7W|&&rk5<1lZkNb62#|!2$&MGGH4&epWp=*3v|cVPhGz`}5=3A;K*^mmR0n`Q zPz?G!IIrf%hpuE6*82?oZK((IUsDNvlEUr7;Jub045fg*wd=l+#kKHSr730Z9Hkd` zjgMGKJ0)w^Lyvk;*`tfkEFnVD+Vm>`QTjUG+`oy7Q$}52O`i}Kp@zQrTw=iR@lL5B zv`3H^kX%@cCQMdVj_TPB&Y92&CB2i8F!ObF3TWk{!C07Y*A=w_0XCTzCjk8HADJkx z)+a!-M)Dae?N2+pI080Z zfp4_X87`rr51;-$`FL-q>r*$w?_GGjCdoelTwOFGoN2>y-qdPLGf;V%(o2b=B*VGp zCkCyEC)cKKH#OK2E^JI)rsDnV-jpu`425ha_72l-SQ2M?kH^1D7g3Ej;NH*S4R*+Gdz6I}aFXK{ZsK_l}by!ct_p zwz1~v09o$fU7I?(EKPof?)ROJ`mO8wo7jBY|)Z|JK{ii4IUpi^^ut=Y?Ff6_uZr@`5s!quS zR9{)+9~$7F06Z6kE;qj4P{?R~JZ{-|)Lr5%D9#|or9T^&W$WQ}E2@5<5f;oCBTM6q z&Jbm%V&Z^^{$cQ?bf#M4x{liOjpj-2#r2PzoEQ>McxO(gonFDuc7O|qbBOW67=*w0 zvD?rAX8hu#y-mgv!)3s0nlkxtU(_;1SBl(T`2CDRiE(XK?P;maA73`SUfT99S*fuT z=&a)?(!-gWSaK+~HNtdcyZ$S{i2{{{o)0tUy+OP?;U1kBXO1i)WMx#%w#QN2)coB*f$B*X2=OT;ZQmM$U?ys>5|jVV^bM+t8L19K((iRq({(3UR>D)YDd zDkD`CHLRf+VUV+CvZ>%c-UwWkk8veK&s_GBbXg_>`2C652u7d-bGSIf_0AY?;Q1;z%%ctpVmb#wH$YcmxbP!8{K6YYtR1 zWassIut9Af2_;ol4MUyRiSVSlf#_w!MPK#Wyd=$7*fPYJo6i1H-0?EHCa*1!>WmlBJu%KjT zaKn#IjcuTCh58pVw#J_mtS!%>laorX-Z_kbU?UtY6{1Obun?r%IPf%>DM9^d1ZX(< zIgtt(#mGn@%q&9BzgC6p+n{HeJFt?zPjS^ul6l-CZ%=UXc2EB-!}xQV>BU@`=|7am z!5Xv6@BHCx3IMb0B7d3jCnwDhP3+HB7}LhViZavzs2u2nbj3}DV_C|rJ_%WRtQ&Q) z(pB$f{Se@(%0F({|0fVLbVdo~yCE_7>2;Z_W%pojrKk$kzc)urVUxjj=G$>{+;81{E7`Si|Qg@#gr8=Uj&#@8HN~e|(u-4uuPt&=#6+mABag#uB=u{P>NajsY%bYw}l;j zD8G9>jTyb_YdHrRU!BNI0}e9^6(>UIfwVsB(*R?GJv?$Xmz?Q;;+zSGVbZfRV@2Ms zaWms}tac6oieswR3VFBoiS!^l)05+Re^yGphQLLEj|}Rvdf17{&vKmCb6x+Z1#pRU z<`?Gofka(%c{TiUBUF|_bgBK3ao|C8cDGC=j0d;%e!ydE4d|gNFi<%r8xYkBxKN{& zV`F8#`kR6J&&S0e3o9bO0;pLrHWwJ=DaD)Gr~r&l!ZC!<9)EvVg|M?{zxJODlm5v= zwzxuOOW+vFNU^yVK{!j#yxPwqv})J7^D4| zg@p2ISSv4Mzv&qM{k3KRL z*d)4&J9pJS2aPvm%B#cPFKQh&epK(p(#~z+eCi*j4>~_TSF>?{Pn22EnX@Cotr!7!$n|jq}DrJJC>TGI*9^Gj+^5SM@EN~1GtE1lo13e{j0(qr>nyA6 zu+i4=`k+wqLQeZVCssNvfRbV33Gj$yVnkK_v^wjgIK&W&p&BeI>MU;f&58uZP1 zK;&i5;5d^mux;nGGrfyroxP!|C58Wdo_E3NP1Da2?b}$1bIc=>P_pd+g z8!0f4`?qd{Pi}5@J%u6)3#SmO_Qatny(ylFlPwbR1@R`xW`tuKo9-^IJ_J854SMj9awv>a6n5Rl?rL(3!#bU3Q9(L$><#yqqaJ z)}5KrrMIK2Kl1+ic)jE!M^K_9nlTs$c~o>q_vTP_DNs9yx5*tbmYhkmb^*?Q!rP=7UTMM_R0YH%o|##-d1Pyd6cix{9z9)@u7ByIo0UCQ zQ~3Q(vcBz+U@zAh{sNVAG)7YL%*VB;p8BW`uIR3+LP}2B<;ej!sw_rf?<<&2`oOQj z0VG7Qjtpx;#AIkVhQ!xNd4C5^Vg1ESL7cs66H;L=2q2DxFCzjUiN2yJ1Y)Ps;b!}eT*K?A<^P)G=%8ILk>BVoUbQ>3}HFgG2_)Wuhank!UJ9~Jg;~rMFw%&z_ zXG~n(g1|lHhGb-L3};bak$}qcLPk%8v7?weLQA5l3sX}Uve`xecL;qQh;84f9!ly;+T@_4t zO=V@g@e|hWnl)s_d;k_STV0%7#jzG*%C4?bVUuaQB*4O&oe}UHgp0sC3+e%?b~7C% za3okKAJUU&@ys9#d?CwJ{uz2-amcp66b`F|KN7U!&0ersr2kQIv*-qFIEZbY$%UP& zkH=%az1^4t%=A-)g4D@H_!~%y6D@2NLdH5vjrYx~X^FGBy_R4_B7S+^449-kRu-J7 z=)W4NjmDmxUbmxco5_G!4*@%uOD++-KRfW@9kkn~r@RIjrT5PO+!z|n)`JWKSA}TAwv3+Z+YAYtd7xX^WqMr41_rMPxP&=m`{XD|E`R_|T*-KQy-yK%G z?Y{xQN_tS@U<{1>gzt3y+$z@b`d6DTwB&Z?<)Ib^Gs05+*_ltRpyIncMQ2agc7D zi5@O-u)k4ZG&x8*p8sP$a=C?0d6mfaP^ks^mq*JB2DH!rCc)745nR!{2@;@jSop?_ zDV8$BZ~$obn&((|`YoaZ{0{#dd_BK>Wk>ISefjpv{xXbGdu&R_Hj4e?uen!10Zo8p2-+wU^x24TN`|$ac-PtVAa5a+WN} zAdcqb!m8}POX_Gv`~gthhaG7|?$gi;@k_{0AVnCy^ea3}ta5CXt<8RO#$Qw0nOXd( zCH%e?848k&$oB-JrpFoH{9E_a`bNKnSA+&?F{fNW?&?_09#u0njL1%x8W86}te=L` z3}Pj-&{2nVjt>&8Q{@sQthn0rJt*0Qau8bqq@VY5aim@qUX7S)2`gb${cs5B%=$tC zVT91SkqX2wxOW~0U^bk?^I1GCv zs8gb`KF_Gd)@)5}1bl2SD4{n=J7KUVeVNt!0V;rIlNLqA*X&Myv?E3S&gngGj1Wmvh_6F*(CJiRSIheO|Z8oWDsY43mU(OOT7DnEs z5a@rX_ZAdK>(^9UkDI`gQ(suE_v^UBI{yQBc1V6YPd(U7&yxsYdU{q#{Dn?acq69N zFL_V2$;4+QvrZT>-)O@Y=TxoH*e@O1rWp!}IaBd*_fL+FLZMoWuA%#t|F- z0<9x$$E368F78ii1Y0ZZR4FVVUEq0xr92dqUrVbeJJa^NC`?w5b3&;HNxJ8_bXF;o zG3NE*WSvsq@s#x1FpQmE8dCc~x0b80) zW~^lRQMqnvbNzL+(#ohlg&h#1yktM(fawLMDx-8xq^@AP?;szz6YPlzjiYX2VF{Q- z%TtvEnwFMn%0mg%ey-9I`)2hrw8AWL(2$atT8Go&&kHVS_A|+;;Gr17t~7@E%trln zEZ4+sDiu6dKjwlf#G5)wvk7S|_|JU{a)#f-drvjh!(op=%(;zT`M$&z1-H7rGfY-E zG$w{IPnIDfjhX( z%{q`gB?!l`#6FtSK54)nE*Axgg#Lle+{(v_vA@T?^SfTmXQp^vI6(#efk6&d?KNj6 zDZrzNwJkW#RGTUt9p7S+F0KCK!^ZS9>-}}oj7L9sQ(i@DK>S+66l4}Xej5RD<#Z(R z-$Z>JQfH9+WhU7vv2VlITWq7P?acRjHBF&`{QYmKY+?`^PNlqPsp$e3tI#=|pW+z< zF@@uXBz$r^V7M=SzC?m)TXVeO!@Q*5#d!e2f5{(c$?6JxCC)aXUs`+#wW70I5MgHA z&)dFImR5MTe7iIY`1kykAwpg|=KhYW6yw83NlY&$BMWNAcfVzy!UY1*`zb3q z@HH^b`H`>oC98XJkj;jQF}NwAhQ~w**)OEW-%ZQu*B>nvmFJ7j@lR7jN!W)4Wsi9e zdcJQSv{6ZW0!+z-B*IA&Qc}{4mNkGfs2s*LqLn9ybcGGolSa4>R8() z()q{PBs)hkwf90ZXxGOPGS?$CZ2@47)t6f}~gR*NZXALp5a4vX%S_T~xGGbhN5U$!uF2?Hi>?!Zi6A6t=d80rxeVIoKE< zK>o5yF2r&W1D{KH%NVv9`DgKK`f5=HcCx3F1bdO&>ynQ{ zXzM#M)tV%f(3);VO|5`wIn_`JG+|_C81#A5?N!hgIobuW0>E9D+Ca4KP!f9!%+qm&+1l6<3FOXkY?ery_BA?JBO_q^#7K&|jcEE)|!oVEp~6Av<8Ru{&}V9`L7N0C|;B~C6RaE1SU$uaQx z9dhnV0P_Zt89;|xBayG?A1psCW6`S5CPl59NQc0)B_#bt` zhBG=PE@}RI&)Y~NOyPaEF*W`FXnw~y^Q2!$hyQwq4a|yg-0ij7_&mEdavx(5QewiN zPmSIV7PVNS5MI)(;@+;k-s%mV+VxL6295cT5llqAKzTplp>MD+16YKyzW{{0oAA_m z`Sa!Ax3EHq+C}e1M!EQyaaEHi0n9 zhQK4yWg05$sjnb8JJXK<4WzUp0BHZ5THbxLJ94*;RxU+;pYPYRB5fg&cSs#Zb`Q3f z^dcxR7!lc=={%s|=OGN~c%grnq#%&Y7liGchgZ4{f`eQ8uqDVu$KK5>BfVSy^h*<6cxuW7E zqU}&KO0|z0mw9}+!-|L?>yz$|l%y^%o@ij5zGYi<{?kS#V+p?j5GCxM<0aT5He-+I zi_9c3rk~pvc54hY7mBw zZlHS^V&yaSFF_gO4;r{~vGS5&3if|FUz$uCg;FZzZH7l*{Eo1fj~}=|!SS@P{~%q~ zyvG@PZ_`_TzvMh~4ukm0#x@rPlzY&Th(fYq>1V6x=yap-N`^Zh>)0RV!4W@J*f+18m%I=go()ln<$1WC%M91)P%V$0>|zhCn@!< z6yliJ9WeqSl(?%YN*inytF3;LN^RXkt+`j z8a?ce7f+;B&_F;)Fd?hBF_Mw_Tb`oar&o%iPcg0K0AyIkRw1R;a>pPErA=y_R93bW zQ=@N+n|TVW>k@|V6Z$_-yC{k84?T2rf$4P7V~7Q2GUNmW>uRCz+@b>U6whf8n5dgE z^W+*U0-mT4>#cmBP%24;q=e3QxtwOXhsJnn&Dz9)UG2<{^EJ(Q5}k^inH{3qgm#p#RXMb)Lt~ zaY?RxLdn8@t&-0+o?)^skaqjc2D2E(EA-Ha84$e8iENMrtRerb|9sxReh2ku6E{T7 z%Q3||FLKhr4#ukiUcM*91ml!g3>8(xt9z9RE+$8qC9*GHU7!{}919^x7H1`F?aZm* zSdu!33g6^Cag1~gQf#|gg`}k@uB@1l(-J^}hJPjgi}Ii?zm!k;^zX18ud^p(9m( z*jc&AU!w7F{pv{RD2Edkf8z^_9%jSKkHlX<;;2R}HpLQ+-8nldk&t%@ndBRU)^ucR zOyNA$b|_4DbvZzWnZYG5Pq|$)^69j4$*tK~=IewV;rG~u>I8$_icq_I+ zFAdhHdvUVoA@+mtb`&s7S26r?^8x=jDkE+GTtQK8=8WtL3w@40s1D93aaNlc@I@S? zjF0P)tj~IhybI9GH}`{;q-<>Xm>wC5hbM)PiU|BmO$RXXK=S(~5sqR)TME8P@oc~G z&@ql^V?ug@U7Jj}Eb>f~+2_kJzWt@4NQUW8JelO(SF^~+_JxKuB$-sQaO_v4$X8^r z$jE9~x_!^Y>XxkVloXA45j6qcR8q+gy)DZkeeWjee_nO}d3|3~B536wI@@{ z-UEw~Fy9hcNHrcvmET?H)2ed1xRS@qqq6V^E^n_Nu+8dT?phu19$kp zV0kNTOJa+ml1Ih7^L5riO+{pgQ+}b$9)wy`T)e+v;fsF=vO)bJF|Vu^zc9(x6!#j5 zN>O=)z|8f#Ez27Upg^s*i+bh~vGjvWyre0%Vu#SdJmp-ole5ya8}_pB-i!fT5822_Y-%hBg?3?)iTjyfEf<%I*O5PG>j7~!<6 zXTnQyqfa*yzsrr~l2%Zj7^4RJcHP}5har^E;!UT@WMaXp5vDpEU48dHwW2hKqeNtP z7N%y#3bYpFAbSoGh0xcvU9Ta3pX2V9MD+b zyXTX!3s1?3T^F0PJ0IqCZ_3(x(imW+i$VdQL?M9>&~A};))Z~JHo!7a zQ&YwB0lrCfsl5&MtV7)B(OKis(YFOj>n%3mw?dz(9)hz7;Kovx3%BkfauYNX16alfJgx zw=%k}oL3YJ+|hLf;ctbVwh;rWzNm?77=HzJNKSh?2laEg$T}ABR1*>oMeduf8E}in zvJKJ^@?k>J1wE*`at+oDL9y{^3;3R4Xr5EYbR)|`o7HFVChNdsn!DbBkwZbpSU1>V z_7VCF7vh9Yzx^pP57>7_jr@#wJ7ms7Y>NW02KzCYuht>X2DpsAua;@_ldmdLda|=$ zXP&Xt&`;@W_1TP=v~(va2WU5Ee}Kq?>)y$zgDC&o#DmP3JDljckDD>s=VuN)gUS2m zh3X5q2tqiCQZb-dqvkUzQM4`6VA)L%2RFk~k{7FKiiOyBUoe;QSBhd<;Oy18gzzI6CT(EmVC84ooIK)d~|$wISHv47ZFC0Q;@NfTc%p z$e%I7$HEQHj|FfzMa}mR@(yewepF`C&Chx0%~unfYUStPB;!(w>Pny%2OMQ8Q6k#X z?Q0{jdTYHnGe%m=x|la(&Y7AuH>=c39Kr^Id*%$dLmzq4ge%QxhJihAXMvL~YjpX#qwM!cAf%iI@eZ zT8OoguUDDZla~pv7vPn|>9{ohB;P#j=hoJhpi~b8rb0EM6~&QD^g2p-Co&avcpA;u z=!5WJ3xTbPb)GAKb$|+wa7M&C)~c8L1KjF}^j*Nyi)>uTLlB1)S|T+J6VkGXAP#V&gad)4&{A+XEMI=O|2~&UT%UnT@skThn&GS+1lr!1>(9}U!^p_)O=>S&ukaf$P zh%;Fk;p8?QZF`MR=X<_TAz{UNg|d0CEgvmv?6-&3H_h z(~^iP41+p%9mHL;mJZHZL+-2SwxMu{L_J(1jf{kC!ff1(yp>oK@ug$-e{5by7o-5d znMaZQa!iQ+&#c-hnyr=9I|+pCzR6+>eVX&#l|gHqbSx?h$!7ONpWlX5Ky~2D<*#q1 zraM8%Q=i`cdWnILl2um!2@KqB{GFiY)%f{$YrOz!Z(OaGx{gJE4Ao%P?F zcK7pU3oEM)?7K@;RPQ*YxsA*C3D#te8tO~9g9B0I60fd*d;Q*h&!!I&&Zi`VhK^n2 zSx^(~YAY?@53V0z%FmjbyqF4nDcz}l4~MSrJ88O8XSO@3Iqwek&AwpDgcCzWOKj&% zgBjfbM+AlTKrb+@LJ5~dge9efl1lk9I@N#6=q1r_A{Iw3h_IrOXpmLgV3?P+)k-4H z0gL~p%@M$bEr~$JZ7Oi%PMx$18d6Gyg}ar##q$1y7JWM4(a+aTqrJ>1eVZu`;ke#L z#4>5aQcCN4Yhd+zId5f18U=R6#l=OAMmS*ve$;YaloW@PdcQnUxfp-{>muEn)>!oX zzq7f>6uiW%cr$W}WYUwl>6I!zJRhBkF3wvv!+-nAes@;oqD;lrMUQRDKc;`4xc5Zq<&94`34RPI&9*N-6H_za?hlhu*|34Hkma4!nURm8# zookpB(D1C#PQ`bjB=0Mt;{Z>K3YX$r)5SEY2kI?ylv{%NFgA;@J_nuQVSPmmmSH(B z3ivIfycPkVUFjE5D6dwsm5QCdmfVC@m;dp}})!W-9ZDE!&l zQJ=&jwnNM8Ke+ynh2}eONN-jZ;5Y>s(`-NA81}2Ia}t`&vm7wM#TPO$N41=bm}QnG zR`Bz|pg>7$X^d6O`l1I0{&Hp#gyW6mo)1_{uQ56M3pJ>F>&mH8@~tp=N3O)piNHw? zHZO@Bu{B{n+4!BqHz)q_hV(Cp^pzJX7gAf7{kL0G#nmcZ5`9c0C7X^_muV9n=Rhw4 zTr;O0s(3(>w_$<(5_w-F$(;OJ(t{W!;;hIO`DGX$EN+QC`z4GIAm8dTG?NBV*0@!PnZcQNHUjp@S7$s=by?QFW z5~{#hlWgm%K=86p)%8Mjh-8bXD_3PXS{FE8kww?fo83B=H*roOwAhk@XN}5X<4Pqv ztMekNFxWgJ(iPwLZ_{%vf?YaE);?f`sg_7}*6@W8IC&NowHWjzs8eP%TgTRCF#DRia+u#<_wSLDYG_x8_eaV^6FB2>L)3ty6JL z_{!a3$(o%@CcEqQEu)kvOtH=#p+t;Qs*ZPL`grXw1%vxTFrhtc3MK|K=HK{j%O`Gpv_J~!@VfLy+u8A z8(Qbsz_sS-5e^6fR3m3%Zr1ICK*RRluG>& zxwK)le638v{WJ)`2{4*WpTrb;OWp))JDs|>)R9ahsUv*x&)TU63qc<`fY0~#FKq$v^X^9IImV!rH&hWSZ6AKJI}CVO1o&m0hPwGvU8{jkhMDmO#fgV_iJY}LY-7sCzeD**c1<~Oenszl?aMac`ruF zYLK}tXPS=GY@z?t+_dil`G-N}AE1>Jd)5pkthtm~r!Ni8nU+3=r7??;f3d261=zb+ zSOia42N4d!{od#M?A915O;%XB2yuV;qX4G`m)VCneBPSJhn$Z~C?hDK@vn0~OjSTx@jYjZT_K zjqsINwW8|r1$I_lPvx5UI+lVZtD*F2ff2H*Bo?PBvoHB!b8i}oPKZTKEa2=`j#Pyxehfkd3 zam@+Fp!)=sZ7d3nMI22yb@>Q$U^qn~FO0QoK*af_zwHa=PV9T887hq_5jc8jP6}4y zQ-&28X7P8^IM|$ZJwd{nozY1l?!xDi z$Hx)7#+B0q_B8>>V5GUMbgWwoJQJ%MZ0$X)ZQBdu!-s!2zBRgz{A6vg$Y69Qe>}O_ z)oGH3lxxEQu6%^<`P z+r_Q|VX%9PSbvcCV0m8U*qqLY$2auL&Y`GQo!GFRotc~0lIriVS(dy59avfP5S~9n zf&~KsNTZQhwP0>@;I(^_tO$%ijJ*=vKD}+==A@LoJEZ7A%i%W}7|2#8s|gS~{qwIP zKuC*b8+?8c{EOP8In|U80wIT5+La3h9%*H`bP6ZQSu(T3xVmmjJej91x`Mk_;g~Fx z;~8|+A#}+Wz(5U4%P>g{3>#FtKb}$b$h53(*v&~LeOjgS_D{ccsz03g_G_^T^d!6d z{E@k>771)zP2Vr;`N7}FupLLQFkumV_1BkMQ=W{Kbh%7F=Xix6hV#(89AvGTIy5@W z6KQj`%4oueg^e|p?o2Lgc-s9}L&Fopq`J@hEJNj=r8YfcnaZ{ks?-)q93TH+)5+i% z?&_$kT0-Iwm^9(0Xe>h6X2Es}S}DDP>YM`-;{Ru=2!8~UR7Zp3Ac?ASD+(jlLKAZO6qUInO=H!q*jk-vH?@5N}1q5>BCt&X2l^VprQa06n_Uq*S#MuPDdRnx5L}`2ef@jZdv`|K9Zfi(X?0u z^J!pw9M-VB@r~pm{8GGQ#gMVyU9TcvJVRUqoeKV*_`289Ub~+wVsCM6U0{O=$I_?4 zKV3~r6&1-ZHUm>L=B&$L z%=0UZ%s0^O1kCe7t(a(|!%#fZFjm2;X()=bGh1NVQ3NrrL$YD)Z!e!PoM>+%wSbD( zT?0)NcU>1|m%~4}qEK{J@^B^9gfpOZFH?sS0t&+?T(_f!(hlQ(Sc?WKn)TJAqPd)r z6&zs0Mpu2ks^-G$-Oe4QV!gNg)&oH!v#W%U`j)pGN+1xOqR*vR;lSJyA$O6#oDg}L zR;&LD(8a_&Vn90%FE4~ex!w3@B)aPtl#T9z|6VSXxo?4&KjWHx4KgEM(&Hp2+akyA zBm(uC+18_kE<~BZkW$4|_MfFfBWPH|+@SHxfg=%(t;wwyW~t!uGeVpejGLT}iz7}+ zjQIwv>l3VTS$O$v)K>2Vi#|v+b_U81l;@zXdb|Pjy}v#+rUKadztN}O4B1&I&h9^@ z17qyGl~X`nUuN37^X&D*t}S63ItuP+w*maL5pvle=b6Z=or*VbaDPNYRupIp$$O+C zV-%r-h~PZfmSa3{X4Bd<+Di0**RX<0o;Z8ml6LD--ew~!2P!Q>PG3<*;yAY%sFa|% zbw^ZQf*-rNW~1Yxy7;M19f<}C0hLk(-7jZR&?krD67tB=t^mOwsR;)G%&mzxC4lw^ z92r0zrL}FHaBy#hUkk*NoHF~p4hlz%doc_W)RQEAxi30&M~T>-9UJ_1Gqmm`1Lo zmgtW4AwRV?C(@;_nQ2c+B-z5>S5-@vU|7tc>;tDRBeF5^vzWp{SgfHU($ssXE*?pU zmCI8xjo4dnPi&c3;};qMdQAMN16}G9!m__VcPin1-;0rF{bIo{$!b~d$w&w8PWbvp zks2W~Pz)7eDD?JKAY`)|E`#aP+VRwQl5e-8K;4ei=N1Z%)FHtbbMnWd!QE7{a)2r2 z$yHzr?(ty^rbRYP1_aw?j`;>%T|K|!W2Dt(F&yADr@Tn$j3xYTkk4A9E85hyBBsS| zBibl-X&ZaPfK+t&^z`)SPkC}Ey@%@Ud)Q$K-46BI=R|9RlggnpgdXzohI)O~d45$& zJQ?evfV<A;8t&=Ue`A@OaW2$*;T72Uj-^f}{ zr7@8HNb}_E#SbKhmZ|BL_Ait0Bf23x<8(;)CnH$!Z@=Ma#u?F?4Z8&v70BZghS^aI z<%$*s2ubB+E|vJ~MPpc%2T$JsUpr2d{Keb5cZmu4-9W)5XAd||nKl}Eh!ANsM`|Rk zWZ$#yJF)~I3IHJvcf7g`hT^ZSuFP$Ez|A|DiRO=*xcl?x&mRa8o9W-aG1e7p3Ete) z5IR*sjSpQ*xW(bP>|!EP#_p#>Tuuw9y2)7Qv#pqNGp!>mw=Xg363TKv1Do|!zoa2I z*KI)@NyY?59{$F8Z@7YjHv8-CL%X6Z1lx}+P@*L)^A%>>C75FKU2J*0Rr`lKf$Lp?>XbEgjjM%`Tl5F%LAP}=QnQt%#6=g&=nM@k z>iLY-b+db|LaiARfm3(8y{Fa0XD<(w+~|Exzs2cdVyT*NelCh{k^jbMN`(O1W&VI4 z1?+Ftbed+wqw_5)0*s?-)maSadt3t1@?k5k7;Gj^m^GzW!En{U-r17(bAxeO(kI zOBjg{No^h@cMF2hu5`iQM+Yj&#+Jdj&UtLY@!(CB2odzf0-IfZp^5mH&hdjs0+ats0;`4EB^?^E{MOQM$2^dn zyMqG;v%~Hz`5wG(t1ej%&V(FM&QkEF-z}YI6GPt@z7~7%i$D~4GIv&iTypG?{WLx1 zJHC1eV=Spz*LCxtMpm@7JGJl4+~eVpBKs_oRyW}#7aDF^%!lH^iu7}YO@)S8GqjfrE;N&ApaDRPwid$ zgP?^n5~K*Tv!46J`{VszLSJ?Tn44U3%SzON@H2Na4uhu<6^7o6TULLx+v!XvLD&8Y zE}=6Z$;ybxahc>(+I*&(|2gFtM{6jBp$F5K44~dQph8rHr>HEQS+}QdJ3~C6_%wf) zqF#Q{H0tuxYBQZsN!r_!Ms@zXZnfyNpAm+&fjR?zyD_I(g;T}ntoQ3Js`GO?-Q+$R zsh~vb&n31p*1{S1K5h3dANSr^sSV{K^{C1^!9{|i)4UE{>_+;k#Qp;cxbh0f8Co$= zwPT~hS)4vJtw?J3BQOpl>q;K*`5J!ne<$WaVuMD8PXje$7d(626@P`*6UA zkI~D^G0v}=h`97^B$pJzLSa@+07dK-$#S*>rmC_&g-vxAsLkDNlhXc{f)&+9+`?-s zU7)ypj-TxcT#2Io@M%Fj6v*jM;T=8tikDAuT_OyRAk}bUt{G7xrj@U3 zTK7aMOXg9op1Pibas zr?Q<4!*XcXOvn?n50Dji#k)#sbl5UOKM{Rm0^P7#hrl`HeQ=StQg_fv5AQ`v)GYDn|oq$nNg9?t{ z=oF^ia`AQXvdI*_9JbETU*{%^JT;%1>FWGv%GG-dxii87C*NMQTd{}a93$r(D+5jx zLjI61ITTR_gW@b~mCTh4Iyg?~SB&_uA_67&Y935O>7C~-8VEF2^%l>empd5D9Kr{r z_9H^Tzhx}w^}-`iC2q|t^0M>c2~>&iWbZE4@i-1l)9lmo+`jrL;}fa}yD{XHF&+GL zpSB8;(@v*xqZ=E*XRPn~7?nsOC#%LasXO;F)&kYn+CwJlF8;K^BZF0xA(YGC&}oRD zrNeRcqoOmRrg?dFM2@s0#4cwHN{lsla%qPcoE0fJG)qSTLC80zf(|mWN*{s5Ap`lc zWHhW4IS7e0sL&EZO?U4VR94wL0%b#+y(-skm(O6ihqGt;*A7#df!(mvVYiHU*AVLm!83q^RU?&xe=wBfB_O0iqm~{YhJ6)finB$Q0$E4VGsgtN(sMrK~BD5 zJUycdDrj}^-A_+ZnMNVluREksiS=R(i2}RCU0q7o$-9aLg}n>Arln`zUi0%8AM{W%A6dxxRjxO<_~ zNZ5Ec7!gDgiHFpaR|gu$Ua>-`DFqyzojHEzmjx#aqyhd5*S~idp3FA*M>by-?g(+k zAx${m``xHmZt#+bTj(DJ!Az{t=OKeEkBj1u$1po&uKr3M*F<$&0Znrc{sLqzP{TF1_G(v?~m@H%;Tx-CERN7I6ZjP z_{z_Oj*Km&-#4eMf=^u!$lrdxnlr5_#aA@nA0>aIHoZze!Vqsrl2L_$!Zc287?Lugg%Pr ztSG364D%=uK5%vj4%aJ>D28x_ zoX`=_!{x!@o%Um%huJ~PL`a$ZznHPOJRcK%vV4>L3mhxWj;FoTz!KL5XP(1kM?)ijk0GxHiI*6Iqd~f&B;7|v z@!b5;=1r{`ppRGHXNU9Rc?DV{I@|TyG>`$ovq23VGc5?9;WJEk$WXVsD8S5>D#OKo%k&4~--8a_pKA$e=YXej@ zxbjQ~Rz_^o>aD)6paS|0TV>+0kOTGoGBOr!%16IuER!Wf86Fng%ZNTtd)JDl6Pm6q zZ=zMbKH3y*OZ0b~7zoo$q%I21qA~cacX1+-#h+i1w2zPm`G~A(G#GQVmyJ6p81SSC zXZz@aIS{-<%d*yQ!sJaND62Nd)DzVw;=!qOXpmoHSV%_AF|*++$uVI2iG6)gGqs1g@SYWKd=p@CiU*ep*sYqeI?L+WU5gh04$%SN;OZr&%*0 zZ+|DFZ}xv^wXzvpW=NXsgnxe1USmvKpksG6lf`~B3SiPLHKke&9M87_;qck@WrYOlTX)wgzz| z7*Ie#$yWS7EIg%V$0!Nn z0>cibf<{=$(X3#mBi)iRX?-~SBh7T&0Rm3f6O#`AbPv#`WNWH4No-C*;djSo$u@(# z;RbfBn`mZPDGP7`gMCZ%ECa9bP8Hrt5s48lRQt=2+qkt(=l`<+4H0P*&qwOt-go-C zfA%mpj=lH*D)IY~t6&rTl16*(#T*Tk?6YFm%Pkszy?PYg@(xcRAi0{4%c7rMG!MVL zM1OI#B#}4YrQis++gz7^EvNF#fo_%gPI z($f_*G*b_7$2$p-7dR(4f7)9e|7XIi6B)a&-;eN-JnT2pc!Pf0H+rJNsSgu`TmhdV zh$Fn|GO3h+tut4mx4(B)8Eg|0ZzmMqgG|{ddioN5XE1Z+nc zy2;NogoaQ!;DEipe2LIh*|xkVCGAKdQ&Q#)_r&?sb{Is*RFX6gf5EbT?tg3l>qprzm#;v0L*AxcTRUD zDvT8ftGRLgoYAqFpv$f({Q)+T76tHPcv zJ7g>T&da|0hV861FF%ur1bxyGYFv}r-n|l4R>}PuN`FXNtn{b-yqs{|M*20SNPAD1f&KT;Cna0$ofVbc3zBuLjo-dFjEY%UD-mx>6K~h)Sc_wlvubZ z1>(q(`fS$~cB^()W^>n^n%)7A%Sl)5yNp06JzyFt$ick(Ez5CbWp(n>kShJ4maeWi ztKgOY)B+%lolPL6qp{r@(qK39qmH#+zPNDbinOz%#AihmVbn!JCYvE4-{nZ-F~Eql z{o^&+V*0YzjOtaORyKFF%S^I9R9Wj%VxOJagj&RK3Bk5Pt&2It;*d4%QC(x_?^F&d1y>XK&+V$Fj^jTc56Tksmk78+VGPrCu?LbOD8c#SdM<%pW79L7#fX+l}Vzwb)aLq}2ryu`qY#*C+=(^dre0xcnj&=m#T3tHdfVKRNVHWo?5^^AgR zb!5b*7}!o=hAIJR`;PA$;pxvyi$34UMd}120ejGlxnc>sG=LufBwN~~l0z4O*pVO2 zj9zM27qA6jEJ#{r5XdtcPu=aT0#{($iXAYQW3(Ypl?hReR9jmca%g1!(WhKSn$fuX zsD}x2{s-3Yy<+4Lmmj)=I)vEzWC;S!v5$?^{+^DmyQh42Y!Iy5x27a&>c1cpyiN?I zKWHpb`@-RuRXJuSUepU9a1}MihN#jaOy#`jrl6n9jmoORQLV}2kOiBbkh$#t30SqKoFIf^iMl2xZ2;RvVm`FSPh!p@t z#D+2e*{;ACvW!SxrCA%6VKWOsP$ICvI=w25&oV5F_Pk71CW~oWn{LmZN*?S4Y16J= z9v*Gy>4Ii=xZmtJc!{Qwjw79(G;1fv8LO(owW8t^sA*$^9+gC(RKH3`n-|2p=!YI> z#XC-6Zap+cE=JI>hV5P;3$Y`-6k>fM=B)YnZ!m}Pcm97G;b)b<;zB|!gaJCAz7A6s z{+uF@rya<+aRj1>B-3fijCkP5vzM>$%k>VaX1e&*x$Qi9(k=W)Sx0K2W94~%X&qxn zXo;8$jV`NFs=T~Bf^ChQ!I$;VdUPp=i|(JCk|U|XYg1ZUlWRt z9}(?^lT*Q|_^=c0B4rW_&GWN;Gkm4*e-Dpd47bfR3fbVMVGOlgE!X~JP-dN|mhf|j zmx z>DR5K@77wl+VbMPP5)+OnOiZzkme*iNT@jLe`3&<2BfnVXaq=n^4PpoP=G*cZfPO8 zbrJa%)}OmYXzBIiM#}52ewjz>0(dy#TbVjL1qGP?`kL{L9rc@1{TzAOh(iE?Q{+iJ zezc?BlHDt{r5QO3EQ3#nI6mLk8R?eP)(6+7 zl*|FzF%A6y_%gY4WqiAHaMVg|s>(0BLpSK111y!zrp zD_6HNvf-5o$+=Vjf`8&D`=F|7(uf5{Y6HBgvG?1n5GUwcd4i>>)7wAG z+NpHES+Qdwo-jG>Gl3o9N4wcxEc}nx9R{^utv3L1@>XFz;Cfa;z|w*cQ9{zZmjw*@ zer^AXC5iE*WwiB?XI7+g2TE;iC;UcjP3@RJ{jnJ*@n4?0dww%c6Uwpx`RpB_v%5!M zDiE)X6t9A>P1n*#TI;VWETbjC6m@R1D^aZ(*C_VDLDSs)3ezax8I>zPlaXc%3vR+` z&$zAc?Ck96Q3q@y4M5WqN+gh*tq$1wmL`c5N^%~COThR7j?Y62c(1nloopX5z^E}G z_WoE`FH$+jTsB3Uws-lCGb_@Xj0^)UT!J*d@mdUNvf&eF@AFu0rxj&3Md7=5L58V& z?J*ClL{noBx)}WNSOR*_1{R;@q#Q#IT?|w-qvWR^bs#-p&g7~whtiAXfMlhTeF&0n zPpapR;%TA_7;B>7)DAN2Vwm$LgTD!Brh6Bo9DP8{qSa576JbR17*FN(9TAe@W03c} z*-?M@kw?|?-=%5upI|lkgoi_XEh}aP&@@%v>i9H=+8wbw6vRa9t&1CxpP_|}Y`U$1 zq`RpY&lIQzWZYOXh}Nme7k<_TUbK2-q~nUufc)vB<2_On(~OhDG>wiHF}UszsX80+~|U|65J$#rU1*3#nHT=u&o93%@PDJ6+i zVz6Y#Nl8b-z;#)sE+REK6+3D14z;#_>DH4_wod(SOCnXrs1%B?mrjyJizH=X|C_wT z=lE96KfqoBohPS#eW%~1*i^ff^Xvo0xil>|Uj793W-LmgC<0`yVQjdn>cQC?8H@#ddjRXX)*RJICDaFD?Y}{%ou2;+41~jsTvFlHr=8IEzCcoO$6DW( z`{&=3E$c;rMClgAEs8OZ_0w*pLNMGq9N5%j;X$#n#H>nytm9<75e9GKm+|DKq>YUQ zW?2=$X8S79cF?{$M-XF(9QwnfGorFRMvAWX!W5On7@rljO4m^dgq+%rt~tw;4a>jV zC}X~#*->8`5*2XHK@(9} z(U(wK&~C9*e>V8cQC4z`Cno*flFj~J(pQ?Wn}85r1bKf+Ty^jlajcke)IE-!m+xsC zzt;eSBNiPoX09#fsLg>_%z+y4tp`!Tk}&VBN*%h0rXZv?HJ^k04OCj$ z;RsA(w*n>wKi%#X5#wK8kE^Z zuasm?9O?Ui`E^qg+uLTX?;wwFCfJ$q!Jzwx7FyO0Fe9fyQ>6iG;!xi_rOfD>T5su{ zZ%(`l+OP*~%$gnrx?)b^YX!KBlZv77jXwaFcAmIj3SNI(<%5C=i8t*yXi0rOih-hx7ugh&KTu=KD5Yc^W~@d zS`BX25g+Fk$H}vu9^Z#!<&+VuDaNb$xPH$jTz5dCL5`VqDhbdpL*E^ft|`Ui$*HZR zi>+we23p>#WMOX67J&LEjHdW7xk>Cn=iQ%LH}x6 zHv?hVYV(|?Pwm$KkhJtOl|(Lot7$11!n}8xH(Ys2i&&1Aqa@OltN=Iz5L~Ik%`jbu zdFvCN->PYo8+I3+R{K(tzw5p;H*hicRU)!3EN+j%u%FsL;V#pK&&Wr zLDw*|v(t%;h=wIzBt^gx$Wk>L`0rWIT{5CpifQ=4k9yoDX9e{bwxy6p(6|#iq7MI` zDb<|6pJNEsf<=F~=xM5NNy#U{V`RR<_(<9@x(2o2S2~sydK$xI|5fMY3atO0{bFe= zil@RvK*v=tsVcxFtdwd4cN$LW1aNpZq`3q`1P7o!M()Xxge#cs_&4Qd`KY7{N!+j=suhJMrL_K-;;d5I z)F|MBQxzB*#dx1A^7>Qd9kG2@<09<)l%-%j0r6HDpwXTI+?UMe3l}g@^yc>}(CuGV zRrT+m9&3hLY|E#b5KUU+!Zq2?>CHe`i@tStxQJ(02HII1sLdgvW^unBM{~JAV-Jha z=J9Icw`viUM(TRe!h+pJ(LM70i#66C&TNAbr0~<>N{W-6PN|QU$K^f^nYo7y!VL&G zOO^9NaMQvYtU;gD6gtJHJu~fd%WnRPaQS_l8y#JqkFy0C_*_0|TV}f>fSHy_3vV@7 zX0ZU8pr9$q;hWb{N%dFpj^pb97A;_4^qM2y- z@&PYeA)&M3|NlZS+GcJ|l_CjmV4fDQ-Pr$QsbBDb)5iP4z z)hk=@Zgl_!vIz24*p)DC5-)Gs^%$3Q-?o;%3J1-wgi800GVf`~s-3PCaEqBC}B1)OP#eUQK z(6bD{(2oKRj6iR3d*y@Y`86ffQed@78y5o60aJK4C7D_Ra1mcy#wULaThj~CbApu7 zwf;n`P*ybBi!qIlo9mm11XjIo`S>!TnFq~tLg-kr+WV!G2TV?tBAGa?3X1-~sJcZ8 z$G@srb5{p-g_21=ent5~Af1kEkcnaRK}KwXhMgA0y)2xV^@K2^EgmKc6E!404B^SZ zyZH6{G_Kryf;$B0YF(U+MM;=zw%~A`FQY-ubvJBIohu4JGE%A+o5vGxvs2twDL1Qa zz6DC}rg?EX`RL^^d+O(6jFr3DLwi+}CV}Rw>`hR?SY6O_Yxid8?Zs4XP8CWM4g-S` zhsj^TxZCY8kf1uu`$nzsHiQ=04)FNDDkTE%0o2jl!QI>;1yaE!c9qeWgf;K|kWYn` z5wS_I~Jc1(KT*ecLobu-I_*awD$`AI*A95%1X0oyc1awHH z=s`0a0P-`n39}POV@!r50A;7#*Oig}T0p1ZtxL~JpO9ob`ZHw5UR%_qUQle(@h)pZ zt#&mp!rRNfqbhR{^5HA8A6mG*m$;JuIW5U}LbsgvP3vq)e-isRLQaI-GV&W7o|!IJ zV3DL!GRPo(`01}#_ZqVx5$8DXe(A3`TVKuDG4c# zIvLySR#W%BmJpjNCb9wim8~yG{02pc^Q~#HF_g+siM%!+L5-2Irc|6H#D!T36yigz zAO-tT(v-A?#$)@W@Nq@qtSol?Yvz}h4(AiB^geV1ghWBlkMjDkKCjs3oAJdlBDrkt zCY0S6CS*SXX^gsCcwog~LVo|-+k{Y1;w{hHAcv!P_OWU4r!__VCLDBx(vXR32kLbl z8Atz5H-o<2_Kj_CZX7?}ubd!#5)|`2BS4LK)~ejvX12=wJZ-en;=Im{4d$E^#;!%Q ztq6fOg*VYiM{l7;GJRD#f9tn;n|t=O2J1{q<0~hgX7xB3z0ycb3cl_4looi`@6K01 z^54B56v9=RTSVi*FUig)(X{XoC7q6!)TW!Jha%$56}<>y)_Z2Ov^1F3=)k7-fZki> zq1|mMX6LHUml?JOBTLa(8H&UGB<5KOzLwBqfP-q6n!u&N;g9^T7}~d6uOD?|u)4M( zeD`PW&>Lm-=n94`vqbuR0!vr2o116qZ|8b_2TPq2gaKb4|+W&{kPefvJvFkQg#?s04QZ1^hOP4cN<`~XC~hW3b3ON zp^uFOJ-hnhY{1@2qP9KwiLBaDo0UtFzKyZnb>JhJD`!Ta8$hbBJsMt*>k`CPe~drRI)8iZ!;hp4$VMUeS+&r zqxVsQOLcPBNViq*W=32kPM%M33W+iZ)O`?dcnik6eBEAUJH zn*P6_BccwJIEZBxXmM%f29el*zz6}{bkXi6s;)Yuvc?svfua5jZ(_K>g z;B9NFM<~E%Wl0+7vs}e0(he2JsOC&boKsR32MAHDHZO|Xfu`0i!n0u1I9Z1uU`754 z;g8TxG4u<~_ap7KO5(ENw->j$Ie@jO686_%zR!PqQdS375w9{pC>fzfQ&1M>4V^6X z?fpzM%pVF$jpy|;mqGX#VH?7xH!cydJ2J%?*fw8ew1oIYA{LP;veQsk-hjSIr6lLYQ3^EM>-kkTiB547d z3(tfW+(j78u$9dlf5O_^`VPNuD|Qal;T4CtCGEN8k}pM>5}z&jwYhhUNpdMv7%U>+ zy*Hhom{1iZaum4qD-?ey{~{{&3q2D8)_o7Mewcq-a8Tdg&^us?5l@>MvoJ7+Fd01l z89KkNRqI6Zc)J*;T>R#YRI;BcwcUADUG3*ycreZ;Zw&wdBYJ(_Ny4OBZ}+tC?P{fR zVf>#8^7AJOvxl81Mnj;H7mr>lp-*237=Xe{mE@XJA$@E#tWU`Zf0;LUfZRB`<<`1Ple@&C3;KNqJXaFTM^gpn~pO3@QRtw zqRWT6v*NMXi*2+2(Uz(jllg|im@6YP(}|_>LTxSIu(e-zdtZJYKUSHOL~jpKW`%op z>ADh*NKYgDiv9QXUqx}cbvrY)|LGGHhXrDhC0}DY|7o(J#+#iMbM9$xfJ^iuF6d=Y zLhKjRB^5C z)=Om=+KHt|W01t-DZnerO(#?@FzIu_f`R9o;-5_IgZMty2?HJDT5TU?yQ+pg+)u1{ z6K~B{%PwI)&BfS%7Gu<@<#D}L%2m_52>uu%{P(Y)7+7^mcpCXrNXKdD$xQxmEjT93 zf643Hh5h&rHuaHXnZrj_;?=-@$86 zg;#L9GAX(@H77Ms*1T;%R@az}fi%@OmsM_*f*O~xL!yV-UkZu~FOs7{%2 zjm+Y&hr|l=Tk1it^LM?k19#&0dnV1AuVWIA$6pJcJ%m$ycY4ZA{ht*c26_%U2r{M4 zl@H5USTX0z0}qyhTmx+Pr(bT3{9qzjVGssi(Mz|FN`T4VS+~V?p(4z~(EE}ZeN$;nC);e?(;vR z<&q)Eu%I&*#DinmRd~nU3R<*0Zblp8xp`=lG~y9Aqb&H*OIaw3NG3Z%v;(?E*A@-; z7Y^g`^{V#CREgHv2G)}MJA_j*@R@uUFeAUM0$nqJ8$eJJQ+b*F0Jcu2?+!)C$Jj zc*)g+2~{lJloSV;iOyE34qi%Q@KYjAN?I6vV&q{d%_{sf2iBv)Dq}rur0SQhYLI{Q1~hT z^ML69u(j!HhYW#9JJksum0F^3PVQMeIc+4F4J`Ae{OQF<*S3+ob%*ED6oC~jqiapp z`V=GCUa#w0?3mgg%59jC)vfHXXq*J~=)Kupcm;>-)KwKN2`ukf37owif9?bEO>3p@ zZ%dpZz-WjRq#%#_OxpiPG^GngGX+p{;9j$1o98sN1+~vr*ii;WNMdLKzzncJ(xjRR znHw+*jNjIom}->b(=Uf8qLrH?4)7}|Wih!hezxSFOiZR*P*(P7!YR)HF?;%vi9Iz= znLq|2{&Vw60-7)n-biA2$iMj>AUk5W@}_lhLENLA;?$~#kW3^ABhpSy2dNoHRmTjv z%M=E}C3g#NP7**4vz;mL>w_QVEIrhKMf2<6>s;*olc-vVr5HIDmer6B{(JmQ`>H&x zKHPrUVX$J!KdzZ!1TDC)^}BOTRf4Y>90|QgV;b{m7qnKEU4C}qaq4lHjX3sOSJ}TG zcK5lxuto8wvs~xieSAVwVBilh=)xFk>CYrW9So%IHD{c9DYqe52hYIgIJVrPW4U61 zy`i>~Cr4FCeja*o-A(2kj6Ajd^CMSKhi>)neeYL>p~HJc;WUs?ij}zm2Vj}@Gbjbc zGmT&lD3PFjjm!Rj7JwFIiQ(6oGlkQ^hWBzN2(MSB!-dH6+weT%=g)Ik@klaw-^7e` zl_HvP5qmo;7hmQ~7`NZkjAeHMO4PPIz#GP; zY)+DRo_8gTi%3YQ-sr)(o(gjcnqScTE#46V5K~cw=JDRGRBf>O;NrPB)=a^=1#%#{ zz9JfoPFPQfG}QPR8dgf0u647>^$hH;6IX*n617nr{%W;f8C3|&n0{Tk|3%X7?qm57 z#r1rCb7#t_hq0wHQd`%eAYOEPp^FJcTn0>VOa6B}DcOJ9i*DhQA#avDyz!OqRz@Pe zi1%mfDXS(jS{!M%ok#d&VV(H5S<|y-ceZ=_*#&2QLRQnvbu?NY#hamiqQVFB~8hQ+$2(T@GnuVuixQf5o9os*!-C$|9ub0D&tX<;O6(* z_>u=a@2HVzORg_}m%2ACAkrTeH6#KSXT>QLLr`MYwN^&3$!LG~{BLa2ACZ{UsHYMU z6PbNN0KHyXhPihM3eA1_tz$LY$34J3k><&4sqASoIQ(Pnh`=`JwffcH+_&EkR$l!T zL5dh_Jm5y9_jy@CoIDNQmcJ>|-XN8RbBg_CqwbYz{0G<5)7kM`=EsfdfbgWQ+*l{Z zVXhPn*bivt%E-bRCG%PID8S?hxqCUqNMa=20zJeX@{!e_C%S|sv-R5KN9J7E>~&+< zL_Ie6(6o|C)SjC1!#?-eds&6I$9hYTe)T?k-x}z_j!!wjzaFuXqUl7FB6&t5j)N8U z%iSU{^xM0%NDk~UTp2;_>{8M93Mki}u?;NaT0Oe+I9#gpEzp>DCkKYaR(pa_kX=BIkj}?XJw%v6MJd}GA$qib@6ab z<@H650muFD*RRh1BIaWrNrZVDusr}PObx%QF9zc6@S>wi_ZOWHi-ycF>;MTgDO=-O zcO3b5Vo9=YZ0BjTQ+-nnZYat0c@~H_wp1@bIYKx7<7ytWp%fPj=)CdRBheb#1%@d& zjaU7y%8c5}> zKHBIVpx73r3X`K`B!&p^6KzXvifVm%>s5rT9&>*`7?-oGX!EFpn%r4Mx**}>Sb$7Vu4B1+U+atA55tO9g* zb@OFjnl@x!rIrn!zfo<3^D^A zx2M%xrjh%gfyW#)9*ZbH$((|Km6ZU2EX;W9QwynQ+s+|#y zZjd*p?DHqbJ5UK}Fo=MF59qfW%Iir|(s%L^2h#8Oz6&a-r5@kH&3cAIw zw=V;u(hqH4OMVl*GGdMQ+4Z0553M3@H2E6mqr(r+-5EL6xeDC+6B^e#}a2+NxTtp0~#>IDYH)@$X$+M->i> zRT~2m^Spba2R<)KoiXQ^oB91^Z32Qu%X``@*u%|!%_zXM*aH$r8w54qs7$@zaD7%C zAi=D-!Fj3T5WtfU>0$g;r2rk2Ufg8MOqKuHIPx95`*#R;`*CF{a2^H~IqQP`HmVaO zOE8j!(a;b5xSi#mcmy0hZewnas|Y>QKN~CkK#(3MCMwTNz1T~;lj!bgyj}5=aJ9QR zx@hMTec5csE~M6Bee?AC_%(2q&0N%dQ+w|p=2wZn4SuzG{X|0j+r2e(Rq6Mjn~AV# z;BR%|>mu>Tpo@&VK-0<(nM?hFvoFCuQldP5yqqID9;#c6GJG)(1aTvbO1^tNBO?kw zKl;5MwC{w}Iwr_>!#YGv30oS6^PV6NN$+tW_L>fagg!B`kbfaq>HVk|h9V-X2IEU{g(J?5`h-Tg!4tw~W zBXtzmX6uWpH@cbV*O`(OlBwYAl$F}QV;aWiF-VEes$r1rHb*j4g0Zc(r0vG0+xebi zv|D(2d@`d&)cC!xpWBK(2KnA!7wP_WU~Tm1WDiXW(NRxOBJfW89aC#RZV26yc%Wj) z&xX$AP!tj5-A3&#D;IvGp_o<&b&#W%KMj7(^7XdYoY#!_3J%ly$_6J5Z-S;3i&cEUBn}FkKH|jv0-y8jMQFzBIq~b={=UX1nL7vS_b*Ea{eINL z{plMP`syi`y)T=ue;aYch!sfo$EODv8VkFx<~E(`*gI@Lqpgv>JuMJe#Yq8 z^r89-CsEP^{g<7nuO2Y*KeO6ASZS&Za=jndRo;DyVTGI{5j8r;{$U<9?#^f*dXMyG?eY9Ui&eWWO7bw->k7{!1hhIv+nfh+Bao;D{&$X)+|+iY`)%) zs$~R-7^M7iG9US-^}MPLD?^Qx-o0swe6ipM$F8ie*DQ?DYun@hawf6aF3QR$A*EEg z3usD74sBtXFM5lOk}txktN=u+R11-aK_%~lfTAg_rTm!QTRZBZjAa18%=$ZZ>QbrS z@tI7-RTFELOiSn{|IA;ca2ik1z0m;xselg^64)jE_M))&75e)0?278Lwqgpq+k6Py zd_F!aG!bUIOg@Zq6;v(J0l$v)KG3@s4Zpr9ydD={X{cI_{4FP%V&4$YBuzsa?Lq{GD5a6V1dJ#SF^!#2M=bG9D9^&!PlQ9Nax z_H7P75cIw_zuqjYDRJ=^+dp3T6=snZ!opl%slV3wI~kOfTYfw1!J#e<)^3N%X%>tX{f3enhKMr?Ivx$-s^Z_;9yd!C2H6npp~+Gxbho*X~w|<_Yu*!h55Us zj)t>fY$HwlXp$o1_Z=eOM?6X=>4A(ht2*;#c*4pm{QWdrsBR=1ZAeQRN%NnU@&&int`gwc^K{nY-C zrmv2Q>ixc!P6c5|fuUQvyBov->2B%nK|*TiE&-A5k{Idk76D1=knVo3pYQKoYxtKn zckc6?bN1fn?4vyA@#6?t(qjI-&Mw5)a{9FtU+HDb(Jpc+-3EU^B8x;f!35Sj@rxx3LY1#6 zzL!Z`aU&_i>!aN_yPsJVqGqr7JGYw+z0vMFj=aSxPeBh z6F*9;k%4@I8&A;Bee{zs)9m9(n6DX6E-)3q_&4o}|EvMC*Jis>nL}!{#`$L*5u~$x z)Rqrvld+xillo^teI##jLl!y)1*yZYjy76=>D`M0XVeH;Iye2)24`DOe^-#8?H>=e z&9%}(H16`m>y#i=O`)UX4H)MI?0l)hh!ySupDonk)*lO$vJ8hktxxf0c7BIhpDtsZo@V)f z!0SKi6d`yvX4Lwin8p$rJ%=AZ?N-A=k#;C@Vtm}3keZ?)pv%>Ohc=*!Oj0ZOaUsq& z#%9{k-S{>(Ty`fiJQuooB){Q0$`SK?!T;%D`hb1i@FFeX&s@jDQW`*g1Fd+MUhL0J zZEc5vtY)Nygp%!Nx7DK8CvLZ9N2>wn#_ZLGSB;5MHXH*Bjk6yT>Cenx6XVR4*^5C_Mu$ zk#syTkuzGZFjJ`AfzErD@D=N3CnmQ&zf_OwkO%MjJ?n^t9Aq!y`(Pwu@tPbS`=-k& z@+L;-BT0b2!EkJx>9_9BUbFM9b=o3~X|KxQmDDz1`oKtkDt@j6HOm*3ziV~_c_>-V zDAO(jzvyTsBTKHu_@e0g=xM!xsDn}zB!uw*=tPC^ngHz zN!~_z`uPwk{BAXceTTi;prV}j=MjSV9mOZ6HBe_4&cq;+Q0`*Hd!^*XIDj9n7hOkpBBcDu( z?vigWYfj$3PW?FXcI*W5T)sZPxohJ|OV6OAqxW%w5^rD=+>L)?>`E}f)k-xS#%cQMus^2}S9mWv}q+F0;)L!2*fEXE0Sm}J$GKijHZmJu6j zkr3Px0&{;;hK$?w8K23LOqv=?XO$0b+qy^BFV>_`KYy&l8#oKnnwE$z3R<#fOLUHa z4Hn^G7HX7~;d`TKs7->*iJO@NReQ0RT4%a(gSz5lBo1%AH77s zj0uDdUuIv*~;XcEYQBG7Ay37z{Zvg7>YQ|uhCxW@`Ndo^JO`Hk8`eMcOv_{v*CiG$3`Vent4l% zIbc)wM67xtmG?=n&qfXb%ir49+@n5kPQKu&IwfhZfVz(}&_>L+i8GUtZ&|Wi^~~wW7PQaG&ux|gmnOx$T$q~X|cd2`z%Y@H$JXrMJ>qp63{s@;drBx zN5NXc%c}@7!W5}`0 zlZ~I>V~hA5I}E$NStpFn@N3w|pKmU~ZFkrAx6pS1D!uxlRndPuKWKA;*JKIav;;D@ z0v$kIR;rbK1?lx17_6ynvhR()h~7>F9C~2{22SnRrMU$2GR^RmHvl&zWf^V|w|p+} zG?kY7H~M>k>$WO!yhYP%c2u&uA1xgXEgf64Kx-Z+H>Y1?DHPpE7zLNW zZzRQc;y2n*Yd0@fs+M~6_CJCAbq{{AE-4#!+t5;_84om3>YV;Y57&nrDs|72zMicz zl8DDt8b33L-yO=&?G#;feX}GQQ>P1CTpV?wPEzQT9OQ_W#^tin1NkVvMhVg`zoSAm zbvU#yvf3oRi0eFkQ}kgp<(1^1gdXyUDy5T+kfoLhR(hxuKmJoZ%?wEU(A# z#B4iCXQb*QYp8W@?Zl!c{Tc2Z!J=K|SQXM$GSUra2Lc~eSo4Y}ri`Y)aN3B2qtV+m z=j4m9gx=NdfTpo!lu;)n&bysu8; z7+!0|xtLwQpjP|+w6G{XMik^PmCu`>`)Z`_Tm#G7JKV8^RsK}O{{@}m697RDOV1|~ z;S|llMEya4@cQ_8|MNM~^HXCXx3TwnR1#ye2JX}I)rxR)CAZoA((dDZDj|Vt4+Cvbrbsfmo^2|!Nh`c zjs3#k89`R>N_2md!L;?%8;`TgkQ&&%`1wGp zDzTL_k`~k1B~>g_NRwA1a&V9WBW$bYb|_Sxa>>8dltB&^|1%v3_Sy8EzgI|2DxOQd z!P|rgJPc<;$LuEng4);M8yCg1z&i!0+j0pGYVUG`UqEY+WybZpuzdKl*nsI(kQ0vQ5+ zdDRH*Y1)?>E);eHrZQGU#i1W;gdcP&Us3yd%l~L)$SEsGlj8;nkH6Q(nP3&eZ zb*eH9<`<4#xi{I7mfw#Zq@BjjCdnavB`a;03O;-FqWIy(HQR)L5N&8HaY&Os+tlKglwm+h9;GRpI!n>|TSCd=R^-5$?0|y_XR`k2njo1#eAv8K zqM6B>m9gE$vEqT8F{@CiDd+%rvRqQ%j4Qj~&oBRR#Tlf!>v&{hmF4G^jy6GE26rB70%Pja9a zO$uH7Q5(SO#TI2rhsQaDWLdzP-7q0szwkw&F2B-*x>kak0IRPXJ84G^ve~}}%Ie+o zEMc*Pz>$rtW-i!NEds-+@a&VvPEY=_*`QmQ8_O{gG7~^DM4so;dTMe;9`QrCiz)VO zL|nZ$-t7=F8&F)YYvnI#w@(u$^;sZ7Wzk+0P+gJB$9^XlOuUYx`t)=TenjZ#$(d*k zP7JUURUlh=m14>q@{Ec z(w`IR#$U`au5M%EpEisss!CAUwW*(eEr`$mJvXSVsr5Nsr>XYf$qqz_h)R%kL}J3} zELPwe)9mwXQ}0s3Ol|Bp_l@Z)Kw1e`VGT*_E~&x|r1%hf{Tin}@tbxnv8_=2z zZIeE@`q!yaOIMN#2re>7>}QSA2eHOOR8tJBmI1!|d!KURu~uvg7#(tM8q#ITJf33w zFc;hg?KGLXR(-UcQlbb!hfL-OtX3fI1K}lS~Skv>Q zt3Yd_XzXp8^wc+;khwLcH#mXGlkFTT^D^>Dg}sw+xxxm($LZbq@}gdl*!HXfx#388)0 zu`AV(^dQCHZ zQ)iSJp-#_c9qaL7h9B->m{_lg>I>jg2xzpH1=V^4XLc?Q_OncQtn^>C#WD4Do-w1OVzhZhA= zr40otf5$r)(^0H_*NUUC8q+`?-!%SY)JeqiizkS8a#RY_>K6^?$LyO!wCCkNb=__v zl55uN?S5D5Er)NjGr1h#?dvk3G`Pvkj-EPh_kcUq9ZB z9I-pb8c$3PjdkE>Tx{99h4q++jAhX(YNgCQZHDH~rH1@Q4KppyfX5Mm0op&x$@qt- z7zlGEBP}fjl=}&(4W}n>*tb-tn~>RCB=-7!#`1$b7%*${j zPV65aN8`_Ik9+n!cO?JXdc-}x^GB$@}iH^(C1)D|ins}ucgx1dt2 z`_bCCr~U?nYwkvqR%M8e4Au7ylgq~Fw{u-2V0p`15vWjaFs!@%3lJ!OtI>{^hM%&6)WPj`FGU02>Jp=lrVS$}iNhexJ#MI|RL`_NV1sPXGBQ3TB#q}wH zu&r$dqD~pPt?_7VvV2C|&nf7INmCwv;((JgU8n@*TE9(QV)ya2xp!67ZMkj3T2dj|3ew5+POYcgwu)We;I<4EG9R#)3glwB8MC{d9s0cs zIuDP-mcyrwhzcBFzYg%&x|?GWt+uW2cGF_X57FQonddjXyr!}eOf)Tur_C_m=6VP@>t&b%Y5`w5}F+|RFmr_bOR zYh-OK5hUSV_qYO__r9+~O(BMDK3hp6;Ds+ub2lcK1dqhOjA@wyuc!Q{3wWiE^Hr+2 z%ihW+B1R|PRU~+OCmn*aB=fb;Wn10(Fub@pNisRMNG;@CW|)4Bw*HpTaaP48E6J@G zIih1SV~`6oVA5dvz*U=Q0)QVKLSue8?ha*S3I-Pnd}_;xV#8ZRhd3;2aLs znQ;=Q!p;iLz(k~nDfYXbp~7rZ5@bot&mwsWHJfoxV(3vRAl4eOE+v=^5A2*XC*A_h zpD5&yj{BavIYE83f4z*^RAF!Gfesz_d?ZirG9wczs-scI3cfK+TG0h4LxW_fWshsG zYdQ5|f@l?mlo=qArSQ_ePHL~$M68Lu1zJ-crCVs31Xkp;HCaOw5p9dO;A+J@5YUHB zsD$GCh$)NK=gMB2V0=Z!{TjjP3|eBkElxMEfR4RXAn}+#t5-r)P_;_2j-7MJ8_NVD z0xWJ%%Z%tXr{`+Gv?%0#wK{V%r>Z)eb5yc3gFvHJG<|(8_B>cnME=zEgU7dFp|1=e z)CB(^h6K*?Avd_YFOXizdc6IW7zxjiTQx=MlPD{`SvZD|U^>{CqTg>6GY;LbHnV2=&CKoHZk*T%IDZj$jia;v|zhMhh^$pZ5u582q3 z>v@vab8HNDFfFnakPD)3lUm3>6U->R#49DX=n0wK>>T9KCgJ_@76gC;dmcjbc0^CF zSDw@_gI=^g-Cb)dW740O@h3$FUB9RItL>#l(J$d}-4@$5V1pZ!4CW#n+b3;**bS@* zmox`O$&h4w*1mM%qrl=8SbCEmh^H6+H z(7rh3wAMNqR#_|xIDh(-)ik!-(BI*6Xv{my6C&|ey6@)_vF4jBNlM%^p9j#)XBT0k zldh>J$=GWII+P8ld**jST*593BLW}r9|1-bL4T|S?}$^evk$PBw6c>#n0He4(e&x} z>OsV+F;&)q~%#E|LOH|VO3)BAAxxO#=? zz9T(nUvj*>P1oZz3h{^*9c(oG(pG-^U%J3E(DNe44fy?;(gyGOKh(42`nzl;IU@^T zH4$h*{GY}K$d0A^6F|vA$Iz2Z=D3;_dFt%I#9%mf;dz-Ez8iRiGgB``X1w19=53P8 zvwMToqWvpw>T|O}l?`nLo}-(vpyZldl4Mn&o^!tOMha&pfI!zctrpOnO);@FyJQ7t zAP8n}I_sRC)$$9S$%vF?AaG*G3kAAHu(Xkk0G?L53?vl!)z>gYs^YOE75jz3h(5ES zN`7e&0^bhVe3x1Q6>d{eWo1KUWs2YCVbk;axzFEQc-)2IIuM=^Rsywr!CpF$iTLVcNP4RdRkgKR7AkFNU=*MtoUglNp-K zKKI*VFxpT>JKGXRvo@Tl#>^DZfe-kNGNx6i&gAh{uZ?Xop5TcXk5G&Of*Fsb317+k z3LvZdA`(*z+q5SQTS(!4Mp;OHFc!bX9FOMsggDxnCNZd;pcLH8y*H{pq0ouXp+)Rv zW}yyZ0%3eMd*9mxiVJ)MwOlrB_FWiULBz_yb4@{))Nb&)Lm|-vW&_|`-R~0bMX%Es; zrucMOqMRmw&G}qB%_O9pgsf{>l>jTO2rK#ilQDe|)0y)yGmi6Rx&eAH2t$@#(=ylvuiEs?CTh^I--LqdF0bPXCR0fMgvBB&1PvBUlLS+?A3PUL z>wKI_TXox90fO0-cXAOoF!gt}nH4_Lbrk6B`msw8CtQFMS@P`GKdSaje&X@3bDwD= z;^|SSxV{5-)+a57%y%RWUxkB|LksU1*dJQk>vBZRrgT|_l%+jpcC^J0ew;eIhx9pE zI{)oon}2y#q?IqO`JO##P$*M)tZxMkzo&Kh-h{4?zAY}e0C(_%D=s5b!p%}ZE)na_ zVn#v&4xzrRqvc^(ne|r?!+tMJht-=tE*e@y>rKm-6WI z_35~nb*@)Hps8lpk^07pDpOSky&($p3vV*tszqbB2eO;OaH;bmVrz${Gsnk>?y-^r@MGzTfyz>tauu!4uY#f@Opo{RM-5i zwg1v;Gk)t8X@mf4A}IQLN_mDe{-nnsH>Io~Fcem(B2?$p8ppk}y7$9{j?8G2kYLGi zpnByNQYyz54@c$fH6Z&ZTwxdDh@lR9Fio&U##PNP}Kehh*jL+=zc$` zdg6xP!Biq$BD6bx(7B0yjSBtjR^F(z+CH#soqgx|#^E^a)LW&P^Wmm17hGz`f53{9 z>(5%V>*e#eyn|9QJ|%TuUQN_=I%B2nwy&el;v0%RRIM%ji3s|!bV^@HcR8{!y zKUo9BY}Xl*PV$WhJ14H1@z4*zvIs=$wh=2q|>p>>iclN zb(gOmB4TrWc00UEs-byx-8yuZM>R!(H&f@Imeo;c2Z8u`A7a!r_uieqra4MOVm$D& zprw>Mtltr^qQGHf;=n$zIr_dkj8S6{!<_W-rKOb?q$U(I+=+?|DZgO!Qwt4~Gua&J ztQkD89}=pF>F*J}UG$-E|DJWgb!YcW;cv~N@6r?2F(|*gb!@E3T)H7N9!MjCg&8)&)+L>KhNVI_Z&7p zFFv1jm=k+e92OX18AKnwnfvM+IGOP`A_Zz!Ysl!akcN15O=Ed#rMO}_Z zs-g~w$fmKB>Rp0Fkq99RCA?kiYSw!>f9#CL^MwttOt-}dvt@^e20ouK8o}ZF;S-P8 zm=Tw_=*Z*_*XaV}!~oJ%i=#=<`9a=~rVRo4fXP)ESnpsDbsjLMsSg?!wg2iwGCIp& ztQ^{P`VT3%=#p1*jCJVS=!&ox4YY}oQ?!mG`5EHQSo4K%nxQKhBbGoKRAri+Sk!3@KSNCc!1~S7to3n2{1zWoEXJcQLrG4unBOl53SL|TAD zDsXDs9yNb-ORlCrg(|5iBr>{G;`<;i*Df@k(g#s{cow-| z9~Ls@qZVxyK<<{)-7zMF_5E$J>KU8l{d9~GUJurKmtC0 z$F}ci=*f5Mg;(6a85q|V{X16PDgIb_sz4XVC&t~Kew$!84no9~=1?c&-ahfzRv;#E zzV7aj0gW8K%JcYd3(Uym`L4vbWc zg6U?W2R8auy-)IImC7#v1-GvJhK9n12Fr#5XQ4{xqmT_~a%{o8(@OZ_p>vBi4+)ur z@W)9~);m|gj^rupoqwo*XbdpHWMZ+odQs_U_n!RQv?dcurpay4aLfnH(!{LqW0(>0 zLf|w-3ked7P6cMaDnlHAGv`{P-S_A%_@#8k6NIq0j?;h!CN@tz#uWo8izhVW2^GOr zM+lG$C04DGVr_b=dVe2G6TanXW-++wTC32idu$P!9taD<2nZ1!0Y>spIs}Nt$5_4^ zuo0sVd~<1&Z7Q_JI;-?@${>qdKlf%?cflbmc@@OSq!?s6-*Vi(;VG=E=rZRGCh5N) zJW9Eq>S({Nm5jEMm2LPwsr|>9z1Lhqy7N0r(O#ZG<vE)c}AyQ(va@GlOcs|;GlA&V>AvHTc zxkVJqT^;B7d=+=);~(ozpQM5qg|O(*8o*ys1k{tPn#3f>((g~iSbsBXK`M5jOLf`7 zW39m@KQT+ChI?(gM_B+N1BO^(O(j?*Z#sjPqmew+$+7LpNqjlXwe^=f)s3938c#QwS<`Ivy39;wd?$E|StSK4^0GkT?%d6Y_ z+XMv!=I7?>fkWEuR*NSo^PU>E4$xN2*+Z6dCt_DK{Dwu7XFkDX5i0Kn)`z@V6(KUm z5_6@E$GR6=v_Koy{DJb&%~Cfg%=Df3iJ9~Vnx6>Tj{XN$O5_fzw_ogUP{xF!GF%YS z)rQ)=Md%X-o5vD^zKW0A3-KPXiu+y_|NHx!lvmG#zvz4b;m&3EeoD}$5WW3ufLW20 zMiD^3ll#ge`}Pc4?m*x3an!=B&qd(7k1!@dU*fkiMXC=H$I|6I#IuCN-VJ&X``LR& z*p#N-EG7y7sfL!2$4fBD&=zoo)43@XA*hIO6yew@gV!U5xcHwHX!|7%1UNn2xOTCY zO=)PFY-{R~B}ft9uYc#NNCl}C^Mdp`UHHzKwUz$WhdQuDCQLIkC+=!TY)^gcEs?|@ zfQ2}2@LhR z%3;udmuoNTa6TV!d-N&i3rXnClg8n74RwBm?!aGdL!u~1m3Ge#Rt^g~`n)EBAG(mf zTBgUg_?P>!lN(h=UG!i^er={L=3-zk<(=cqzOW#5Wyv&rl zNxyc9QZb1kUV+XZ0o>yZhcwdB^c-H=v#JMgZ z77diG8tFS$L}7MiG3y;BAhA7yXy#LMj+LR?d1(}aw*vMhDn&_qnxyt=+gN#L#KbK} zFDq<14PHv(PKaEro1-9bHgE{?_|&)msQqm~vx$}QyI=hNxYRiM-OG@=*6|1JiHGKf z#<8Q?=lw_HXw{ds#^Do0@wBqm(-PfBS6Hvw;_T+w-DqXA4azudqGO`V*3M0$x9hF} z%2p~5u|lP#@H#<9i9Qu(&f~?CK$TQ^xz~ga{|(D|p_nO^=WOf!%i&scPTPKE(8P?Y zwI$KXkn2ChgFDYs9Vo>!GC8U4#4ddO+LBJTl#rS4O6;me>GX8x_!`^ben?r|uHvH^ zPJq|OA~(_MwQrg-3a#us8P=<`Y}ym7w26#p0&&0FT>e=eqywSX%7u_u)o(!v=UAXV z7C_nUiYW~(#nKidCq68%6nQwycOql1rpvf22*F2sQ~ifycQj^pY_dDOQT6f9Xtnh= z!yiZ$f6kq0%x%1`HIqh(>13*rc_5DUuZ$0Clo%~^jIirbY4(Pnjh;A$Ex(^t1+edM z7-4ADN*Tt2H4Tn)i%dG12eIidw<-z%+Fc~+N3i~&%MBr+Il{lP6SfFcJ;WrRHBp(7 zby@Y%g90nA<(o?Vk3Q5c(dM9Jlj$4&B#9cp7anOE=lWLhpTsFa3HxZO^OgxyHFGqS z=1lAeog!{y^>OamZsQ&_22EzVfV>yW-3LG4fE{05Zy$$mIK&LBboW(GFQn#$&I$*W4GInL+*J93iTU4rYm#=&*iGYyi>hb+c8HXl>cGl>VeZLUE z%XJEvZWVRY+uB7E|$D`C={*N zzMU^SO_Svi6X!6ViAm(G>uj95Lg|21wy6irh=e`?%uWjl4l3>IepNkSj5h zJhO?mxR@aeE}j{Xpk?-zH&j`fsc04_Ij-(e$8tA8YzSU!Wj#8inHLo?@IWL6PB!G zhBf!fK!3b{Vn0NAh&VC{$h{n@dOAt9M$y}ZS^;as+l@Z1@TJtVN{lZjw~sA07AAC@ zfV6>(SZiq%a7%DBmY0{;-kxK_!^I2D9+zoe888&MuH8xO-u}|m;(%GY4hWzIj%Z6B zujCb5e5*Zqa;rGB;*oEwS8l*9nL^}7xGkl5;$7sH^&6g{EjVV#T zgN4&Z215?-cXG711$UgEjxdIW<=4Qvax-J_&D5 zTr2Kspc@rJkBc#@mtw$_-?_oTnYkv;p*Vbmqfd}O*a0jz;Yd*f%JR-SZ?>j< z5=>IipwjkB6Ov6!O5CR9duIWAwmB)r?}4T!M>Jq{gvQsY<9@?ICt|2!zS$J_amEk2 z`i5_0DthK5K_Yt1OXaG{gTwllN@P&sO9MYnj3M zOmnuKj7++Jp&W-Gb#a7=4PcY+5I|W2Wmsz56sQL%H{C1(s3jmA*Loy=eF)anvzC}2 zg<3+#Q4=XQl$9elV@a8#7-Rk;r6bx-#Q+)n;^I;TbribvHbZ;QoxbJzU%9vI-v1+0 zj>H-+cWjb2w=r5x$qoo;s^I7XlWVB^OQTA@IpFKEU=w6=9q#^|L=$+L&aa;1N+P!t zGZRXB+P<6nP_$1vk~f~3q*iTMIU0u~0FBjQ?XJ`@03UkzbP>WNmcWTF5T`X{KzK`d+gDFZZCh<|NCkk%iBMQ`WOksytWiBRc2wvqwNEJ3hiT@ zy9YD~6EhxZ1Y;YI=psG+BK2X(jNli08!BrAjGE3D$h+SLP17AHz8BaJ4RR!Bq^&a* zCHc;&M-028efkGOkj;#}!3hfUdj=6Q_HcvDB1sd8QlMR@&5&yQR6sP^Y@WC=J2?A3 zya3FoHeZ1#I6Jh9w~4Gd?p0!FSjkgnBtOa9Qo-OaJ7A%c|wpwlB% z#pU}Sox)l`ULXw(0N&Dwlm2Lv#tX$-mptm)WcP(O7IPj;soIE`sRD(ZJgGO4;e;Vs zFyx|wE-J5`|9hy7!nCuw(l3E9AV7<7&*ZAfE6v`kSL#urw#A7qDE;8f zHM~QYF$0V@@9eQm2f5s}0~QN@W}-nDPrKv`gW z@q$cQQASb|EtPuBrKN=<89@c=y#AMB-<2b1H9qx@re^9a6^X{GO_t7Zib~rOFg9}N$ z7SoDN41-e5L2Q{YpK5iFLn5aPrh30lGcv;T^z?o|)TczHK!QMv4&MKllw3M733_^Z zL`9dU7*E8yO(zRu_shni1C$w!gxU%-suqhw9lC`Majhu8`Q^rFl=g@s%XdeaqKTg9vWuN1qcy_*}BbUv!TAuY>F;iA(hStE%8BqV4zI7Z%|YL2iK zM~%JDiqd(hgipB-lTX*;epAW$zw5XjI5pZSdiEzAJa4a+HbRK0t33+cG_O{wRR7o2 zR6VeFDbR6v=QJ%C=|PpMM4X9snu7d~DVu#bd$1)5>)G z`2749u>x15Gv6C8L54YDk0cG|>iln@F^nV>c# zVcp+T?%f5vk9Q%)b*4C0*|J0aRU^k_+2j~uAw1b1OC9QWNABf(D?;&$^$OdbZ=?a% zkpugFK>YD>w!IquE^uN)LnMGtnTSB}24E+`dj>8asiRI3NBesXNCHk3J|^u zdw|%X_DLCvWJCQczZUleB$0_%9~YN z&EI!rsA7HmAIF?ci7VKM8?34l{+#>^5 z14n+_8TUE4jjC*gUi#ko~vs3Yua(eN3TB zRYpOvr&mqAo>z0Jqb$Q^7YdL$)*Uaz<~?D-1)WL_{~gZM3AXIpztbdF+iT9NHV2AH zoFP}tMW~2b^a80Zu5}CG zYs0wQGE|Vtg@q~p_Qt0LNl+>QsQh2S*}XKdyakm>Ed6QZ2kv+}|8zw1H+XNVIQC10 z1uJ&efajlPcLgWVi>BHZXCPB zlyQ4Eu0VGOYOSJnLm0rK%bx7t)lB4ev_;dZE(lCmdmkpjZobe z*Wj*2Tz(hUvg5#Av$A&C(s9&QpnYIB8V(S#f&!~MyuByAftQ1#K>0eKiXJll)4c@6 zHW)x}%ly@y%!9TncW3;$k1oRaePd=n(^vfW!(B_)fo3=qV1{BcKccoYueOxxiar@c z97bL$uGe!arVy-BsG&92%8u?@-l!UTs@N<)JVrpD^qK`DK1_lV_suB~D63KdSqoK$E&_Xu5Pc*ZzC@3z@Iu#29CajO872ZpYF99{dm47I) zz&X_8s$1I{F25e>ZO@cCW|dS*n~l1&o!WCqpwb~LBwZ|lkEj|Vhpg^bvpaIB7s9?f zWc87ZfjQ;_b5TpM;X{|JdF!#WWjo!v%t5KSDnl}tC12L#?g);Yz}pzv@4OTt7^{0K zcRlQ@9qwE83Op4|Gi|3AacT|OsQATiv$-2TmOEILuL_`tQ$`xT+rB~*c}j5uw_xf1 z*Jw$J8$k|iG!i|Vk_YQmx;ZwHTN!ZzkV`We$$H)(QV~XdY_1FW`!R2w|I@APgb5(Z zy1>sGf^>nt%>#87-ulJ`3Ceh-f*r!`Wicm!*-^B6niGHGZ=+e(+G%}nXVp)0e)V~l zQ{Nydyel(?A(lV50=*`qTTobt`+H6lLTVyES@;(0D9=t5$)}@-=)`~F5w2BOSzaOj zYtqGI4YQm|A+g)#A@yTAts?oyqY}Qki@2*Xz2d8$qS}`K)f9-eBdsUhQRQ?f0x@H+ z3T8|*PsP&Tjuz4|HLsvq0Axm9!ogA&QM=I2i2$=o%3Qc#zDj)I+`$h{zz5ZY(>4aA z=)vRR$>Y&29D*n(G|T;S>oZ;fhtmF;5D^UvJ^Qr#_R<_U=H1KcYo702+6>8NSJ8-eLo(YcqJAl zS5-|&_}J4X?)}6tkQJ)|LRqA&)Ab$a{Pd?~;tusLH5KBVoE!=7Z4=X`L^dmMp^v4` z8Z&xx;~3B*f!_AJ^Oc#sgqy=b?^1eC!^vRVJ5jIaC}#M6kMc3}>TtnXKqfJHNIgfb z7%|Go@h^eV?&4(mrM>Mh7_;n*%WfXF8uq+_RysoN$o7>11ecEIKSCvFo?#`tlH(ds z49-Xh3Om~`#afN#R-gA*Z5zS>V42RpburIi-EUfnC}-I99L_H(<`rU`k2s`!UUjQ% zNR(X_`fZej&ADYe6O70(-CcUo@7)oycfnH6Uc3@S+LePD?97pVN z+ny0bs|cIe(atOzPR9&iJdW+B7T9gq4fuK|JvJeF0}<8O^uA4)OaH>Sv-{VXgN%&$ zI5#8LfvVLQjO zX$<_zMl;i${?TETf2LkzNV5pA`($AXe0+^*vh}xj;4H(anm2{%r`->nXfEfjag6+N z?1o@T^JHaEo_Y=ZY0xgZEbyA=fVI-&a7w3lVkqO}=8I!)eYZM7U1et)-AmGZNu++J zW5Khw)$GUF7fJmtXoD#i|KT8HvrnfF=j_f-v9YmN7w+LwlAF-Ke=s=-ix-ca7cVXE zj=HK?<~p##&!>JL^x51!97zZ`ebOXm8PUv?m`oel@)j|Y9~mNbdr5Zl`9sk5k6%jo z0^OmNDmA+ANDJkd6YEl8@6G+sOTkKg)9=`FF+$HGf3^qiET4bc2e(uuGYRXz9hP42&fZxc`BC)LuvZyH^mfO630NQU%hejzT(G|y)ds&J zx{8qEau2hDan`sa;0U!|se=?gXPG}Thu(E<;FP9hK4jN_S2Cg}7}9y!)vs~pEdu+7 zZJVU@ih?CU=}U{hm2>N-4X31!#R6L9r6_bUfqt%zB4jUv@+>p|Uwc>n2xYs5i!7f# zMudz$OO|6N3>t8I;1^au1+0MO!u|YVM z=KQr|74R4#Wv3hOHA+=3oa18*xg7ZEtf>upnz}PI6TxM#0{B}!6fHMboZ#RlU~wOFY;69uReZ+sC^HN5uEOvYEVfrw4=n4w^Z-k6|uA zWs0}bZr*9S?904Z9C9@nxF5A6hNq@y$jYlqOM{*8M(3}=J<~A3vw#KFQO_) zP5Fw1NMgJC!&7}vSKU}mc}}3>N8kdVSH)fU-r>LOVZaunnbID@c9s2W&E5gBbYgwK zeSC)FL39Y4DB63#Q6=Xso@C+u>Gs^OsC?FeMb~=cd;9ttoZZ$LaYIa|);3i5=mtEk zyQFuE$P&RY&1cuDDfXiZv-x#-FT#oIUE522ycL-$Fnvo&8(T;|e*cVW@A96*ITjw{ zZbR`}KK7lU@EiB@N(v=DrXN|_{q`JX&td{~Ot0x~?eW1HN(`30Wyo(SREB@r&+fZ{ zElJp5(IEj|%q#g#%3^=Q%PyMc^^~N;e?d-*YVMBR=We!nAx+)A_u+l;7ahWaTY`lN zM^A}?#n-LCeF@8Deb2q|+dI{2mdr zC=T=Aq<`23R@AMVsHdYaLNAWSqTMkNim|Gz zYZGO+?mp+eE3Q%VuZ3O;aR>oEG(OB;SnouV5|YMbK9DwK!cgWQ`XBZ5z^Uopt>Y?xUKaX0Vb8e6-wYKz-kaQGtz5ZN&e z5t5xiR$86rq4%0+d*9jr={`y!OLs5`ltsoSJz|hgbc?zwb;9yZ&gHWNgxKfHa_SJH zq`Q9t9;eGvHxi$Y*W0jBc})3^nc?6dx5XjT<8I0iaoQDrD5_ll+CikWB@8<7R66~b z;PVfu&x_S?fiF!i{rJen`sgopEi2b4TUSRsc%#? zy@-E5zvL$}nqT*-BL}X77AE7%ZA2CVRk{@eR6~1c^4vD&aKZo3;<@thh??|Cfd#{! zBtRr;QO%_xAP>K|X74{xYVVT*-u5{fKuh<>qi7@dS_`@JD0Z+C^Q48)?V=Mec2Db> znWgGbcxFo-69=SNd08;uw4Nl?mGPHBe99fVxKepFPtUTOq5`bJ0RDe-<9Z0m_83gLxVqYq&XmJcNBuR=S~Z9L!O-{hBE9iWE~Bm824{`V zDOfG5hgZA>Ib(3bI}6&nl4}|SvvZqr%;Xn?9EB=)7?;L)cj48K>C{rhDvAcju2FDsn#@O+KMtLnV^yjY)%xCX zi414Fn0!r#L;YB`$lPWS#u>(GW|h^{+(6uoZ!{+_s_Hc_eZ(?9w61g-v@lRzhDaE+ zWhOFFiRVh8Bwyye^9lXIQ>#zpAZPR+8kQ6O2FYB2L7N@}oayUZ(bRN3P`M=($}X7c z@e(r5n@&IZP3leKHpU*#)d(B0px}gf5Zg4zUSf)UR;F=^2@tXAmZ$o zbY#06R#{a3qR#xNiu{3bc-1r|Qy!5a3nUxBy2;|0n265{X#7P>%W$2PP9wR5l7{%? zCgeJj8<2FyU4AquQsarxgez*kZepu_!;KVxrxtub*2;6o=3_&RrEKzbg8rGSp~l{! z=;Va3@uw_IsGLI2du3-_7wr`9reRdly92y6ReR)*0eA&f_k_;o9Xg&s_;t!(oARB%sBghocD(O`=ey zPAS&?{;m0be%Y?BuJG{2*w$#=0&9E)hB!5kx|`Nb0i40B&3z)gAQzj{vv_dtwFaTy z$5v>-V)HZiOk@xSlw9}qYcE9__zwycvCAJ{+r`ZuZ<;&{Q-yFazX|T9nGi~bS7cd_ zF$6}xM_a=8Lw$T=A49aRURJASFuN8nnBdM9qu;s-l3+)s&&xh#_%WtPh12ek<4OHJ zUddf6#*d^OO&0qHavZ6vSG=P%)b7NI1@QE7mZ}B%2K+h0d-MY$p?@bO7(br1{X$IB zqNU?LFC*Y|zyVq{|IWcl4#uIQM)Ap*{Z?C*kEswzyD~RPqe0?%h#G9YrdaS4l%j`Y z5&DKE-dvp?ofuWQ>VAI4gcKn#T{CXKqcPiCwQZ=v^zK2MlM&g9P$%pr7oNF4S93d) z-L^4J7!(iECn8q@`Dm`%-veJ*%phXIf3%z3m;q|PfpH0}w_JxYj>T9jHRF03Qsp&Z zB+%gXxfRUX>Ja8 z+<<>NX>S8rfkco{`V|(hrjTH*Coor8^jTcB>4_7T{E#_qs3(&$y0bjPkwBRVM*LrZ*}ehXR!V7)1(fUf1IXqrF?wIzZ7@iX>KE0 zUvsWB`zh+0)~uo+6EdKfy9oFk#%P}mq@(neNyk#TS`pXr+4DBR?!%0K9hX#kjF)Mu zTsfk1Z4b^W68-p3pf9KI8#h+CpjFzDp>@Tx5ZSN33O#wEBwi9y`z91nIJMmm{yR{c zPQc;eRNu(R;ib4W$n6|*s>^AavsV0HGTCa!@BVjSu1WGn(q9$eB8-YwRellGiaMlGD2cdq zGCWhV^XT|3g{;e?BkIT!_Mef+5UA7;FxNIVrj+2my$wKQC^Q}grCQs3uBNU>d}q<4 z$k;a)=9|%PD#9V^4cZ_CyKquaRyF}x^!MY>Wvt8998BZrCNhbf2-1~Tbijm2omy28e)rfQ!ngb+55twm(kC-a|W}hV@t|9n0j)cKnJ3lF5I9$ z``OOt9H7SZ$})=Q?%N9U+ga}me{EK*9STaix~R1YyCSR5m0?}U_u_Hvbe@WSRXt-( zB_2VKR))ZLzrDzlxEB4(pa1^`!k+af2n5a|%2=JE`wVC)LVh7D;I?|s!>B}ck&m!c RZ|o89F*UL - - - - MHC-WLED ESP32-P4 shield (V2 / v1.0) — terminal pinout - read from the board silkscreen · GPIO numbers are the ESP32-P4 pins - - - 12x outputs — level-shifted, single-ended (LED data) - - - - - - - - 21 - 20 - 25 - 5 - 7I²C SCL·SDA - 23 - 8 - - - - - - - - 27 - 3 - 22 - 24 - 4 - GND - - - amber outline = same GPIO also wired to an RS-485 channel (below) - - - 4x RS-485 — each channel = 2 screw terminals (A + B), a differential transceiver pair, NOT a bare GPIO - - - - - GPIO 4 - A - B - - - GPIO 22 - A - B - - - GPIO 24 - A - B - - - GPIO 3 - A - B - - - - - - - loopback: A4 → A3 (amber) · B4 → B3 (blue) — straight A→A, B→B, never crossed - - - 4x in/out — diode + ~16 kHz low-pass (button inputs), NOT for a WS2812 loopback - - - 46 - 47 - 2 - 48 - GND - In5V - Out3V3 - - - - Ethernet (RMII, ext clock) - - - MDC 31 · MDIO 52 · RST 51 · CLK 50 (ext-in) · PHYaddr 1 - ethType 2 (IP101) · clock external-in - - - - Line-In audio (PCM1808 → I²S) - - - 32SCK - 26WS - 33SD - 36MCLK - - - - - Loopback test (RS-485 path, per shield builder) - Tx = GPIO 4 (A-4-B) → Rx = GPIO 3 (A-3-B). Two cables: - A4→A3 and B4→B3 (straight, never crossed). No switch — - GPIO 3's direction is firmware-set. Through 2 transceivers, - so a fail is a transceiver-bandwidth limit, not firmware. - diff --git a/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-gpio3-switchable-schematic.png b/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-gpio3-switchable-schematic.png new file mode 100644 index 0000000000000000000000000000000000000000..f6a3dc93bc655274675bf7dea208d38fad4a4c01 GIT binary patch literal 63458 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 literal 0 HcmV?d00001 diff --git a/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-loopback-wiring.png b/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-loopback-wiring.png new file mode 100644 index 0000000000000000000000000000000000000000..1882183627978c6c6982e355e846d1bb537c3bc6 GIT binary patch literal 385352 zcmagFQ*>p4v-KP7*zQ;zb!=N5+qP{dJGSjk(&=<;+qP}nJGy<&z280Kd@uipHP#sQ zylT~N&YBgeC@+Zwj|UG128JZ{Q%o5Q3~=%9S%!u9SDDN5>i`2I0h1CFR`txe=+vm7 z&`A63@y@-R{g9VAAV#L>?VPGI1i@C*++(1UNM!V4J50 z2Lfb^w2Oq7RXyC&jcO4`jj=nYO}#x>tDldz_G1;XzPjBVt0P*D>%I$VXnx65AvVih zbdq01I(+eVdRzxBRHu%bc97)C58IvoZd*y}#a6Nm&PhcA`dqgQ!pi6J;R0G^d13v} zLm8oa1z#<`_+Woqr~`K%AW@9Q7b;1<5&wYhJg5&MwAeg=P? zTtf>t))4_{#}7#?RkMX_T4EX~sY-))_Nb174c*MxVSk+42rHH^1{cf=ABn2XJktJ+ zHc1Le-U#KcW z7QmtNULBS1?mIFO5g{T_Lmy;?N;l025N?h6Y-|92J`R7~ZleGrZ8(8DCB*NJ{Ymco z*Xa$Q&2|r%-r1sX;Lbsr$xlD0-u9_NQLf+05;zRig^M3M;ex%rn=u+uVX6+Q8lpoi zD{k*Avm~AmyKg{4OA=zhdKfg&(8!7zHmrFY4Zzs-a!=xU{ehB!^n0+*qkTj|ARNJd zn;RQ&$$^}gKb*=-h+FHFY0Hofa&>Fq<+3U07K8;sqnbL;bvw$IL`D5bcT(VG;kb>O zgW(2iDJ03BF5`(&3o|iq4-Kw|ia}?|Gb_=4*V#>(G~a7$RISEjO7AaWt=IyL&MaIO z1e@NUsJA9d^;(fkG z0mch<9%N1#aJ2 zg>TlopWUu~G#Zs3yC$b5Ct!q2l;MEu%{P@Vpu=e48i#4*>*Kc2&_j}poSgf*Stmi} zvE#{<=kaptQ}W7p68h!cDp!WfkEG_VuxS>ZY~N=>!l$$6Lg~9om~*;o#l~ zBarZO>TkfWL}Cb?_uEmwMn#x*2dvxnHh$j^n+2Pd?-XWE>dP}?_2=)-CH^OKxbwuT zu4mey=&FtA8R5*93h5%N=Gh?zJuqX(%P|VZ$n|DQPo}Bzr5n+=Lt4ve1JIZTaOY}2 zkmkvsh&p`X^x|C>^7P`0p9n1&R)gEm4 zm6t2bBp6yfbKP-2PO>sT^x|@Y>`V4}vL7E@pr4+v5qh_yk(=a;Dym4TP1c2zY>%IJUfx|5%GE3@n0 zrvXS1;D;ECcuCY`AAIJDlcOrSp91bJ$vg^$Mfe*YF`fu+U+}KUZcy2DAqKSig!e zThkB&<5a1B-}TuF@%MWDPS%Ck@Q^jMLum9_=rwIn!MgkqE8a>-R?z`(t`9IPeT$^hR$si8+8ct@ zPP<)lSn{)q8pkyy5~Pd$#j;$d&nLQs*OVEPS z4>U7_SL97(VMSeTE0--!^6e(lY|S(EBaC-yVhYanMtH@Wq@mi*mr}=RJKBwt7xq@Hfs2!kt4MlSx0Xccg z)EUo6=6)%dR2(8?#_LJvbFCSy%lYz2o#Q1)t=Mh2m*ge5`{Pac=2mBis@edWI%6E7 z5cgy~Zq0}T-Yezd467&h8~{}`!vbYr61qGmTWRR<=Z4RrYG#(OwV^$2+1&~i7G-vzxMC_6ejmB zV0i{FKi&_f{O(Fy;=XaWJg|Otl3=`NDK$Nk~Wn3*;sotU*njHanol^O0Ts zoYc`7o)R4uzeIBSaIRIdB^7$%Te#W70lnZ%hxw68^+C;a9DJ(VL8DdCIJ2&gY>|92 zYMb8hv&W+_d(o-*Ftar5!?lhbknwzybOIjRemLgwDH+svJL)7fW!O2?EdrIlvGqsm ziy=LKU!rM-yFv&?gl6M7?UE!5Q?v>42wNi;E&BDe&{D~8)ttS+ zal8mW=v3z%vtn*U#f;k71a-(~Xw}kbXJTR*p~K?~!qY&GpbG-%oNY2w9oI2dEPI;9VXb+L|AQ>R9%Q@^Xr%>c7f8zjW3af%*Bd!{zFR}+i$}jL| zh}N*WJxWHmMNxa7I(Y$;7`KqkWOg1_w7TL*&yAD~<)XizOfE`#*#$cGw#gl@&JC-p z7Z7XtD1!DCHkVr9L7_PCD}hSA?|m|bMg1Z5s>E!}?Z8Z;#TDwDvY=1jC7`rl1B@)^PYKcjU%O^E@5ynqdYvZ^(%Kc%|ou4E;%GKhP0_QuhOh!t!NS2l=h(ZJ*z{VL~zlM}@9^_*r)Yj30`43eg=R6I+`40yB>GD)SL6mC2jLz?I zf(FG+ZN1Pe2)Q6MPl6ZM>IQ-SC*8dwmh1%pJLy=KA>Q`wZPU?Tv0Q0*_R15a-~XqvN>f5$+QF?0z0;C zY?Mv1o+7WI;J!Kfo+;xH%F#(yKvbw~uJm$&mqo6WV8reyhg`&T))|&edDPNxjnGV2 z=s+;nB5o7C<12*OIC^KEb8mMbOL(|q#&&l=Z%-9@Y@Mq0FMLN9_!)8?{%`Cg1Uw9D zj&dl#xHWJ6uA*MkiaNcD)8pl9vhfGsmne;l3;5)tBxJKX=*q1z&dV!-Vu;YLoO?`M zB+F1QJXyp1LbI2&MifrQ055h9#a%kXC%Bmm(UCI?yr`DRY=O6;do2U^UnUD7!yY#P zO5ttGrAXNNmCiGe>T_m_d|NL5WLQpIG-KDRoQAuMG91OUNiTT0i*|Dy5t@S`A>^B& zch=$U*pIU_*>_dXH1;n0!<30fo;z5%`FA}~TU;eg5G%mY3bN2F@)62J>r4@0pu6bc zy<|j9>sQXVn;Tet$gW$Y36_^WmuYC>LX`H;W5JJY;Led;g&0!{{wCFWI9|D`*`ung z;cBA=in0YVPOJRIkL3z`j~eO9n~PRD1}?q`b{yzo=JB$;UIc|swR?in67Pe~@_PAU zD+af%oot0T7kHu$;%g$5T!C1GJDz2(ajQhyuBFps-Qxb&6J*(>v7|U;t(1DwTOhmB zCyv0jT1;E1wUPB{Jxjbas8Q!xb0U^kR!@$=@pJBC5I3&2j!fc&`&eQ1WZ+p^tA~RM z(0IR1**$4(VrVcOv zZu~kI;{0ejTXEEBiLx6}@7)uKA&)~56J96NjVPHyOIm4fi;R(C=uv?s>_=6Zh@Y*_ zc+#$(!&&DS`M;Vj@dM4~zsdH$0rxjO`P_F>E5%+kQ+q3uS1yKV`+EcC%@Fu0p6 zXj$`AMhu{#a|@uMlRGmkr9t4W%!AE)?+O{YP z-!}lv6U1q&Gp^^vVoIeJ6qr}=Tt}Bf*@#RUoRBa`@ltE2e=>?|sz z2mWC|M+*wBwGCqFkG#ni8XnbCa{5+1p}@o;d)2o*35pFboWE64Y(FQ65E?L27T2S- zHh}6#H6<%?_W0+|Y2O6~)?IJ+#HSS+g+ZM4iApQg_`r(N3kNh+M$=dXZp8u^ggwAd zGO>J8+me$gDb8g@g!mG7J#;ue#}1y(o%UN@r#77Zy=hf?9ci+0XF0D_1yyF%Ul|OU&W|{fY<=XmFcae)96Qm;Y5Q zT+@NrCJQ2Mj^2~!E2;;3ukBL<<;1iwUX9#V+(!0&Q+k9I59WE0MU+4s(Of18y*7zh^YDx{4>k9HT1l643xgmr-3Kf+;!wu zr}Rrt6~*QQ{%Pl%8rFr!_3V1>*k^5|MSWgmB5VoyKTOAN3WqPgV|RlC!uEYGZPJRX zqybfq;?E6wxFtU~8usY|2V|pRb5Q{$lK@NPFlR2qXWv?|;Z;dnFKIeR>Q;d;Fo#1l{D)8R>Lj zk)~nas!)LHCw66Zip;ce;2!{%C)s%Kf-t z*Kl`4`%Mb8QI6B>Zp|IpiH3kg|JQzzscLEzo1g5oI`-#8zV zd$=+$+AU0~?s`I#HxMc9;)hI;xk*z*KJ1b~4hMvsjI8|WKNA4Egp}Kxo=#HY`;)bJ_Qk0qtcssKnIvqAKp)ffiY^)-eU_v zy@`Bh`$@WNbG{`8W(7Bh{vmieOV^ZN_p6Nq-W`iUvV|(~C~Lti>3hAQG4~2$uJU6r zU5bT){UHeUh`vcMG{1&l3$;BME16Q|yXU#M7Vv}=)QoRIS+Tndt77kmGa#;#ldz88 z-=7ql#)o6NPy+5O5mRQ?l~hc$hnb0zA8|etAdp=uRrmJ@fBE(xt1UF#KbMw#!{ z_~u0v1<+dv={eux2*(=l4`O}EOn+_heaGc9g?aH;&hHuTmroiJK~vc15t_9Qy1+7X z@jM~s1L!$L^GxqVRnu=av-kaS}XI0DnA+kN1%5GgytARX32 zm{|{&YIPlEC_A!;7tVI5pQ_2duGmY;mBaDHQFls@^?Vju(SV5Ua9Ad)9^x_XAD8$0 z#IrZ^$}JbE`E?+itR`xF@|u0e+sOJ6$IjR^Ud+vxIF1UG%{;HkK`vCIk2ons_> zQCi-4%+6D8!=>86|Cm86LM zzV-349}m@gZ{S4=>;K@F;Lq3zzvST#-Exs`(8C-aPb7~1@Hm-hR5fSn;Dlt!u)4CK zGR=sIiyI(TQZc{lBS ze0dul$U_($zm1gRd58C7x3hWIs^cH_H>pd~ShEAL@Rla0dl_$Q!v%=}9>kFLen$bI zQsEkXC@+_%P83CYJ#FNvJ^YVB7a?!t3qec(EroaT96x)%jz+oh_y%9p1}E6}I}m%| zM!QEph+UHItZYTSw3)HgV6vEs4$iLXc&)K&DYK+OyaDi zMV+%!T+y9JVrHKs4+a&<+8Ej+Wf->KYuHJ<$HR}>hi5NqXiVllNYw@x#hg^Ip4)jBm3b8b^scYNw@0WAen75fiVXnqQrSyv1|V{4t=Z_ z2{>gya%RmYv&C)UriG7KL{C;obd*EZQS+>4^S9EDBb)l((_csNOVqMX~K-oKi);8O;GubpQ zu+C&S92JA%qLysN6oK}yJnM=y#wOEr9y3>9sZMLm(CZMsr*A%gI4;le3!TiNp~5#DN*ckDYk^Wd@+w_^d1p*$CO1o5t16 zE+!`#)9n30_!~(Czm!T<$17v6f->O+ME7;Y05d6blq087J^F2FcYI7IRs7ztaW7Ap ztk@HANV+%bXm?W`T~TPM1xL{f&s%u5XCL(+khv&FaUhQ0(Z>(w$FrmZA2bQCzt>Uv zzvT_$#8J7yS0%|x6QtwX!}mWKoYP=SA6EwN;;4MjP&JKSbCTsUEmI2%s;CdMS=X5s z`N%+TD3W2$?niptG6=NH4kVkdBJmuztnm~^hM?PTcmM$nGOz{rJh0)bR}iESY?zyoR>6=rU8GxXCdAH~Y#7^h@6bgE81LA$53+MI zpGR${ByOSTwO?SC?Hfp%LU$dbC_$I2L;jr94aG>g8a&iQR_Ch`BA@D4ES(j-mZ#1; zQrr{sNc>U7!kfo`v>z`(0BGj2G4v;@scQK=9En?!>W$PWmZ$AE+bHo5xx%=z z@${U5%qccwm@)yJ)R-RLwMp)1l&hi0U{}r~@Qe1aNG@v?Vu$W8HYgMZ+AoqcD|i@b zxFPX4Mh!&}Mm1jWNX{OrxlS7s|LBm@SN&^dp5NJ^1o(nR_s3>UHLw~v4qJ2ZwVB{$>cQ$V6!EU znagA;Lu-_;uDAs_MKN!O;F*0|oa^CzM8;if5KlTE;h3Y!h*^q=~0Llo#on zlr`ut&=`U{qOH8;&Y{UTg~JlCI|JS_EQ7j0`;h@|vP1z4V9=wKUf{9IBy*{9mR?fzO0zyM4OKKr6>cu{dJhC&7Y_SgVt zoXPKgF-G-$xE-G0t>X|&vhzgjUEwl3BK~-M4mONMoCuERJ5i$EHsi3yGJT9I8X1B_ zF-d$lr6D0pR_U>Y2gp1Tg{!%t9%BPK8w$VrB9Hz2U?=*cA->8Ijq#XSpW}@RhIfIbDpfS3LeG&OZ^$ z=mT|^pHZ>Nr~$Rq9i)e}z3iN$Q1UW9Pd~7klfg)3{5{inHP<1^=h;X8WE%OYbE#eP zXrE5j%ybg0MUNXPhpHF@+w2e}TE=BgoT%gpP=F|cVh-AxA_xwNftx7==d{g{y+26T z(Y3mQ{MpuKm6)PpDX-p<<}w=qXr&Vf?g zcHU1rZ;cz`(*9=(4kCwquSfj0*T(*Idit(TyF9H!W_*2JRJecVsQ&?l=?v~xr$7t-P7BVX#~5_(sec1{Sw8^(b!0czEVQw$?k|B8)?#<; z^Ij;U06yS(%Z;;ctk5==8*}~OsSIO;v~_s3)eL3SUDx|BOl{&nb^JsoPqB*m2B_>w zV{r}1@gDrhwltG=dCP6FXz=WtW|#oESJ)>E@NUiR0gvaeC|^dH_QBRvbCd$8-N1Q2 z@Kk68L*|@s9Dl=PYso$NW2+eRqe;9i*-K~bFP=eZUJjI8rklPVYeD$=R zxnfFR60!7;J+A^r?zQ|hkT4R`oRj?<#|_8!2j?~%Pz26*Ax>|l(P3LaH+=i#nh&0m zDi>Vm?ek5O-p?EFVKa`f9ccJ`MMzDPSf#`10No2q+G9(s*eQb1ytB$k8Y$eDX5uPh zzgV6J?wouwzFXu0-P_0Kjuih7-G3-m855`RI_p}KM{+^v#>xWbjZOg6UyWgO<^~`%a@I#z0PP=7$N;_ zcMSmbG~6p}E0wHL*(iLFw%p1iL@YGVux(_1ELEbOQ0q@NL(%1Ypml$K&ORO8GRoPK z?P_1m#uYv?8IZUNPAwii___nJ6)Ip%g5e8-=W0tC9@#KByJzq`Mc>k-z~(kW(ekdp=U z-tk0U#kCBKQ>?bn=e(C}MCuhBC5bt9z!RmF5#t^)gU^6>~TuE`pB_?Z1+d2Qa*iTM1^&{ znMK`4S(Sys{}!JA_fnLaD&G<+-YL3r+f>#H(#rNY@hmQ=;x^%R7_EaK|rV7~IhfbQ9fz3>!1Fr1F#6iQe60eL&k1?9U8+YJ^XWaUim6UAX3_&kCkgX}kR9e($2euj$>l>rP_8_FFbF zbZ;aESf1b~YCB#9QlfbnITO@z(=q3yzUC6Fr)C0H=TyrRs(g>TvSZQ2OhoNjF~(e(s@6E1Wxq|m|@4|4Q%yF5t(0n$_9aO(05|Jxhb+T|t^ zSGRc4&L9?nij$pe(C@i~oXQe|oLT0F-xwZ+2Da-0dx`SFY>b4sP$Ghyj4sr^+`}@` z5p{gwDR;1_^_mkE{>=+XvG6S`kmYn zKFzSpTb(*vPoBUYH6h;ce0&sus7iabtL|I1Oy$F6_@d)h#nEfr?p`(Qdw#d5kiRO} zb4bn!{3@0;E{L!tSc#Rqw}lzU=6f8N7p|#`ah98yAU9cm4eM!zOTIs0Z$-SL8?Xtt z@2Ml{^L3v!d9jJjI=1MlVGBp78xrA|df`kK&DSfrznPxucsdo$*&t7(S2pK&<>l&7 z8jMzv$BQOMi7cX;GP_NkFEGg|mA$#w4EP;JBojx#4dky#bKAo7 zYG1mi(Vb=OdbQ5lZ(YGez`WEw=l)`d!o~is^F~y;V*Qemp}Q)FPyy>g;9)=S{EJ@?NuXPh`;UO-Np;bEXK?3fHqx`2&F~Fm9ufw zp7F5rjSc3tdlV@k){(Bt3-GJ>Pf~FsI9>ox41==@rWe?^#p3$qBC`Sir@#m!Rulg6 z2o<(XFS0+IC1GJlL(=vDb2B5*#hgRbIBceLrCx*yv2MvaCEti6Lru5{IlNX`jC)=bR3<|MWO+Wx@4wu^xSodo|0zf*$KlfLlPE&y& z=ETDnAFLEFvVf*fhS%LF_Hma~C|l;f#@+WqE5{#ro~NMS4Lny3bYhqYwppu3=}Iy1 z-z^uuDgC-L_|2iLt+Pu5W|H%}tX$W!OTJmcF8{o$!q=5u_eF_@SCX2w`#{p#A^y3$jzccQm8yyaquSZuirJFX@d=w~+B3wGg_LuV ztHkkgII>q*m^2@9HN@eOw6!IMw>hGcIJ9@7G&IzG9VB)Sp}5ogxKg$ruNNfdp6M&I zOh*)CKgGj%@3r-$G8n?mFfUg@lXN^uH?d7B5s@8!woq{(o(?3EGKibo~) z=$6M!SgAmiQaD(RAHOmeZP*CR>$w_m6soM`HE1xGJEG_hEGM#yCh4{ncn)&vP3e|5 zRKV&z=O`}l2#0fWF{oy%8TAGs%P(&}H37Br#&)RJ*W~hy4zRo)J4O%xELxb}%;jw{ zWUI#x4@ROgEbsNPEI_;ZZHJ(W?rNaol`@>E@V0&<^>?Ck5LVvNA9S(}C-3ZY zsA5e58fSSS736(ocPqbK&+r@a)C#IbI+;@CI!5S4OPlla_{Ikl#H2B}Lmh6H+< ztQp}AZvx~c@lb_npn0|W-#n_Po}L2E*S^l%vtRd}WVBb?7bJIq38l)gL{H%-f9hni zE>eGZUHTF^6PcS}#PDUu`=}u06K4~vO(*4}LJ%ULP`x19cyfVbT|q%^VKUO=6F_f3 z{@F;Ds{3U(4=3u+H$s@0mIb~Cs>_1??p%`S0QzAOq74yt!ew{Le2*JU?5feeyh$8*(qsA-7rBSubBt z#!4-F{WoBY!+*fF_aTAmS%PCIV?(RvV0ei+c--&GU4PXVIsVN>nl&rbc3uSzV?`G^ zr%B{yIV7r`;!mc5>=`Hx1={GgK_&2^^iMWy3Ntam+8FiIFL zomGz~YA1*FzlC?~RmD-$C=2|)(TX9v{D|L2eAJ12zNDbxCE$lA_fZ(GaBuiM@d|Zv zvIqwerN70~6<_m&+=B=O_`K!E2uo>S=)-ZQ=J1mSlS%hLOKA}O+aRT6B;BqQc-6q0 zhRQ$|kapfrbwNRAArK7eoyl-F8wsMe^Q1#7zSbE4^~}@ z>+7R@Itx5Y*5vCZH@w|^i6MW2irWOA%L?i6=iqT30J=j?0DM$N%Kx&nvf!6&^^ zucO7|a_#u`Mh*FMj$EDgd`pX^w^Vqp>oPE)s^ZiJNMUw_1Xu#CjoVHZ*UOu4_xqCG+I! zWXxqwJA4|g{}XRMZ(jRzMhJX~Gxfin+UZyYHogsA2mJfyK2;Ki3_fzJp?VXGdS1t9 zNoKYJj{jMmZLA?PUthSg$373Yr4?zhw42rPERb}PQet3%gYCrOLz zZpW|)7mWC&)sZ?;=?GRuWu@0vj0g|6x|kkg3q9!ZZeepR>-Qe07{PMb6##&$x|r~#h2?;vC%kmH#k?ezBsc~ z@J7x#`80aI@8rC-i+poQ_)~?PUuVZn4d7Wdzt6d%T~Tu?RE+}1=;vsCoA*}W-hgQu ze09!veW#Oz?4JmKc4>cY*EJm4eP!aAF=KE~>n|{Ec>_W7P~A3n8rZuJ@q9Ro<)4kS zT=%{+4;ZbChi@Iti8i(+;zYWK6`8weE!NBU?A>0dJ_v4qG$+)yB&vLYN{44}IIRd? zpRY32bsTMZKCcUI6*P{y^@#4a!xy)XOeA?V6`^gBuy4^^W0%4J?}RC5{vR>-tp6 z-K<#IfQ0uy+$Po>)srVLjw!7!Gj3H)eY#xndM=i6(NsQe8~=5V zjTG$mm^>+}k3K!76q^G{?gt69nlsbE_OPZG1$d+%R4R+D}iECT-{t6qQgUPCG6#pPl&_cZf;l~_2b;^liY>Vi?- zzvBcpE}Vmj(W=dmhmuvf+%1ffw7da;Y`CpddHy`G*vHsF!%Wnj$oZN~Jt`9Kr(gx( zP7#U#Eb#VHQ?z3NhQ!niEob84q2c&C%PA1z^U@Ws_Cb%Yb%#V}(x%m9f#K1PAE+6Z zu3NKc?_MR2q4NUGP3&clIy!|)Gme3t?C?O}CSYDy%k7%~&MqRn(!TU$bMgM~ zZ*n}nug+rysf;u-cwbdX30tC7#mcZ$Z7fY^Ar3xcI%L zm=Hkcy+T~LFzR>U0cgw1x1?`H&}b#sRU`9q+C6$pTs#4M-$xG@w8yA!vh7;zx<8(H z>B#QhLmB;OVB-jSF=I|orMflX&m=^g&7i#O8x;jZji;z$u_Eb{dKJJ*3x#E`P^DJG z!z4T0S8NT*0u_HUC@~Y*gOTLqbX;bB=LIdl2AsJcpyaP@E2Fe#C*@p)K}f@%70;LW zgvsB>8zuO1cQ#M1pN()hL8>E9%-QFL({7r%=@&mQE;IdXvi7~XWx+jm&3&A+zK@)z zz@QasmnD_LTCu>-Iq0MLNoGW6M%fpNU>MeH2dT{49kU!rigyoRq_01WFf?FS^UUs) zT?+lPo0#7*<4_c?`TCcIfQ?CN>2*oy#RT2X3eUDtTaMPgt*Y5lj5QO|(iw;>tl&&~ z&`1C1ex%USiO7L&nL+PhJ&O!mgQsJeXK@bJ&!kOcgy zGgG!i?L$~f?r5Pg0dB3 zUYd*0QFP%8aPsNgJ~A;Uq7F7mAuRze4X$SDKkY0qP#o=4=&a0M3(%G{Tn6D;U-}rB$reSZ4XOhxfy>I0G805X0pjR#h$O=MTUBNJk82o3%-X=<-__Qx#ic zSb2E=m|D@|<)cy@AQjr2wmzv?2usbhO#djST~GhtA)i&^{~aJ0>wKEm09tzEk!%Es z8ajua;Jy^q?*vd*^(H?(0fbsUg-LK(les=7X#Wk+9TLYbOq#vUaCdSpu#w|FDvRKq zmrbEKg`758*uU(KVzE4#{0vE-1N91k-X_AG#J^^NLffz1T^IlyDFMNUoBq7k+83(l zc@D4RJU!u>zR`?uWKY3!SP18i!g7CFe}-e)uu4rOY<&WmWlu? ziNA+El+l-t;HI^TY4~QkpWQfa;mhHmNGIMWvy06bV9% zsdrIBp>Q)_SQAzPx0ge*7_UhVSskm2^^u0HR)&fZWK! zvo69}uidx5NC-h3wWj@Pm+)vu7*o;yevL<>k0Up;1bNdI`M3Yk$1`e2@FGRAI1cv> z63T;*3&tI{>QNsZC5h|?;Infov9+>RRihlPy@mAi+v*~P^@Tk4ogRx|3?GhGlrCE4 zH1@zt*3=WXszc%<9~+Px2SKKVMuU>6q-1=RBI(b@6-2TnhZg=FY7!L*%vX$1w*AkQ zZ%CLRo_x%_s}$uxXU3l|99WS2u(@`fCkV}%~F?t?0Iu?A`UI&#Y!yffYn zr82W<7RaEI+!HSEq<38^h|+uzdA?JEuSUY(?RkhJ%)}pBf5ij-b%5}&t)mOU{LMM` z!uu)y5?hMs#{tSw_3k=pSaE>KjLt91gO$c?!X3#uu9SRD5rw3Y1Rq2y;^q>$vD$oH z@1m`n4zlFpR%5&Va<0V)J%1~2WyYGSt{n^Vv|K9_l$uO=8Kj*UE;3$ znwh4y5#ujvrc^d}Cqq3wa2$_M3{CH&h*~+9?`Xu=JiAhoZ^;dahnjETzgRh}@ZWN; z-`!9z*4T*v9^0XCIB!ou)}JS$EA|?+LIu1G^eKBwcCx*iB~o=M{02SLiL@k-1WtQV zvKA!B$4j5)d7{XTYqg56w{>};yO=qe)W)l+(yvA8KgR}H`i^I|(IJd|xHiqY=0)$X zOK`u;uM($DlVZEpqs=y9JWa>7}S8x6fM7A3TUJNOD zF^rf+Jiqlg|6NV0)s~GNohbFq4;b}z(c>mfHXTo@ykt9#%@IYvOj0eXUwj(7%0l&k zOLot6@8Zs?jykQXU!eyl>*NprY^muh40f^A9w;7!<&^W(eD4p3Vbb}bSCsEkblAyg zrgndM)0?h@;>TIqQ%OToMA5W>kA$*$?M$|~A}?F1eau(ku^q79-*gz6qg?SDF-e1} z%F8UiAn*~JhE(O-6)`f9EOsdy%arby;0V3jTS`$GKBDn3?#KJ&q0<_2+}86(@N;u* zZpK1dQaW26)iu@J;bAQ|SDhn} z_+7kgz?FaGt|Q>1Jlva@2)T4f@AEWk%hd%bXS0@vmJQ%p8V>(0Tg}dg7AnRwGM3nc zFarNe9mA>S>GLq*7w#tDfXgUay^k3VwT@Q;AIc;1_z%1?q_(%H0QYW&+$ewL`-NBo z_2r)n<@nKz|HPR&zMRYN5~1dKp!lsl@bgW}(_jN1Cv@*uU3YyN zz=8p@-wwJ^UoMw-ha{S``wv0jHN)M$myaY|jyH;^bQp8gkNZ4=pe>YO!(;n|A*yTe zwD+xcrq%ZQk=#6-+fg3{sNN?%FcIa4^m4U`K4jz5n`+<7P!i9h`)TOjbqmMC?)NJL z=w8l%V;dsQx3zK$;Leg=;Mgyo@@3{W{+T}@oAwP33pyHGO+FW@5M}9HigpoH=l9-; zcqUblM+3gWrZ0|n@or6lWZ3*-z0Hw3e4Tse=f3 z3%yB%70S=FEJ0Jj*ueV|tKAHL2K+yuzu= zT?wtGgX=?VONb9Ml5>kph!(U@!PqA2!q$;NvV*aUq}zup#4U}uO}~XiX>Nm3Nm+G8 zXEghBa$SjzaX{c7M^^T9oIH|LH^@O-F`@;lTChvafS{vbPktmi!DRi%wI;stwE+)a zxg3E3Zn;4^?KeW-=szj%Z8u~8Ckp^REI(o7n*jQOu7GvbCXT2%6rO4$DZKdAg`6RucLNGQ#Zoa4%Z8JJimM3$djlkgfFf&WC z!rnm+%i#Z_gqos~VTs)q(_#1%FN$nQVNaGXyevn0%` zp)3S>_E3T_wY4d(_I587f9s&-iYwxfL-OTQfGt}fE)7@_e&owMFH1X4Ng5A%{Ntj) zz>8quS>@S2|4uvCHKC#ba7z?l8j)PA8;9|3?o&&$bW!UL>(IW{z?_Aj)io@v2@>Zs zq)U2D%1-JkkT1u<ELavBWWmW^07Jy3>i%`8n+`4+C(hecir?ha`VgdmjBh@V8CR zNT?-1t*XuYi3zVb2EPBU^d$l@1pggU<&Bb8szd*ru2qo)?vyd|5djeD1Izy(!rrk- z6lmG9E!(zj?y`5;*k#+cZQHhO+qP}n)pb8~^tmry#L54#B3I^|W2TN5W}?BbW9l_HI0O?yFJEgY6S-a$K~ni29S%AhwXaBK#vwj$GNH5vS=lMM=)aOI2dvG!0( zFAAO*fvc1Z?jI?+8}At!4uz$*ckKtXa;r3t$o1!$DMN8)h&~1CA0J zHV#9Vml<-ewt*F@1(ItzwV$HPIEb&UabifCsEx~o_f3wN5Livf$LCbXmrPlbR$6S{ zGEM-99&I9wZ?67?yZ|nq-`|I0`NR(G5hA#Rzyp`ipztHkOdTNBc1Gq(N6Q22B8Jwa zOYXf=NP~-LjqV@;n!nQum`Jt!gU#V8OGeH2*J32v3|j+B5A^Qv+1BtO@CtQ^~?u=-pVxfs% z;O4$pzoHU_p6lAsnAWNLmx{d1SInuWA;3zqPbwt)UO6! zVvNqT$ftdeO45RyiO%(-=D#F+Hgi5$f0yzs$6kwfzC9!q;*e1=nEva?7FMO{=k3eo zat-5;Tp|P3ck|tM1JbwcWecvQ7BsXo;{$W~{2q0&U9@rN9QZR=noVJ-K`mGD1MVF1 zEA350SY+{h04CfrhW#ALekZlWzNe}9;lxA&4sm$Dgb}R%flIvGo8iF$Ihppt0V(2L z-Q;kKh?1QjZwCR3gz(6`hFE+yOmF)L;yPMtFLOl1|mWcag&1TXxeK&!`{j;$|#pu{~y zGF<^2a7r1&4HRhOiXfy|;skfNefFAJK~Uo$!Kx<5a^(#t}V4QR9wMq=8$o_>Y> zIXW_$ftF=1&8#)J85CR5rTTA%a#ZP(o8mf74(^h8$BZ^bP3SUFbJo5motG$tc?jSH z{~&F&n!aKRbVFe}wTwOaG2M#07NCd!=LW5wMcj|j$1e{N@RIp_di@3}l~cANU)S+` z3GeU1k!S2|&jew;lm3LIoq*P%9>1m!$Wu`R|Dr-wCau&haIfZlZ*6Oc#;#nL!g+dR zV()@%nz)q0*O`5^>7AQnP)0)@q;Nkd9L~Lo9g1#5;?3Z#Kdom++=J@9XBBz$R>=hgelK{=FIp z34sf;h6L;uUtbZzE+pWY=7vXHV|5P`hn;d#8*4yGMQv+i%__heF&M5~eQKTQ0UDlF zycn?=+6SG?o+DU1As%PcI?+bvXRtml?Bj$g@_1y_34F8Kyw!1Ifl4sq@tpSs6P>#z zMZb$`XJy42T?)gB2I|xP2miu~I=~7A=R&3Ray}q~WmLO&7etujf~jI0KrLIdy3o8b znHKV~hF8^Qjzh{8W;vd_!-dMMlZPa)DDS;gi!MrOM&iXbW3w;gPIg&)`TB@kUy`bu zXQCbTyRmHcU}Hw4_Pm{U(5Pc(Sf+0u zoUt=XLM3x`tl-^LGfxes3QUfz;sPzW>F&6hThVKj)Tr_CkAnoJJ6BH6Id8I}bP=3X- zspPcvwJR-IToHBgrTP&-#ssn@aTLzIT2eK-Mi;2_1FwD>Q`-RHMKn>g(FuA=GLPaT z;2n#$S~S;$yp(kegJ4}x&Nz1>!VpPy1FwD};Vd;x>4mgE3Y0F*6#L%+4;7hMGQOt9 z9pgvsyOR@#234Sb_sdg68ySg)XsEJyYP`Mb3lQ`ctDWn+TWE(}Ne!lcu0YnJOI6T| z{sCuU-WY_EZ;q*<rZMcTy0LF4x2S}#$nD@ zoRX&V%nSx!?M@ST+u6IhJ%UkV#{QR=ltmC&Vb&0Z2kO4I9LbGjll=6VJ`T$1&Xlm@ zQ1J=LW!*Y_HBuC<1B(n6lCm5}fw)-QGsJr&!A0hgkS6X3`|ck1u;QbLe=yL}Zp@BV z12(aFh*H`%i+~0Y0PJ6DGaalbOi-h z>ro+d)3^}MSN%d&Lz5Fs$l*pVofe$^lQo}eW?39iD&#H|(2g>d^D@zaA z6l;_Z;ID^3*!Om4qY_w^KU=zI8Nb!?s3)qEZD?xNgMp8IwqmdT8$ng^P@cX0!xNKj|Y3n7eo`<>&3u`|?Wn_pZ-CB=U?YQ+~vrvoJMy-7s}+Mf&VcR-#v0pzc)s-b$8 zH7Z3XXX&EE+p&U#&r}$J=uEteLF`pkDP{=llIyrmb=_W4Tc@g4?br%tM)7D@`232= zwQ{0FDs&($SK{}Rk)C!3QIRdPfMMUxWZV)W{aZ-t?F$5v;EHG}c1!4|7r3DEYWZhWwVk0k|ECw7S1mp2OImYaw~(@ut^zo z4lDhNP&IKn#U4v3H0~k6QIXv9d}&Jpmc7k$RCUC_upczW^n!JH?UjpGoCo)!`V7E; zGDXRC5F(K(DU{kA`pAfS@Jtt%N9;Y6Epy~n=R@sH`y64O#y`F z7#tOIy{Vz6%CY>tejkk!lA=E1C|Xg*=GDZlAACYW?PMV)Xz}(*c&2YixMy#bqoC68 z&U zZH^6Obq*=2ZhaT@IE+$fU_t5yN+bHVV-3?yhO-c{SNl;Qgt!RV>oBr*YU9}lGNF_8 zHhb1j{_$_+AH7kAgubE#K>tsULa4FLNE=Rv#Oo8?2h#uM@IQ!`{};B&20OaIq(zPUTnZp|XP*c^sPA{WtM_!$=viXT;nJZhx~ZMm zXx6?D#`!G>FbrqqHhQ@7TCrL`eq7Z6h^xx2wv)p3g%C zph123kiH9$9$paY^hAa@0T+KMV7+I*!^-wI)d4=QAd73S{Czgy1+;G;h+)*|UY)oR zY^%v6#3Y4>1tQ(r9_YJQmix{XVYBrOU5ptU{+=0u<{?fL|M%BSel2*s29C`NVAhZu zrZ_;Xo7ZwP%JJt|ufRC&x!D>zDI_kp5o?BzA(FqBxwwg`TZC4+l%@`Ahf z^%wdf0`GO@*y*0z%a?98pb#yH0Us;K?BVed#-W&BI@@Mfk62mqWu!gO z_|kP3B2}W@1jJ$*Wq$)UN+YYSP9&y)shI7bxofEB>)aZF>4P2R8G2zK!xp3cPY!994P>Is!-so;0$OZpuslA|*8h}opQhY^7XMEp)yWQ8+ zmQbMt<;H!1t+M)PxPDc!sJ7!s4R1j(-{wfnbf#ZpI(-OQB zs7k=mnjX?KeX=E?Muu! z&{NMeR>|_F@%}c<6;?JL1^mo*nspR<5yVkjhc$s`GChcG>(IiLdCCI0tO^%mPk2mZ z*~9ByYUbUvnVlr*&soC-lQ~|)8q|K^a6C9mpc{@GGO0St!0(nXOUa4 zB%e4?F!a9eiQZ21{}q+bcD-kexhwtGCz$z#z&^f7)7t&@aRcFBw!zH%dR~3@0c;_| zdMMS#2pv}lu`xPHR*j8$*QlkIF)uU_8tMe@h?;4cUl=yONo#SJzWH3%f*< z!#m|+)S+27V|Pff(9|;@(NpQNh8)O6m~?r-hVHI96*91vm)frnT7dT(R4ZP7x$rxQ zcwP+PO8=qY2!O%KC@XoQvvB$&2{EP{1li1_qsuM`TA1imQsz@DERJTbrip)Mo5$lB zL?B?)s0)zJ`o~)p^T!`mj7-qW-+EzC@t$Kx# zVOkatRa@N`+-Zlvndfd0`L`qI_4K?J;D3<7hpgkA@we$TsV_L#Bx~ih0Y#?Q(TZ21 zj{6w1%~h!)o2f59QNgjB@W5<*dd;y}p=Ncun~F~|w7QD?f? zu4s+;>pH?X(1m|txS_ExU96*|#O^{%RtTKTB)0+VB6^NV|YtjZPf78o5i%nz}B(e>1x%IEsTJV_dh^q3-51HUl&TifA3EAnu z@tAGe+_v_=ZtrP~wsVWL%>YKn<@Y)1zivweZcVgsJg*NP1Y(cZPYWCouE=egr7{NZ zq2zF?AZ*mZ*4M_fNc|ellOB+imzB*(deb58uf5XPP59cjg<^P-Kz_D&-UkRwW5?3c z2g}zUn0=ARZ3dnl-HoyOQ2djG)rd9hvZw;4Hx&<-%L@@BgDSZCP6k8T&U8Xf&<6(< z5U@n4O1>i7_>II0%;^leNzH(Um!)edquDv}f|3@HTg9b`T@1t{OKI+R3t_^4v^nYK zu8mc@1GUmcoL?%yH#vzO?2Y`z`}LF|Mc^J|TnXfUZgX3>znJ8!zdl^{bm5e3y598u zhxkLy+>X(5s`t!#O`hF>_qMb|F~Q}4sTd=B`-xr+S@yf_dfEOEusv>a`HeE=Ih~mC z+KUjlonZd8a_$o`oN-eVisne=rGs+O9L^maT0`rTcq%REwRD%{M~VSg;NRF3Kn3<4Z+uwgGDf|1tUkhAtI-vyr00Y~K;9d^^ zJ32v5d9PT%?o3xzg7qCm{CcvlGF%N=%tEQO7otZLdYhG;Lcb>5t0bk2kSX+es7dt3 zgIVm`>x$>CkK3(ziA9G?GX1rw85D&2o zcWF+C7-&55z)1t%=2%ywR9{5&(NoF^s4A8Yq^Uh-1);{S3I#AI;B5tOG&+p@xfy1~ zuH3H3Em(oDKUwn*7O}fULc9~czluMhfrqmj`W~P-;0)fOUVt$KlSroDo)5}8;{i^i zApkCu8nF#5PX9|*AUrCn@;2Dc2HZ13uG>o}YoHuKEi>Hm`A@Z88KwKeV1B)oU4Srm zh0RB1-xU=eCqM2e?DAxU=T%7=_wq{Wrs$7CU4Yy8Nw||Ta(HGfsUxo2_xtplJa?@Q zZC4?lgk-chsm|Je6T9hViUz1rZQf0hVdCwx9s1Zo=rkPgV{yGD`k+CCj*4Z^N^ z9$tQ&5h9}jfHcWn7^SHX;J3dCAim#!q2?yR8GZ@gj*_rixLLYiOD0mOh2Qg-sqLR_ zuNLxGNX3W<8GA1azNJgL{An5m5ogEf4(H(vsn97=IeS z*tohY0o#M~-y|3}V6?IbXkC@$Ff00nTU#eow(0>a=(Zxl(uH(crk}}&8Sp-ym#q8l zOO>-+c0Ng=(SMsq@H;*$9l5KUkUzvutAzQKx7nBT$pM6c|8xn*-)`RcMn=&Dk^;lU zf9>0L>9w;BrltssN7Y)p-E=x_^B-qjzI}+vqma~cBjl*^PSycHlJ(d^b6v5ogxCr{ zj}t3>LtigH13wrbF+Om*8&r^VX6dZ;LHM5bV*_31_Ap<3Ls!guU}9BJXDkx&wqd8n zPO!1631B6Xm!?bzNoGhN&s@1^EjPgh^dpflwNXTnr5H< zH|1+&{u$?F=cU46@~)_&VUhkji6Fr%on0bj1HFlIst-8%=*=-6j~|o@^%H|(3xA1h zCS}}&zUZ)AS~4h}SWL=T%&aT_(V+2MR!KB()>+XljHhk7DGfi<>eU}v8yn#$N1%>^ zii*fVHeqR?-?;i2w_UL6w)lL_!~5&bSVy+MWOic@shxNP2Bb`x3t7bVQe0G~!%MWBv^v^R`|Fo+uJG$!ekfb9KV-1phtIgAPI*fB}G>Vhatn zY9Vshzh6vp_zKrh>$~1+2Yfvk0W0M@ULWzy_@MK1?jTU>0gkhKlES#8Z|64TQ9}`t z!#tvz242^#{N%i38c$QaTu(JxcMgxIW2iW)m zww}`)#__0}wlA&~_jx-2Dmd^R1Pk_U`urRrs6#)+T)iTiOQT`WC*$i#85^6NOMK1w z9_xYl?Go&GAW2ZGNm6KGc$}U9Vb6Zgluvm~E6cvRsF3tq`|5}EKZhm)awd|l-xCbV zUJp$wu~B81HAv>Hv#cKQec<;!Z#Ul>nr=Y+b5|LSI%Kz-hCC5lcidj7^jYA=OC(nZ za$tY~MiCmRT+6H~*Y!BW%Ry#SQzEN|Biam(5Y1Kpe3?;yt>NZpPWocjb5~QV(4xBY zclzH5*_o@D`bK5YVYy^|Yo%Y*MHx9p zmus}Ea0sPVI*>n?pPYy?XNscQ;;??~Gi4df7R?vJcqZ=DrjwtE<#L$e$vrS>w|Ck| zZxd=d?~D;(;D4b9tBn?qf}+^r2xyj8GI!cfE4QM0y{w2pB>1;ziMd3xHazSh6IE7W zjz!G52aNoevTFZp5F{Ix^=<9~oCfs@1Id7ysdJz^@B9*nL&2jcBQIR|Zm5n_jC13) z4~4A8kP>gtBZI@XXj)AB)G8*r)fv2Y6LQ^Spc5We)x|ZA$4aWYLjnKsjkCbbkunOk z=SsSo&ere^udwD`-04|61j+!kz174=n&`l3t88B#ztj6KcwPh$6>aahS~s^$chhqgG~YSw~K?T*td(3jS|Q>SC&<9PwKHgb$1;VfQ+(3e!$Bn>gBZ z8@iPG^t|#gqVwZ9r}}k}+7wE}ZKet->X|Xc$Y?z%WT36m+Ce>z8k7V1pZ^R|jo%ym zf8kQUX;b4-HAT8tofuk;4Fnt*#+5Q&SY(6g+0u1aRnpRyv=FykF#Fd6a zw@hUdd4#R=w6yd4F+0onKF4PSuLV6XH{gA@4DqozTaqiA8Ek#MH1u@uygAmSmx&>@ z+g?a`!J;>u=WVYtvl=!*n8+x~5X~U5#L@_-qgk!?d{<}In!?K95Otv|)=lB&YQ)ov zrtit7NvyHVDRkN}{y9GoV$RvnA{|Z@W9Wyb_2f$*hv>R6ueS!O3!hcYyKB!^;D-qZ zoa;?Y)|)=xIbY}$L(;ZfJKqm{(Ega!WICqPJ=lw^jSryR|}bRt%-DERQ29pwu~@4}ro2@O@Bru91`P{YYA!j6(I2A5Z78NQCB5+XsY%jo5VG*_7{q`?_co@J};Z+ zT2$H+3H6umV?|CD>=on-JFe|T=Sh{gE6?YZ6Q8alWUT$6rqvOYy@7HP*HpfhG#g`P z&ir?1sAZD1@N z5>rxSwpnwG!L-O1xH~tJ1L4oM1G?6cIb>kuijvU$YrF?|O+}VG3{q1PY=|hIIJv`$ zMV(J|e`9sU>iK=%*@O*~=m^M9b&UKy0hu){a{bBJj`1}}E!&K|`_fhvHFX&$)v?co*xchoT3INot^Px z8HpM90SiVL)3%3kOKgW%b}!Ri0=8#Z$+4=t5#bj})^i}*aw0Y-y{s`2d>?Z0Vi5)ieA;=+}3L*7OTrxLS6IH1?r}BP9vaNru9=RjiiL+>|G&aV)vZR#-bHLl15h@SC z;Q!TdFjnFX$aF+)oy~BbqVsBw(0RM@o3)0!A;OK``foiDO{^tcbmw!k{)C>b+e_mY z3j%I%yDuy8-;Mdc{srkzDH!6FEB0zAFWE7Vf>(vT4+9)hI^b}C=srGt9>E1{Unu!| zBqMTpl~d%yU$z6q&vd+A=(|Xp6{p)|zJ-y1zl8AWxLF~I7f|VNzjv8qa@ElQj{hwK zo=i>xE?3PTJpSH8aYyNEf@YwaOt@pObrD6l+=5OwGREScBWW8sGRmcAO+V7^@!n!1 zB!T`)xEaWH4_dPSCd#a^k=eYB?fE^oLJzTQI`#5^Kd|8H2+=er%5wVdG`l`>YTac4 zkET(x&~1}iJA3w_m&wi&=*-Rww0wH(l==+|8%jvB^~2=YP??9@^Kng10cTUKQLa%M z=xVS?b0rdFf%JPK#W>##g+UgoNI1Vh8m?^YnxLd*Ef!?QmPAD2NVEf!O4eXXwq1*d zzsKG^OiCrbsXi0c<{#F0hfLHUbY6NLBSB@!%@EOjL?*HA5tc|;8Ks`%*nBNI3sQ3S$)-uKPy=Y0q(>h%!Mn zKo^|OCFu1$U2F7oeD=Nu3m2GdeC#~KsG(ascDG#yh zDEc#D>=nds@>)XCn5QEcT!N}9wihUUyNuUVv-xdwy?@5q!8$~`#`FYErJd_=;L*?> z1zubt_r46d@I{y#T;u#n@A7eSp0mb)i7pm#MA|z*yPEUe zzn;XR!KR6V-;wax!Q7zICRd1HpQrT5v|L`Sv(6d%odtA}t!-lgZRiCQj^~);uIQFU;e+ z=8slXW}%Z)sJ6Kx5f&8`_LPQfmC;IUo6qO@aJw%!`KFDLT=0fA4(O)aMsGa{OFzJG z%~Oh_9E2jDvM3p+$J^sZW`dQ0xN(d;CZg$oT)ftDSmJgGFPl&OSh5e6Y%6c8nWhHy zT5xdUEyGy@J27jFr|ztwJfq6-yPN~yF(w*>w%${kA0j3{;PU~B%j~~u1o0g@nqbeS+6{rH;V$ylsT1XKhGW&hrgtnhK#0 z3kyijaYTC%6LeF>l-3vuiNpiK4b0z86tFVc%&!&X z(j+jVS*OQ;gGUm1MO^KL8@jz%T5j)x+%HnQEzrH%q3T(&q>ntO^~DgOlD2`=&{qcb zxqzL72?tJvY7b4xzO-HM&m4J<`yU9p*}b=SR;6NOo0neQ9?=H&8ws@)jZu=2ZbzP- zA!}^R0$}}eT3yJoG$s#4s;B_L?XGZ4XSE~}eYKsLVlweIh(lFIa!46xy;!7@2U`Jm z2^Ebe^G^JFK|F}D8o771d(<_bXFosV*_yemKf_@lp0IN{uP-FnKY3iUM%Ftb zT%I>Vk$)^eBDJgnO=Zf!&_p}+f*J>V{xSLWXa4M5cA3-`u6P}sC1e6L=L}mO`3Z!l;bQ>Dqh8|x-I!e##bQ>4(LT$~3OVum+jZley7!8j1S}tok+8QUex= zO_O=wdu63%G=_&bL|{=QcV#9r?WC8r^H~;ZVnx58WUY{gJIYLz*t!5M~5opE_DaomSzIqF)m+Fc3__gl%nUU{W)Fn`1*mJTUq=C_l&|9krieC31J@s*(wg`N#~{ zFO>{ed?dz#Wg2B)Z7DrV91>@iHNtr)wxY7u8SgB<@}V+VpV6Tl>E$qLVGS0>`dlVx zVEl5`uvuucDS)DyrIC7%f=i3VQT=avb=pNZ$YtQpdDjp26VpwD(v`dqy$vtZ0enK| z;AL70Hqtz0R#;@~Ux8@Xrp2cJQ>&^ST01)m>%lO1nc^W;Wd{b=uuFq$rqOcsSB$-u zG9w7pNM?R8gu{m)6fRU7T?a<(hFn$46}@7uR%H7Y!eYl5wA0x$1pR+jjgR@g&!D^8 zf7BHw>3f)SCOf33wI`N!OU}1jDiSe`!WCPzpSU0j(d8<$jAcwCww1g1b1<=zGP8I zOVnuC%Q2T$@m=>4Q%C?6OLDjZ6s$xdko|%V44cs-FxASD;4Dz1$ArteP z?Be0#n?n{gw;Yo!LJ(9*00`cX6qV4Tq5=({IXy2Pqkb6iaN;|vfLM;V5aXW}J)jH6 zJ0Dv=s7k;L~)L%e?^Doqu4bwdh_Z}iI0+I^8BTd6p1)tJ`UTx!p*PsBs!r> zXO1`qdjqed*L6!AQg|6b9jfK&@%IVbF1O$hDkzv}Edw;AH}J`>j;!}2x^p(bx6Zrr>B4MjLj2oUa`qZJ)X~g{4clI(+f#8oL0sh0D3`h<V%}5H)l7#{d9s zcMv@+R{tZr`P(GyP%P6yGi>Vlu_x3+vCy#GYeq}QbZ#Ck;TO_1$2y8)w+3N=4ChD2 zXZsRBX%qSTeEF5ER^YQib@tU12y@t{V$HG*S6wF57B6MuIE63`5v;Adx)`s-w%i~c z*E>*Z^W&1+EnOO{HehmsSJ6}xY)wdAMdNC(p)c09Fr~8d91Yuyok8lG zU7);ft~fTl@Z1m{d%z7JRRr}45jTRClL_#?;d~D7O0lEEbDb{PeFE?RP{cqx(JlooX8dEPmfiFe4!Sai4iTv?WmWdrzV9tT; zrFSIG&IwOWgF#c1`bg5!GO8Yr2wM9t)=Y)bH`Rnp3HTTVP9dX5q;yVe1Ntjb`|`An zP#Lz7a3ipeL-AXo@CJbu=XPt1YV0ei4Sxqwp%1;u!J2sp4!3#-c)I6xFM?~qbeQyR zz7b#F-Ac_bc(k1|T#b5Gt&GcQR1x0~?=Sk`mAvL*s@PnO*2lxZL6>diaOSm=fcHJv?QVGRu=Fncbs3{;U*Mix)Hk=#STn$Panh;oj~WJs z$tI}5G@yhKXs%6u)zBXNWg9>B*(ig*gYoP*m&qV3YDc$GG9Uzcu=N9ar|Ld3pd2U~ zWApJt=hc9^x@1sGTom#z$JxG@q39WUd*5r&4eyIk#Sn{Vy;^7BW8BU(<7kocNvfr- zBVv*FE$?l0Lcyx?_#<;n{l5d4Q1;Q6BBp~9C{jcDYTXVTJW=@Rn-T0qBm?KeoJvgl z6c4Yc=mkoa!b$ohvE=qOv@;^X}8I*G9iCiD{y-Cka)qnafZMjs2myP%A~t%`m$#NEth| zsn`{36_FKb7PUTvxC)Q}vPKf7P~x$n@&GkD=nMOytUneSU9VjBIWru0E#;=b4vz}z7zhhMY*AIuM;4eKF{kI%V0Q;A<*BMdk zNX_TbivQn?(3?qbUw>Bnh87!t7Vle>%ttu9Kv2_$Ad5(0dSot`ZsJwo0q`#q%NiD*=f+o(+wZQqwDP|2~x=us_+61A!Fu8SV7!LIufS<^_y#GD;DSNGR`o zN)VZ7qaDI=g`^d<;P`=)71*ZV6;)T)2s5$l#XZ9#?PyLOqVKsYBnuX%SARkMV!ifk z@e4eak0*(V8JtLZQcQ!RiA!M;6aZ5b877Jacc0sudc61~*k@nzj(n91(YBlH^-l(4 z9Y%6_Vu++X1P(vAJxtmM|%AH-bxHB>3);$;D$>e zCgs>UIWehXUdt`8&uqkibr%9XYNx7D zcX@=uW_ICVNCGQ76(uw`cE@rsXj9+{NUp-9Dif)R3T#^AvT9Ck)xQEA=aXTV3!t+^ zqncHZcm_f@B-8*)N1~fvmaG?x;tU;!9*oDXFKvcGu?Bw=gGMJ;p;3~Z3B$~tF5WUc zr^{3=kTij6l?;(wZ{o0i2(+Yj9Kgfqch4?tu*P>22F!*USQ|sH>_Z@b%Ots>^05Rw zBop+fhYx;JvOq{kj&tpZS{kDX?9?jF8s1>7CcJ2bow3askL|!C$=KReZTCd10W5+# zcd`Jqk(2M9RI1L;n+FL1AFg#+GJEhoSa+&W9Bx~Yl`){s+@*xUE=*_sXUNGA=zoOy zl*?Y3jAR*@C%|puj-RbrW-Icj7lW7G3tU6H@1 ztoz(jy?^A8Y6AhAT%b^#@rb~17Jf{aAyd65?@5S7o>%a^lP=3c# zJFZr?6HKK^qTyKN{37ep2U!Ce*ODUX=X@kMg&KV8I9`x;v6|u1uBF_lWhYk!5ZJ_J zH-tO6ch!C|gOKv%WEH+;p&7VDTRtJ^!bBSFXoK%jwwR5PZw4XH@+efXNn@!=5DY=;0}9}pE#TNDR55)04fg&loHc;gp3OjmS_ zQ%O42{ox}W?hMqxHjh_}SUB#4nT-CjocT1H3jFPxbU2+Yh2wQrR1?IE5oAR675)fyWzw*99o zE(SLsWDkU~&0p(SVcQ7{7_SH4xUHu9 z-aVH6fq^^O=ZVdSRm|{Xj<@FX^o<~H!Y}vxxaFHp%yLf1^#@V6*96Z?CD!$AC`As6 zlhb&0+G2v?k;@LqrOGn*OoD}tPDQ>i>EEK4F<5b2!C^1?F+VJ+nC(>taIJd`Y>`Y> zDp0563DvNJ7CEb^WsnS|k4I%uh@pl$Q4Q&^fis+(vfuw~`P@1%s`ad%CEdHfCdyRONZ&|L)4wB?vuD_+*K zZpIe)z3yFjLE7R!oRC0WrR;5hZ@xm6m@#Y)k>w(Bh$UHH>YuVdX3bHGDBYD>x-#of zCdU>PrF$nkj-M((SA=Bz_fLejDY7%2?R5)BGaEbE3LD3**kwqoDO!#&65M(i9WvJz zPrjc^(pe6T(MLn_#GN$?le(yWpkqa58fzXLKBunqKoIHb_V9;7@||UdL(iUm!mw*H zKF4gXh#9ZO{g?0az`H%jxxE;X?^&_sA6tgChM)CEJg;D_ZJ&!X=Z3 zF*9`p^mE@vWX`qXJ`;m90Q{Av!@*VrZMh{&}vhc5GbSSmqRZ)ZHqt3?#& z>a0#&qP&*wA=JwrjUd>K*i2@gX;AVpj1Y>C+-%XVZT1*9L<2Xl_dA6|!&U*!Fq#Gi z>pi-oQqpu4(?7L45jdZ2?xN)Trh#B5xj-G02~!k$3ykx`jd0^6Ysr|M;r$Hoj%AV_ z3eoI`@j?YX#hmdYJ8z^?Af%P}hF616fcqd$lj|M{J0GD&2Jq~o*qnecvydJx#J`9VRsi@LbAUb@OS z)Jj3`3;%7Ay3fWYBeY7CAZi2~6)Ag${}WgcFnHqg!RCq>2TZ0Qo=di{klWyWrt&+X z!@$C6KsbgH@B4t_&HW|=dftJSwH~IW9?9AHviWP@Nfh^>cH!YbUd?S z`rRp1SPN`H61i}P2}g)`zwc-(@ZwiKAd64+g0s-L z^w%W=ePy(zgd+p&tom&aen9%YLe^`9({!6>RVzK4AMNAhWzX+7^f?V2w51-TWmN<^ zfL2KLu5JXOfq{eBVs7r|)(Yh}8*4*!h@k;iXb$rip!I6}ltuuxG+oPMbtyXbP4Cw_ z>r5BVEfu$4!Ez#1*IVJJMc!{()n~F=j-^kIJ9~yBlaB_3!*ax>&==6p_sJ4J+$Oc9 z7ARym%%F|2j@AYohEu7efFA%kryeoe4C)v>8h86wsF^8Q4Q*dhN<^zssC{x=S1w8v zCn}o-g%t3`k|wKL$MXU9d2+)QZ5o{fTU&6l-Ht$#j1J(uEb$LI+vUi9K0SC?Dz%Pp z_-{u*KH8&oD{D0v6cAHv)iv6})nlt8U)eWW%N7%*#Z+jV-era~7N~5b{!{i2pNZP2 zc88F~T?QKs{k5uuL9T_Hpi2aM@ux}oJ*BWjYja5IT!3GLZoWTvD3foRpH1bai#(IZ673blf5TiGtW7# z{CU%dCacS&nW z?G2SY{6-E)er=K+8CgLb21D!^)QTNwWTuinXBdgU@ zk^HVd9K4?$dQeE_G3Sh0-_r28kx9%0uX#V?;P1vht8$ho<2&bLHh{kXjMF=dr6!$h z0X}6DuJbuNwZAj1@NO);d&p53S%4gdK4kb%NX|c(x|8};PHF;FD(@if0R^kbWdLI^ zbN()9b-^@j?z~^k{C-w^ju$Avn0Z{#@cMmz18MO{{xti-@k+7nTCDi`)YJgUd)y1j zs+%Fq6Ip+Wz4lp1Gyfz=}lx8M5-KBoW7|_rh(r}5{?yycIi8uoCdi3 zoGjrD?zic6xHqytLsdu_rj)@!;9{M5xYqG{L#^mI67Cc?8AWNkC^N$;^!^}QFA?CD z{XdMoV|QI)+b$g2c4OOajK)o4ub{DQvn#f3W5u?U#ak9^-lLy+7RZAIv$% zysq;+cp1JMS%kuT4n&M)30iSOAJ zTw{%mRH$n%HS0b8+{va9J)PB%X>K2@AQk$krs5{3UN^tZHsFPYp!^6NYrNbHuv+ZgE*N^!=U>NbA-Mi)da!`u#LD9l?Qvvg<@QyR2tV_lkBZwwnaK^MmWT7t^UehFNAi(k8+RG$n-?6 zW(v)lqZ!LeOV`Rf=u4v;@>rH(O?J9rrUfW;#wxJUx70-tU(f`zLco%E>>D+T6X|s) z^qU6lo3U&`VP>$LYjP3n+}6u_cj~LTY2LE|?c{5TkCdwFw7JDAO*K>jK=4V2wWmkz=D$Z+t+pW#>gFa=KXyXlL4D0YXlJ8=t3#V z637n-Xd!=x0!Te)?vO$C5oPxGf-^)_hyvKcY)q5uFy_2_HFbM3lp278-9LL?MLPZ4 zrYFdU^5pk5Gi3e@(}s^=<5hNwk91mJhYiPi#Zwmn5gt<5U)!0v|BB*s@$OE@L2lE> z7{|uBMl%7%wKZe@+;Q(hO zJJg2tSRF6aOik!0O{L4=`PC*kpWSm_V&MqaaXqU#E6};VZq3~6MuhUo{(^P)%b1rg zV!>wSBdL>9eYL;B%Y4miC@J1|3FD^S2_M4#LQoOQX!YXuja`hhI50r8{D7) zy`SC^UgRo22T-%Yl^=6Ha6cJkCaz%1m&hg8*^h83>e`@|_w2f!l1LqPh%$}$1||?B zMF>vhyG`r75>OfeKxfCsN{FRqf5Z2Ul&>{lf*306so~qJNNo5G%{d@VxU>Tf!W zB-HEyjm~~#_j^@I(16o)UxA%FRQN0FHgC*R-Ww|g6_>&`MrDY=HloFz#? zyEsB541*n}QhFtlh002N!;2oT^PJ@!^6lChp`rQp`>c-_{fr|=QOSs=4FNb6_Ve)G z#3Uq*mF7+Yl<<1)%XCT_p)E&TWP(zlHCLR@E>9Yyy9aL8?z^K+1PsIiygRqc{H%;Z zWt4HY=W<6Umcd29d$10s<@3mw`*ju!mNI&jV66L5M!42ih+u7AEKG z5KgFqDG^nN2j=+p3qJx#rg@n*B?}4|*y<~RkttyzHv6nQYMDx}0YbpETxfG>Xav?2 zfdhKT2?ba)^G%U$fi%;T-)b{mcx2E~F>SD`4d{&VhRp*{LEZ_NTPBL+8uBi%)Hw%b zJS`4i@AVUVUx}zbsK1aAzd)q~k05_a8F&)`Bj;+C$@fQJIr(g2A|u{Hu=cCTZ*TAc zTN5p(-8l|gRE1!D{KZ^5J9o5j)zSnn~ zVib+^&p6e_&Tj1=F`_}06BvV6-gte@{PH2??D6Rpjo}1%0*lc*Bbu2an$-JvjqfA^ z4=p-L^`iMDQ-yxMOWuy9swHz`DL}$}!@~M#uSKYz%RqSFq8f$+wif-U#iuzRn*pP| zS9Yn=0=I|pgXOc~lTya}$ZKo(;yhV!^7QDicDAx6=+`$h=f8t;8bK1RfyIQ81*PJ2 zjZOj~@=@ne;uBbsU)4(gkPo^(ROQV%p#i(loW!!Xi~vB>Qh8bHo&NS9dH zfbpyiX1{hqntjFjY8$L`YF7o>pr(x00out#``)6dM3gyTL_oZ#Fc@X ziEKYYfm;N%KPXJ}Wpc8=)E?l-E;DidJ+NJKe)v0Fx~V71^8OfmWsse2K+~RRTVJxd z*BZ4{SB_LK^ldX=`bW{6`7^>*Bz~^$dPhlx4lQ?4JvS1)a7hXrNjE zV^+l^&F;qeH8f8+ebIV#b-m7iGfoAopeJEhGV6ZEmKJ~;%ELT-i)4)+@0@LIj)SB2 z`LeM1$Dx`ndhGDY+M6r(qQRP5BbiNgOzqYhdH#J8ajEho4L~@?)&!|Z$r|rI5!Fcg zF~{=e5c@R2VrUZ~9k+xOS1XS&a&Ru(GjYUX_>cR=mY>0Ag`Ix+^KhO69W?c*R7WOk$PlUEF|S!&oY`ig$)mLj{@tu=YlQ=ByW%ZObFL9EbiZUtX~W0u@rL z{Eg)>(E#J>^|c#|XA35(sB(2h*qGt%&9NCWZETI5QZ(|>)FSh`0@EH-Y;9AI4H4_A zC@FQ)AQ#n40cUiyRG7tSAFx<9Q2`QR{G{i|1~{NIIMD+G?@IXF(FX|)iBsPt9=Zi8uIfh7>sm`T@L-NG zu*KH)%@Kw3&L?%cD)$`?6gJ~OHg#x!#?aa*|_*D5Wt&JS+7-$*)qC{hs3zv zp($S5EOL>#-Pqw8xj5n8kT}YLvL3t=wIFp`+sS0w#_x?T$@uWvBVCRHysn#Hehey; z{}K&q6Idx1T&=aHUi8Uui9&B1@^x@*-Q}kcEmV%vyD}GejGb+il3QXw<07@JHMsyi z)IlT2{i2|4{P9<(?(Dkb^Eu6&`f=EyPq|^-YQWu1B*Cd-MBf> zY)_9{PoP1hv-LXyaP0#wK{%AcAwHGY->cqTx@&~26#m_MJh~m9ie16;1YM%k{ z)qPCv3Q{$0^Sam7@$Kp)olN-@#*d+4DaQS$%?-(l%e&VvorE~$ty9kHAnDB$X3Q6D z(goYS`~A($01hKTl~v^OTW+TjOwU9e1>TnvKG441{sP+M2iR?ulSo-J$j~Y+FK3^| z_tIDt5W#tJ#}fGK>g=q62r*;-Ol+8zhf!|Lm%nMu#>)a;-X-E;T(uE}B+Ea}INCQu z{NF`~3o@81wVXEN#&6{Bz+md()a4N~@vL$6?Kk?Q8Qg;(gXJePte*BaeN?|@@B+v8 zRlkjp)wZ|I#sACzb43kP?X|P>%l71TqItB2NihEeuRRNbd@9rzXS3Y|Zv@rJO2wfj z`q%>XEPhz8+sY!R<^M%aO8M;l_F)nG)QjqeMM>iEGQ>uBfUpYJJ(_nh?y;rZr!##{C<*6T;ya~hO!YQ^Hf%;d-UN}l8YO0A ztS!nO=b6I|PyVD%ZZu!4uWqVVaA)7wuXrF^D)g*Bt>PxL0eT3n#9E+R(S^5Uw)bC- zv1{N|4ka#&UhS({jU0iHK?|)?gK2|czulJYHOnz@uPD+pD7)I5LX2=IFtq6Ni5GeH zQLVANF_%YwjwQOAKt-9vo86z9KZl)F6A-JbTBAJ=Sh8SZu2EQ%4e%kd3~10XR{^fD zrPzc*Sc}L)@2n4%=Of{pW=;#}f~y@$3iW}L5^7$gMN2-b$MGQkf6(#|IiQg8J$pbb2ZjyQMbRt^~&+2+CO z*t^Z73^sk~h+@xZN?&R`X0C8di;cQOowssDO;6l~5)wEJ+4SyF zCpA~KLn7l3y^c;~%S#5oAn{QH_Xm&hepN^O4Fn^(XM-lVV3U)NCDQi$bJXj77QY)g z(R`U?sjo4|4l$ zFz>!x0Gg0r&hbu9o`KXou`KA(RPSIlA4`W2R_2R zdbCQcskzmHNWz;n=wwFYkYd>&>$mMdp1$RdAiO{aG1P3=AI~<)Y#!T;Lp~3P?215- z*NtOjs(ic((=i4Xhu=zN=R;nQ>g8^EUsNvK8e?uZscVSHC!HYCjoPW3waNzi-9YtJ z!O@I7z?|ySYcTp++mgt*rZb)$E+#8juo)q}6Ge5C2-a4_F3=xn?%;Fs?ANZoM{r+T zcicaXqRF<-mBi>w9KH~gd!J2}1BabSE%{V6#d@o<(AdC-bi1Ag55^6TK-^9^1+*jI zrBcg(JLb=Bi`D!;w z$XhJKO`(Iz1A#FyIxcn*d>W!!3sC67{mcAXsqOOyH`TroQ|g9KCI_aq{JjBFdU-L{ z?tfE-EHALX6}4xb%vdhVb@NScJoz~${K(sinJ^-Ixryfm{-br6S(@tOdzd(p4jd5D z9y4hB950^f)y>u)sP{Q^f`JL{#pJ6t zYUX<1$XfVCfr0|2NxV-7DSO+Do$bKNjiT$C$ms0nm!sw$YAcbfUZ;MQc!zUT*#Jfv zG{><|W3rQ03sh^;wv=b*Csm+q*RGp3J)SmftyuimWx`SVCzdtpv9rBCTZ(6+t<#)1 zjui2dXWGETgH!D$_jk4jn+)Y2*{53QC%P69(?uEDBh$BN8dTz;Sr{vi*>my_EkySI zuh1r3ov;8I1@q(<=~pgUb~f{NhvTh5s!oK(Eb0YjL*Y1d+eaEJiB>qPunwrM`n|^5 zc6)0$2DP0giO1_>SBsy&Oa@S-t~Ox>vo5JYj_uiL@#UlcPQkx2b@;db3?7KKKWR!+~ClPkwlv!`}<&r^4z_*pW&U7V= zsDtlm`}TGm7BukOUGFGoNJM{_dA$!}ke`Fc zT%@ovYN*MyYS8XA1KF;}ZCV@kXr8U*>Gl9|EN7sEc)vZe0=oIUB?nt%X@FRrVXGg{ z03$w0>ahT!nFq9lTM%fCK6T`GD`wamd{$kr#7NEZ*ce_BLFf-H`?p|4JGWeAW1(|h zV@-n$Ar#^d+kUw`h*j7{x0WGSI&LprE-_5U5Pk`ASl$V<2Qmk{8`oG~hpjr&I?)p6 zys1|+3q`r_r%|{@e%f5>6WZUDlLNq^`u@ZKwdE?79h20ptT`iXm~ndPH7HgxCX1PL z&c*UfhG(7enk)%JPp|omjs1;PEu58;G8@n)v0v_RBQ>>AiPMoW?ivgmYV0`(SB!2zD{QEZ>Q314i0Y{i>96VYk;5%v6Z2&=Y`NST zB3BWB77cqcHR1@3sx7tE5hG4Rd0p(k$}!9LVETgTSDUuHN^zqvJ3#l_GkX1}rQ+HQ7fmd|@Uz*=P_Y6v^Q2GJCWX;tS(>{#*~F1!M!*Vd17;|90;R7QL&VTP z%p=4&diUFnvug$tQeq~+={n(YF*rXS&1eEDGOG5}0>RJ%JubboDBALho0m7rUrV=L@KiX7eWtBP_*^u1Ew+#c}2NCp!e;qj)iGntj2^3C`tH zdGp{D1a3t7zdvJEzQ-K+*rWY;;PbtI4#`OR-j&tUfAi)kLPE zl&>=4I48Dl2AY=TL2WqgG_~^5b`_u*P8_u^)hekWQi&NBD%fvm^*lY-d3^A6VN?F3 zs|=QeX z_vRB-JH+k7D-$DGz zyiP+ywHB1U*_w%*s5w8v`>qz!7<Yp*%|ltrX|-GHtRWO?-b)eN$1wo zA!R2H2D%XfA>xECKCAWnqW;2plTdQqQWKx-%Xf60tLEK(J20tdtvQp&gLK6o|J?We zl=}~aF7A_J@qg(LrfGL>n*sEj_p~itaVmx~)d{PU6|5TGFN9lPSVlM450He0(%yHv z-EkwBUkE`&cVSmQnrv0t#SBa$m-{^x+nfj`-*bGA479oe;Q`Gx-NAh^N&%y3E3hmB zy#Z8FjvN#44aZl~;z9$(70oknAxxx7VKM%7g5LiOV|kyiEfx{OXXU250q>dyOgntz z&iHzySe>%+ZIUPhhVTw;1h%A)B{?trggn-K zJqn{!{-E0bcr<`yfBcFgIUtQ&1NS1L(5w~L5zhQO^?$SghGa@}goe_DE^FC}nR#P# ztcPakVXU}4qWWx$zg5(9CMwF}WGA@RP@U=5QtFVj-CSK61oOQe2j z{LwJX55Bke2$`9k*=zW^gX-JE?)Gh%*j#RLId%P3+liWs`Eop$i~b-|@+8cfbb|t9 zQ$Dr~(NJtkUfHM0)oo_6q{V1RN%?amUsH^2%=FK7-RudegLiE9vfCw81ja?Kp7W2Y zomDKv^0;W?qXfGi8!ul1{{vbkKQ3+)l1&p00>1FLRhrRjaA@Mf2pyU|Ny4ew(7Wa6WiyN$|26n!-s)pCwS?BY7YR*D~bboOoPgV%DmqhxR^)GhOH zlW4VSS_T(~>gfeXtq+YbOk-gds9sl>HdgSKbGn>jV*2Gb%3yK(V)(D@<`qp`=fuz6 zn}IE2+xg2NkmrO=l$)>cBtBRGJ!&3)t9_~ zdklZ!;S8rrk6f`MVc7d^zU2ETLLb}HWmdZ=zyaQ+ z+v_NM0b0AC`}lWP_8f*ud#)9%yptKS6OPlel)8HC(k(xCR~O|{zVo`HoZ{n2D*XCp zjrzjksb_P#IreW2cJ*0q4Wh2_nAr}HICr9CcyOc9hrVN(nYcTDbNjvpsv95(I|`|p zg0T^d0I&5Ty{_H2W3}r7BV8Hm&IG7-p{uK{kfgJ**`vp)@zq$%@Taa6#|BbxEwiC4 z`b>8tYn7{|awiKrhSag`%#cHE@#8PCp6jgcz2U@rup5`FkuDLxy~IU<^y)h{`&qQ+ zoHtL0^RME`;>!oFyhVF0PpWf|ymqlHtLE~|(^CN5 z8}j*~(s}fMB^5Yk{rx5?APgP08Mb*J8^WyHj>NO1q3_M~#eQ6M<5GgmH3;MHbh`O4 zI@<;6jG5_q7nSLRyocHn%wMF`D;(h}Zwz0~c>MqAb~{YA3E^PENyjkW%?Wa{%FyUQ zDB5)){61s@L{d=jYQHxvO_AT+%8BkS`MrJ#n~qidi`hOnbJj$AsfTVdX*N-#-R#{5 zUWmID4YsUOMC2kfix=+B%_!O{9?P z1Vm-#gAL+AZUpGa=QLp`x zJUvl-d0g-H019xq;01%6n3%di#1QY_p4lyoDK0T2-^dZ2E86P;m5}sW-eo^_eV6e* zJHs=kfP_@vS!;Z<5ja49D;wn-SbIcY6TY7b`kG|K5m(yn`8z!b_iA%O7vi&t;x|}f zXs9b0ww^QRX^^WSPP(jBcu- z`|XadGa*KYex#{NeFQs_a3_~=-fo?GQ`7OKJqgpZrCHKk=>DZge zRxS%drO!}M3D4wwi|_(81#RxMC&Wb2+L)-84q|N_#R>u)$WJ|0EUBt1=$dk7w zFKpUFxs$9d*Q9l<7i5^b+%B1U?JIrEd}s*eAKcgKmR)pt#gV#6%u|&8eaL|hI){)A zTHajj!SB`b$?ZFgvp?n3(^d^8sC4t84G9}m+YN_klGTzcYCSu|mUS)<9%pwtdWAbX z1D11O-1hS<82!t@8CjSVfu^2M8dmQ0a0A7s3m`&OgC@S-B}Ak>_F1Y*lwr-ffT2H$ zH@OyBbUj9@rG|)dB`3rRGWBGtDjLW>B=w<9~^k}VSb_93tpqTTHw*cB5qI45knQ+_hHgJuEc_VSQ9 z0%FhMR_b51GCZ(Pv`6)4v0H{S$-->oDd*AcxZ-T2%#~+2O}|UbgV(aBArAG7-T)VCF+_yBOlU-* z8R0|;Els$_Ppbd8wErKXLHo(c;t0%?la!~b?x3ynrH=Of#Ty24ihx94(~oA-*YI;d62YUSFVD{edCSqcZ(QA0dgee*ej29 zhM{_PTE=@lz0agE0Y{gSwyZdb6~^C@D18`6(87XEsl>hZXE0*Ckg2k-bt<- zg>3C)S()-N1&BrjWHbvRN9o3!JT%qSrhKL}{8I{JIoUHu(LAzf&>7~|C^ve#IrD+3 z(`cyKZ;C>#XGjkJ(-@*2k(Zltf#}Zrq!ctU$6emVut7CO#4nn{dTZ6+<@%Ps!-fz! z4CuTJ`bFSmV~Jq(F*D;2JsjCofhJIM0|(}#hFdZ=tIv2?DJjxZekMYA`g?7lDQ5fe ziI+k;d^xE_)r4aisFF6__+{RMS!O z2;`R)?nl(&B(nRbaCfLgI?m$>V>SL*KH>}f8!9q@DP1t!A>JcT|Z1MEsLLq8;DGgEWWtx!Yr&+lT6(-%9G1*)-tL?G9D7MOW3)nRyi4b9^`!j`Qj z6G;9l#=>DYjdX_mW89tgt$byJR+EiguNAO_vC?5yq2)=`v|S2IeF5mXq+u&@k|f9o z9*W`n%(ue*N2^q7=qZUMVii+}7i21CQnR6)MKHG^vS7eXyut1u^l&B-j?^55jzC#w zz$zar^VrF?-@gvBz5s63Mi9*OsAtCMh?go}e-Z9q z9>x}#(4M6)^t&c-U~KGXY^l0UiXa^nmMrMgTvT$C~f%uM#y30fp^;Qur^H%Tgv&f0ZS%J zK{4M+4hsEMnvGIQO0MW!J!XA|Y1V8|gZhmRlpY<4wYRPnE>vKc288ua;rmNHX=lyWlwCLDpT z>%1r6=)q{ZaM}iR7^9xI$Tz`2B_i&vpOIcWqCfI&`!-nWP}S88@yp#d*`0gM$qI2$ zv-qG(z15wlVLCDE)i$BSIn$+vhv`OuErcBy;<$B4avP4=2W5;+cH=eTUp)al; zF6ob4<^V-D<1ERAOpe9Q%-2)m{^z@0PLJCi@Jg>M4=iKrEy_)$+do)3+7fq%hsNh8tbWz<7KbNJ7+jY}vTyxUt8++zrobW7+&DLtS}#(3D3A0DXB~PW6qfqm$S&Zx$D5@<^s*KwU0BqkL? z6@1Eth7o+9Z+2Ls#_Jo!U*^8F-m7ln+Kz5!*Fv-#`PWbEU;;(e;r{Vu3OwO^GASNG zM@HJ+O~Q81B(d zO2eOp4%CTWZ6S0rB*>C#k}2ky?hJ5I!@$5W%9-^3!pA6CVN^;v1dH!(^jAZ7t2W3t zG|N*(rp8I0p%Ym1u*$#4^lPZ-G=lv*3Zlb#Ta<2Idv3)?eApU2V6@U@W37hN53jBZ z@X)Y{mN&ka?>c?{)`>@1o-`-AyX}h?Y4*zYcIv#{(HtykwuOZEwD)Ly?RRh2jZR5j zeCVEnTo{tYTy<*FkP01!8brS72R5yx*GEK@A5>xA>qwYumNZo53xO6u?d( zUl?nN#?FY=5QE7&HM7*HPBSc1D9vdW@}`tCCB%ah9^aOGwsTm0Vh~zfK#l=@g!sxf z)##ne$G*7?zv^2kBx+P5(ykm{7MkuI9gvUI-+`$7Ol-0#fHb6@X;K+GDj=tc*Zq-o z6`URZTfIf5`tnULmNs^lDW%RH2n65D%pQQLo2*(HoWu&5-Iig-8CNF{CSA=k7dG-5 z{*1wIxGhXr?7}KTBDe=?Q>InbqMN`xNMk|IivI=`}P zrKUw5{>Qm#T*c%7?@F5;MKy)(0Jub!i{=7HO+lu?R2}JMGNK#mPeRMa`TeR% zVFgxs*?uW`Yg9;^PQ}!YOi>JkHEWmOd28zMlO6~c&9L)&PR1Gp*3|m4lK}eUTI#Mf zfjkUXg=mqC_j+Y%nTFpwMj3q(-Uo{ZHxyO|1f2j z^8`WCBZ_k3QTx#;&K4+@b6F+>%PGfHn%#Q*iCY-=>&zO+H%?3_Qj8X9wEEg01#xtx z^ZgESeVJuCJTARsHQyRoU?VuMJpaL`!d9$1O!#Z;c3R;qR$?@23C-A54kWXtGY={gq zRYDkLWv17?kjr)aP>&=_%`*kkwpvA^k&qD7BfbCO`sPDdpyKQXR0JWT`12#vtL_i) z(=$#KOX-|=R$27g0VFx2=co9iTh;q777*ZhILxbtSTQ2V&XptCIncfPTsGgADMWX7 zIBM@YolmMr>(UZtISm^i+GUju?G67a<#b&DRHD0e2eRkW55FSRJWr@nRlX9Pj08EN z9C&%*HoF$`>25HTM*--_ABU#$VceK%y94=Mz=M{ZpStUaIhECYbe{HT2PZU^*?=SN zHN5Y3ogUy#+ov=POV;1jyW^FO>NzcT2k1PdVPQOtf>~r?r#O8YpxY2h3-8MUQW9k_ zkCQy*5t4B{JM*4d(qxNv7kbo%(x?fZj2aLA$Ni z1@ODWevQTLO2XgZmLBQw4FXsTs`+$vq&<|)LBF6PG#9y+O-$1)9n<1{Y!i?xzRKZ5 zD%8%UNGz@0{4Xm%Q7^hPGRzyjGM^J`Mx{w|nDf%x*H+1aqP^5q7 z|H7l`a}Nl*yB6y5!tU>C41uwuj}5SFKrXlyGAkmq?ynb1~Kk55z z`?lWh8#yCP464?Ko}tMkw(USOZV!^ixTg5ny2#b}ekD~~47f5fd%pt=rfG}v@job` zT3JTr!L#q{Q}8hIc0!;>O{+g(Jt0e{oes z6wNoB$-z$q9V@;L>>@QzI*}@5p`u(y)I@|+F%oRtfAp>NYB@|+#;C&ItA%K>)&RH* z2Xd3tyVs*+1g&SN+CrBIdYE;NcJ*5dy%Qu%?0&Ipg+7jR1gu)urho|_K1Gy6QTsUnaBM&n&$QssY$THSl!vh36*p3 z?i4#uxMmGR09cvkoZeEl*Kt}2l*rxTKEJ~r21!KPpA*)A6*3;E9NZ&c_b{>3zh_?QA>wmj zl-WlljdJClQBdKI@>e6a$RfXNu`}bB5&Y~wQa(gZR$EH&&Yfbh zkUur+s zW(@Ib_Gp;j#f4i%VVB4?_NZ3OHeuwp(gf;$O)ck{d_j6F876B^Lk9@U_|l;}gm0_kaAT!T5pr|mOSML1PfUv3 z?7hJv?>{7&i0Z5ZmKJ%cM&RxwFj_-PUEbWAu**y0Dajh>82#y*f&{2#2P|rMNY4M^ z<4Ds$Fa?LLU?}E{l0I5uHud1fjr_yYXVuo_j)DRqw^i1nY#szA7NfCu?nAmLa7UHZ z#Tc>huo#jzh7-AIqOD9-FO+N5xO)|fuKf&5!mSppw)*^2N2) zR(4vwQ*uO!Jt~&pKI+rZyHVO_*oXx55Fg>A315W8L^saWWMFGRHQxIdR8sk{LSChJ z1ZZywR4}oE^-@l_YCddA)~$1xR98u3ZLI1?3S%|274oM0sTqrMsC-8~5^y#uRJ$Lm z#FRPZ>@GV+q4~0SGQAtg?WO>kug!YNTZ@}q{OL39yJ0SwwdDF=cuHoA5pBsYtus>#P+9}Cv^aJ z3V`2%Bs==XJbM=Mq*$l_FLytcN9O-NFs5nin(R4bkmHDbE)-_m>^dFjWQe}Q^bdt8 z1^K^EscJldJsoy_QhYYItJq+lE~2Rlj(J;z#Xrd=1ZHOoaP`Q!xsgs;#Cl%%1mj0=nkk#StgmwC zubef%kF~FH`f@Wg>d@c=n{;1=oRfd}{nXT*%=e%86*9&vssdDmh5eO*?BBioTNa+U)`aQfD`q~<4@HcAqwn=~q zY;E*C>dZHHo4NdO$)%QJzagb~<;gxFPWP+{9eN8@d6>RLif=jzwpGPi2P{6%^yN;5 zFfb)*DBNkWN*oS$J0!NaqMZn~CEAjmo8EUs_2gQ=N;VvTx%Dcjk;~xCf5K|3U3+)+ zXr}`40b^KuS-hkbSo^3IlD}Ao_&Pd*Jskd_QLkd`d?j>Jh!RocRWeSNe!tyM5G9wy zb7yEQTaKn9UNwX zi4MW^(2`^O#-2ZMr1C_cwO{0$eo4YF;dhR-co!ns^Cr6+O%rVxM4Q~R`MaJKqh?0O z*9h7z$$VTZp{#lTPqU(8#=nr_&noL{WPTZ$se4ndZB7>T43bo7g_!j)+>!&Ae-?tF z-0LeQ-F8O3vT-YNPC4aHl2vRNMq%d;aT(fCP{v{A3`w!3c4;&88GJGJzy%FJ`I&CT zTBCttBaz6j=wes0J{Zs^ugI?)3*ux+K7#UzMf1Oo-3sOn#6|dwk4Pb>Eu3XDrao%) zxd$34=yzP=Pj5YpQ}?tQu}kXFq9!_)$XNnk0+|JIiZL#S18<)5wyYVhYOYRwKIcsd zny(q6V7ireo&oeYFyj?+W>OLQ*S|4B^>MU%z1rIGvPDi*(Du2oHC0*NO8oY_l2D`m9j2V{`}6q{%Ny`7Nl{5RtH%kIw)QkT8e1=2bNw-sTr zsykI)=k|JJeTS$*)oKJWmINOv87#-ALWM3)5EkwmHQWX?LyTe@~=*}%YzetgzW^Uqbb-3FGNI~r6p=xHUY#ZlT57RRtpAZ{`Se7Yi@o1q^cof%UMGJKNN@f!m_HwwI?uhAC~CLnbi#JjPAKx- zv93QLgye@H5b?PR%B(+J;RhmwGDu z+J3D@{3@L>%#}ivEn*?x2q1i^gN=gREhF{o+0W!Cm9x9pF&5~}M5#H<^RS@P6UX#i z?P-ni-MPcBi_8b3xGwbm?fpL*%n0B*3o8bOi0epdoOR1Sw=Im6|2#fTowfT02?7M1@iJg4)>AV zWt-2ZzKl}BfSqT*tOx036KZY$xNf!YJzJ`Qju0fPt77_Rkw&3Q8XKCtpMF1TuXZfg zs@vR$Kf!lTF8~x#d&HsRZR(WKhJ3E|VKDLeN(Py60>LTD)wd;mv&+v0y)`H3a^SW` zX z);0|zPsX}!XbO1NG#Z$po}A_huTcUT&t|Xj;82cXW8EJz{b^3`sKnpP1q0%Q1V#imqKkhIS=*{6@V%XZr_r4Q9o+Xj
    {C9oxX5AVY4v3)5=gr{P_X~J{uaEEQt?wsG{pd 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

    - Prefer your phone? WLED Native discovers projectMM devices automatically and gives each a power toggle and brightness slider: + Prefer your phone, or your smart home? Control it from WLED Native or Home Assistant β€” see the getting-started guide.

    -

    - Or bring it into your smart home: projectMM adopts into Home Assistant as a light entity (on/off + brightness). -

    -

    From 269315f560af58d4162ef9ac64e2f921aaf70bf0 Mon Sep 17 00:00:00 2001 From: ewowi Date: Thu, 23 Jul 2026 18:04:11 +0200 Subject: [PATCH 4/9] Consolidate parallel LED drivers into one module; fix reviewer blockers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three parallel LED drivers (MultiPin/Moon/Parlio) become one registered ParallelLedDriver whose `peripheral` control picks the DMA bus backend at runtime, plus fixes for two crash/robustness bugs the pre-commit reviewer found on the feature's headline paths (a live peripheral swap left the control list dangling; a string palette value dereferenced a function pointer). Verified live on the S3 and classic Olimex. KPI: 16384lights | Desktop:755KB | tick:130/106/2/6/131/21/3/287/73/18/23/169/129/23/6/47us(FPS:7692/9433/500000/166666/7633/47619/333333/3484/13698/55555/43478/5917/7751/43478/166666/21276) | src:195(46120) | test:138(24852) | lizard:160w (ESP32 live tick omitted: the configured KPI port is stale and boards were on other ports; all 3 ESP32 variants built clean and the fixes were hardware-verified on S3 + classic over the API.) Core: - ParallelLedDriver: the CRTP base + 3 driver subclasses collapse into one plain MoonModule holding a runtime LedPeripheral*; the `peripheral` Select picks the backend, board-filtered to lanesAvailable()>0, with a per-hardware-block claim guard so two same-block drivers can't corrupt each other. - ParallelLedDriver: fix the live peripheral swap double-swapping (rebuildControls already swaps in the new backend; onControlChanged now calls ensurePeripheralMatchesSelection, a no-op post-rebuild, instead of a second swapPeripheral that freed the just-bound backend and dangled the control list). - ParallelLedDriver: gate hwBlock() on inited_ so a refused/uninited sibling no longer phantom-claims its peripheral block and darks a live wall on an unrelated prepare sweep. - LedPeripheral: new runtime strategy interface (bus lifecycle + descriptors + ring/bus-pin cluster) with a self-registering per-backend factory registry gated by CONFIG_SOC_*, so a chip links only its usable backends. - Control.cpp: split the Select/Palette apply so the option-label string match runs for Select only; a Palette's aux is a PaletteOptionsFn (function pointer), so a string palette value now falls to numeric apply instead of dereferencing code bytes (crash on ESP32; Robust to any input). - SystemModule: correct a stale comment (logLevel re-applies via onControlChanged, not affectsPrepare). Light domain: - I80Peripheral / MoonI80Peripheral / ParlioPeripheral: the three backends become LedPeripheral implementations, each self-registering under its label; reframed the class docs from "thin driver subclass" to "peripheral backend". Tests: - unit_ParallelLedDriver_swap: new regression pinning the double-swap (registers two owned mock backends, drives the real setControl sequence; counts attached-backend destructions, which is 2 with the bug and 1 with the fix β€” verified green->red). - unit_Control_apply_absent_key: added a string-palette-value case (must not crash, applies numerically) and a Select-label case (label match still works). - unit_{MultiPin,Moon,Parlio}LedDriver + the ring/doublebuffer/pinexpander mocks: retargeted to construct ParallelLedDriver + inject the matching backend. Docs / CI: - MIGRATING: the 3-drivers-merge entry; and the older 2026-07-16 rename entry now points forward to the current type (the two intermediate names it named no longer exist). - drivers.md: the comparison table is now peripheral rows under the one Parallel LED driver, not three separate driver cards. - architecture.md, mhc-p4-shield, s31-coreboard: old driver names -> the Parallel LED driver + peripheral model. - CLAUDE.md: added the Researcher role row + the "delegate the mechanical roles" heuristic note. Reviews: - πŸ‘Ύ peripheral swap double-free / dangling control list: fixed (ensurePeripheralMatchesSelection in onControlChanged), regression-tested, verified live on S3. - πŸ‘Ύ string palette value crash (function-pointer deref): fixed (Select-only label match), regression-tested, verified live on S3 + classic. - πŸ‘Ύ claim guard phantom-claim: fixed (hwBlock gated on inited_). - πŸ‡ Plan-20260722/23 wording (Generalise->Generalize, five->four classes), index.html ha-badge empty alt, _moondeck_config Request-inside-try: fixed. KPI Details: Desktop: 16,384 lights | 755 KB | 837 test cases pass | 21 scenarios pass | boundary PASS | specs 87/87 ESP32: image 1,493,812 bytes (64% partition free) Code: 195 src (46120 lines), 138 test (24852 lines), 146 specs, 21 scenarios, lizard 160w --- CLAUDE.md | 3 + docs/MIGRATING.md | 14 +- docs/architecture.md | 2 +- docs/gettingstarted.md | 2 + ... scope - effect breadth + rename runway.md | 2 +- ...s into one module + peripheral strategy.md | 4 +- docs/moonmodules/light/drivers.md | 44 +- docs/reference/esp32-s31-coreboard.md | 2 +- docs/reference/mhc-wled-esp32-p4-shield.md | 4 +- moondeck/_moondeck_config.py | 7 +- src/core/Control.cpp | 32 +- src/core/SystemModule.h | 2 +- src/light/drivers/DriverBase.h | 7 + src/light/drivers/LedPeripheral.h | 130 +++++ src/light/drivers/MoonLedDriver.h | 310 ++++++----- src/light/drivers/MultiPinLedDriver.h | 159 +++--- src/light/drivers/ParallelLedDriver.h | 516 ++++++++++++------ src/light/drivers/ParlioLedDriver.h | 81 +-- src/main.cpp | 29 +- test/CMakeLists.txt | 1 + test/scenarios/light/scenario_perf_full.json | 21 +- .../core/unit_Control_apply_absent_key.cpp | 45 ++ test/unit/light/unit_MoonLedDriver.cpp | 100 +++- test/unit/light/unit_MultiPinLedDriver.cpp | 135 +++-- .../unit_ParallelLedDriver_doublebuffer.cpp | 220 ++++---- .../unit_ParallelLedDriver_pinexpander.cpp | 233 +++++--- .../light/unit_ParallelLedDriver_ring.cpp | 405 ++++++++------ .../light/unit_ParallelLedDriver_swap.cpp | 191 +++++++ test/unit/light/unit_ParlioLedDriver.cpp | 95 ++-- web-installer/deviceModels.json | 68 ++- web-installer/index.html | 5 +- 31 files changed, 1910 insertions(+), 959 deletions(-) create mode 100644 src/light/drivers/LedPeripheral.h create mode 100644 test/unit/light/unit_ParallelLedDriver_swap.cpp diff --git a/CLAUDE.md b/CLAUDE.md index f446b6a4..70ebf6d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -259,9 +259,12 @@ The project uses Claude Code agents in defined roles. The user is the **Product | πŸ‘Ύ | **Reviewer** | **Fable** (Opus only if Fable is unavailable) | Pre-merge check | Runs at PR merge over the whole branch diff (Event 2, gate 5), and pre-commit on the staged diff when the commit is large or the product owner asks (see *Reviewer at commit-time*). The model is fixed, not a per-run choice. Complements CodeRabbit (which handles line-level bugs in the PR). | | πŸ›Έ | **Tester** | Sonnet | Verification | Writes tests, verifies architectural rules in code | | πŸ’€ | **Runner** | Haiku | Quick checks | Runs MoonDeck scripts, platform boundary checks, build verification | +| πŸ”¬ | **Researcher** | **Fable** (same as Reviewer) | Investigation | Read-only fan-out over the codebase (or friend repos / datasheets) to answer a scoped question before a design or change β€” an interface inventory, a blast-radius map, a prior-art survey. Returns the conclusion, not file dumps. Feeds the Architect's plan and the Developer's spec. | Agents work in parallel on independent steps. Agents never commit; only the product owner approves commits after testing. +**Delegate the mechanical roles; don't absorb them.** The main loop tends to *become* the Runner/Tester/Researcher rather than spawning them β€” running every gate inline, writing every test itself. That is the right call for a **single fast check** (a lone `check_specs`, one `git status`) where the spawn round-trip costs more than the work. But **delegate when the work is parallelizable or substantial**: the pre-commit gate fan-out is textbook **Runner** work (Haiku, in parallel, cheaper and faster than serial-inline); pinning a fixed bug with a regression test through the real code path is a clean **Tester** spec (find the mechanism yourself, hand Tester the spec, verify the result); a broad "map the interface / blast radius / prior art before we design" is **Researcher** work (Fable, read-only fan-out). The heuristic: *parallelizable or substantial β†’ delegate; a single fast check β†’ inline.* + ## Build How to build, flash, run, monitor, and check the project for every target: [docs/building.md](docs/building.md). Per-script reference: [moondeck/MoonDeck.md](moondeck/MoonDeck.md). diff --git a/docs/MIGRATING.md b/docs/MIGRATING.md index adcb8c06..4d247337 100644 --- a/docs/MIGRATING.md +++ b/docs/MIGRATING.md @@ -20,6 +20,18 @@ projectMM ships **no migration code**: the persistence layer is robust by defaul ## Unreleased (`next-iteration`) +### The three parallel LED drivers merge into one `ParallelLedDriver` with a `peripheral` selector (2026-07-23) + +`MultiPinLedDriver`, `MoonLedDriver`, and `ParlioLedDriver` are now one registered module, **`ParallelLedDriver`**, whose `peripheral` control picks which DMA peripheral drives the parallel WS2812 bus. They were always the same driver with a different bus backend; the merge makes that one card with a dropdown, offering only the peripherals the chip supports. + +| Old registered type | New | +|---|---| +| `MultiPinLedDriver` | `ParallelLedDriver` + `peripheral` = `i80` (esp_lcd: LCD_CAM on S3/P4, I2S on classic) | +| `MoonLedDriver` | `ParallelLedDriver` + `peripheral` = `MoonI80` (own-GDMA below esp_lcd, LCD_CAM) | +| `ParlioLedDriver` | `ParallelLedDriver` + `peripheral` = `Parlio` (P4) | + +**Action: re-add the driver.** A persisted module whose type is one of the three old names no longer resolves (the type isn't registered), so the robust loader drops it on boot β€” the driver, and its pins/settings, vanish from the tree. Add a **Parallel LED** driver again, choose the `peripheral` your board uses (the same backend the old type named β€” see the table), and re-enter its pins / lengths / clock pin. The web installer's board catalog already names the new type, so a fresh install or a catalog re-inject wires it correctly; only a device carrying an OLD persisted tree needs the manual re-add. + ### `AudioService`: the `sync` control becomes `mode` + `send audio`, and `simulate` is renumbered (2026-07-22) The audio module's identity is now a single `mode` control (Local audio / Receive network / Simulate), each showing only its own detail controls, replacing the separate `sync` (off / send / receive) toggle. Broadcasting the locally-analyzed frame moved to a `send audio` switch, meaningful only in Local mode. `simulate` was also renumbered, from a five-option list to two. @@ -62,7 +74,7 @@ The LED driver module types and several controls were renamed so the UI reads in **Action: re-add the module, then re-set `pinExpander` / `doubleBuffer` if you had changed them.** -A device whose persisted config names the old module type loads a module type that no longer exists β€” the unknown type is ignored, so **the driver is absent from the tree on boot**. Re-add it (`MultiPinLedDriver` or `MoonLedDriver`) and re-enter its controls. Within a re-added driver, the two renamed *settable* controls (`pinExpander`, `doubleBuffer`) read as absent β†’ they take their defaults (`pinExpander` off, `doubleBuffer` on); set them again if your board needs otherwise. `frameTime` and `renderWait` are read-only KPIs β€” nothing to restore. +A device whose persisted config names the old module type loads a module type that no longer exists β€” the unknown type is ignored, so **the driver is absent from the tree on boot**. Re-add a **Parallel LED** driver (the single type the two later merged into β€” see the 2026-07-23 entry above for the `peripheral` value that matches the old `I80LedDriver` / `MoonI80LedDriver`) and re-enter its controls. Within a re-added driver, the two renamed *settable* controls (`pinExpander`, `doubleBuffer`) read as absent β†’ they take their defaults (`pinExpander` off, `doubleBuffer` on); set them again if your board needs otherwise. `frameTime` and `renderWait` are read-only KPIs β€” nothing to restore. `RmtLedDriver` and `ParlioLedDriver` are unchanged. The `pins` / `ledsPerPin` / `clockPin` / `latchPin` / `loopback*` controls are unchanged. diff --git a/docs/architecture.md b/docs/architecture.md index d9e66cba..b622a96c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -469,7 +469,7 @@ The shared output buffer is necessary when blend+map writes to arbitrary physica Each driver (a MoonModule) speaks one protocol: -- **LED drivers**: WS2812 via RMT (multi-pin), plus two parallel-output paths on the newer chips. The S3's LCD_CAM i80 bus ([MultiPinLedDriver](moonmodules/light/moxygen/MultiPinLedDriver.md)) drives exactly 8 data GPIOs β€” the i80 bus claims every data line of its width, so a partial set is rejected. The P4's Parlio peripheral ([ParlioLedDriver](moonmodules/light/moxygen/ParlioLedDriver.md)) drives 1–8 lanes β€” it takes the data GPIOs directly, so any count up to 8 is valid. Both are DMA-driven. Platform-specific; all behind the platform boundary. +- **LED drivers**: WS2812 via RMT (multi-pin), plus one DMA-driven parallel driver ([ParallelLedDriver](moonmodules/light/moxygen/ParallelLedDriver.md)) whose `peripheral` control picks the bus backend the chip supports β€” the S3/P4 LCD_CAM i80 bus, our own-GDMA MoonI80 (LCD_CAM, adds the streaming ring + 74HCT595 expander), or the P4's Parlio. All are DMA-driven and behind the platform boundary; the driver rounds an i80 bus up around whatever pin count is configured (any count from 1) and parks unused lanes on a pin already driven. - **DMX / ArtNet**: sends DMX over UDP. Supports addressable LEDs and conventional DMX fixtures (pars, moving heads, dimmers). - **Preview**: streams light data to the web UI via WebSocket. - **Desktop output**: SDL2 or terminal for visual preview. Desktop also serves as a high-speed processing node, driving lights via ArtNet/DDP over the network. diff --git a/docs/gettingstarted.md b/docs/gettingstarted.md index 71867e2c..1e80dbcd 100644 --- a/docs/gettingstarted.md +++ b/docs/gettingstarted.md @@ -199,6 +199,8 @@ USB cable needed once it's on your network. ![The Firmware module](assets/gettingstarted/02-06-UI-Firmware.png) +> **Updating from an older build?** Skim the [migration notes](MIGRATING.md) first. Most updates need nothing β€” the device keeps your settings β€” but a breaking change is listed there with the one action it costs you (usually re-setting or re-adding a control). + > [FirmwareUpdateModule](moonmodules/core/system.md#firmware-update) **Network** β€” your connection: WiFi or Ethernet, signal strength, and the diff --git a/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md b/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md index 3f0e0452..ac6033af 100644 --- a/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md +++ b/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md @@ -14,7 +14,7 @@ This is a roadmap/scope plan, not a single-feature `/plan`. Each item below gets This is the biggest lever and the explicit *"execution vehicle for the effect-breadth parity gate."* ~21 of the predecessor's 60+ effects are ported. Stage 1's prerequisites are the highest-value core work available, because every future effect leans on them: -- **Shared palette** β€” hard prerequisite; many effects color via `ColorFromPalette`. Generalise the pattern `PlasmaPaletteEffect` hard-codes today. +- **Shared palette** β€” hard prerequisite; many effects color via `ColorFromPalette`. Generalize the pattern `PlasmaPaletteEffect` hard-codes today. - **The shared primitive library** β€” FastLED-named, our own implementation, hot-path-tuned integer-only: `beatsin8`, `inoise8`, `qadd8`, `nscale8`, `random8`/`random16`, `ColorFromPalette`, and the dimension-agnostic draw set. Extends the existing `color.h` (`scale8`, `sin8`). - **Tag/emoji legend** β€” settle before batch-migrating so every module is consistent from batch one. - **Per-library doc model** β€” `effects_.md` compact table rows (per [ADR 0015](../../adr/0015-library-is-a-tag-not-a-folder.md)); changes the `check_specs.py` contract. diff --git a/docs/history/plans/Plan-20260723 - Consolidate parallel LED drivers into one module + peripheral strategy.md b/docs/history/plans/Plan-20260723 - Consolidate parallel LED drivers into one module + peripheral strategy.md index 942daf6c..0f931fa7 100644 --- a/docs/history/plans/Plan-20260723 - Consolidate parallel LED drivers into one module + peripheral strategy.md +++ b/docs/history/plans/Plan-20260723 - Consolidate parallel LED drivers into one module + peripheral strategy.md @@ -2,7 +2,7 @@ ## Context -The parallel-LED output today is **five classes**: a CRTP base `ParallelLedDriver` (1816 lines, all shared logic) and three concrete CRTP subclasses, each a full `MoonModule`: `MoonLedDriver` (703 lines, own-GDMA + streaming ring + 74HCT595 expander, LCD_CAM only), `MultiPinLedDriver` (256 lines, esp_lcd i80 on S3/P4 LCD_CAM + classic I2S), `ParlioLedDriver` (100 lines, P4 Parlio). Each is separately factory-registered, so the UI add-module picker offers all three on **every** board β€” including ones that can't run them (`lanesAvailable()==0`). +The parallel-LED output today is **four classes**: a CRTP base `ParallelLedDriver` (1816 lines, all shared logic) and three concrete CRTP subclasses, each a full `MoonModule`: `MoonLedDriver` (703 lines, own-GDMA + streaming ring + 74HCT595 expander, LCD_CAM only), `MultiPinLedDriver` (256 lines, esp_lcd i80 on S3/P4 LCD_CAM + classic I2S), `ParlioLedDriver` (100 lines, P4 Parlio). Each is separately factory-registered, so the UI add-module picker offers all three on **every** board β€” including ones that can't run them (`lanesAvailable()==0`). The product owner wants **one** user-facing "Parallel LED" module with a **peripheral dropdown** that surfaces the shared controls plus the selected peripheral's unique controls, allocating only the selected backend. @@ -10,7 +10,7 @@ The product owner wants **one** user-facing "Parallel LED" module with a **perip **Hot path is safe:** every `busX()` call is per-frame or per-reinit, never per-light (the per-light encode operates on the raw `uint8_t*` from `busBuffer()`). One vcall/frame vs ~3500Β΅s of frame work is negligible. CRTP's "no runtime indirection" protected per-*light* calls, which this design does not add. -**Net effect β€” a subtraction refactor + a feature:** 5 classes β†’ 1 module + 1 interface + 3 stripped backends; one control set, one lifecycle, one registry entry, one UI card; the backends shrink (lose MoonModule/control/lifecycle scaffolding). Plus the one-selectable-card UX. +**Net effect β€” a subtraction refactor + a feature:** 4 classes β†’ 1 module + 1 interface + 3 stripped backends; one control set, one lifecycle, one registry entry, one UI card; the backends shrink (lose MoonModule/control/lifecycle scaffolding). Plus the one-selectable-card UX. **Scope boundary β€” `RmtLedDriver` stays separate (evaluated, deliberate).** RmtLed is `: public DriverBase`, NOT a `ParallelLedDriver<>` subclass. It is a different *shape*: N independent per-pin RMT TX channels + a symbol encoder, versus the parallel family's single lockstep DMA bus + bit-transpose. The genuine overlap (pin/count parsing) is already factored into the shared `PinList.h` helper β€” the correct dedup. Folding RmtLed behind the `LedPeripheral` interface (built around a single DMA bus: `busBuffer`/`busTransmit(i,bytes)`/`busCapacity`/ring/double-buffer) would be a *leaky* abstraction carrying ops half its implementers can't honor β€” an expansion, not a reduction. Two coherent concepts stay two modules. diff --git a/docs/moonmodules/light/drivers.md b/docs/moonmodules/light/drivers.md index 4a537875..79205721 100644 --- a/docs/moonmodules/light/drivers.md +++ b/docs/moonmodules/light/drivers.md @@ -24,6 +24,7 @@ Detail: [technical](moxygen/DriverBase.md) ## LED drivers + @@ -31,21 +32,34 @@ Detail: [technical](moxygen/DriverBase.md) ### LED driver πŸ’« Β· wire -Addressable WS2812B-class LEDs over a wire. Four drivers, same controls and same wire contract; they differ in how many strands clock out at once and on which chip. **Start with RMT** for a few strands, **MultiPin** for many (up to 16), **Parlio** on a P4 β€” and **Moon** when you need more lights than one DMA buffer holds, or more strands than you have GPIOs (its 74HCT595 pin expander turns 6 pins into 48 strands). Which to pick, and why: [details](#led-driver-details). +Addressable WS2812B-class LEDs over a wire, same controls and same wire contract however the bits reach the pins. Two drivers: **RMT** for a few strands, and **ParallelLedDriver** for many (up to 16) clocked out at once. The parallel driver has a **`peripheral`** control that picks the DMA peripheral, offering only the ones the chip supports: + +- **`i80`** β€” the esp_lcd i80 bus (LCD_CAM on the S3/P4, the I2S peripheral on the classic ESP32). The general default for many strands. +- **`Parlio`** β€” the P4's Parallel-IO peripheral. +- **`MoonI80`** β€” our own GDMA below esp_lcd (LCD_CAM only): a *streaming ring* for more lights than one DMA buffer holds, plus a 74HCT595 **pin expander** that turns 6 pins into 48 strands. + +Which to pick, and why: [details](#led-driver-details). LED output driver controls Plus the [shared controls](#shared-driver-controls) above: -- `pins` β€” data GPIO list, e.g. `18,17,16`, or inclusive ranges like `20-23` (= `20,21,22,23`) mixed freely (`20-22,35,38-40`). One strand each β€” or, with Moon's pin expander, one *group of 8*. Empty idles until set; changing it re-inits live. +The card reads top-down as **invariant controls β†’ `peripheral` divider β†’ peripheral-specific controls**: + +- `pins` β€” data GPIO list, e.g. `18,17,16`, or inclusive ranges like `20-23` (= `20,21,22,23`) mixed freely (`20-22,35,38-40`). One strand each β€” or, with the `MoonI80` pin expander, one *group of 8*. Empty idles until set; changing it re-inits live. - `ledsPerPin` β€” lights per **strand**, following the broadcasting idiom (cf. NumPy / CSS shorthand): **empty** = even split of the window; **one number** = that many on *every* strand (`64` β†’ 64 each); **a list** `3,4,5` = one per strand by position (a short list even-splits the remainder). Shorter strands go dark early while the longest finishes. Through an expander an entry is one strand, not one pin, so two strands on one '595 can differ. -- **Expert-only** (πŸ”§, shown when `System.expertMode` is on): `loopbackTest` β€” a TXβ†’RX loopback self-test (jumper the first pin to `loopbackRxPin`), verdict in the status field, with `loopbackTxPin`/`loopbackRxPin` its wiring. Moon adds `shiftOverclock` and the manual `ring*` geometry knobs (below). +- `doubleBuffer`, `pinExpander` β€” output shape, also invariant across peripherals. +- `peripheral` (the **divider**) β€” the DMA peripheral driving the bus (`i80` / `Parlio` / `MoonI80`), filtered to what the chip supports. Everything **above** it is invariant (*which LEDs and how many*); everything **below** is what the chosen peripheral needs. Switching it re-surfaces that peripheral's own controls and re-inits live. Always shown β€” with a single option it reads as a labelled indicator of what's driving the LEDs. +- *peripheral-specific* (below the divider) β€” `i80`: the WR/DC bus pins (`clockPin`/`dcPin`). `MoonI80`: `shiftOverclock` and the `ring*` geometry cluster. `Parlio`: none. +- **Expert-only** (πŸ”§, shown when `System.expertMode` is on): `loopbackTest` β€” a TXβ†’RX loopback self-test (jumper the first pin to `loopbackRxPin`), verdict in the status field, with `loopbackTxPin`/`loopbackRxPin` its wiring. + +Two ParallelLedDriver instances that select peripherals on the **same hardware block** (e.g. both `i80` and `MoonI80`, which share LCD_CAM) conflict β€” the second idles with a status. Different blocks (RMT + `Parlio` + `i80` on a P4) coexist. Origin: WS2812B on FastLED / hpwit / WLED prior art ([analysis](../../history/leddriver-analysis-top-down.md)) -Tests: [RMT](../../tests/unit-tests.md#rmtleddriver) Β· [MultiPin](../../tests/unit-tests.md#multipinleddriver) Β· [Moon](../../tests/unit-tests.md#moonleddriver) Β· [Parlio](../../tests/unit-tests.md#parlioleddriver) Β· [shared](../../tests/unit-tests.md#parallelleddriver) +Tests: [RMT](../../tests/unit-tests.md#rmtleddriver) Β· [shared + peripherals](../../tests/unit-tests.md#parallelleddriver) -Detail: [RMT](moxygen/RmtLedDriver.md) Β· [MultiPin](moxygen/MultiPinLedDriver.md) Β· [Moon](moxygen/MoonLedDriver.md) Β· [Parlio](moxygen/ParlioLedDriver.md) +Detail: [RMT](moxygen/RmtLedDriver.md) Β· [Parallel](moxygen/ParallelLedDriver.md) Β· peripherals: [i80](moxygen/MultiPinLedDriver.md) Β· [MoonI80](moxygen/MoonLedDriver.md) Β· [Parlio](moxygen/ParlioLedDriver.md) ## Network drivers @@ -123,23 +137,23 @@ Detail: [technical](moxygen/PreviewDriver.md) **Moon and MultiPin drive the same pins the same way; only the DMA underneath differs.** Start with MultiPin β€” it is the proven path. Choose Moon when you hit one of its two limits. Both are registered module types, so you can swap them in the UI on one board with no reflash. -**The four, compared.** All drive WS2812B-class strips with the same `pins` / `ledsPerPin` / `loopback*` controls and the same wire contract; they differ in parallelism, chip, and β€” for the two i80-bus entries (**MultiPin** and **Moon**) β€” in who programs the DMA. +**RMT vs the three parallel peripherals.** All drive WS2812B-class strips with the same `pins` / `ledsPerPin` / `loopback*` controls and the same wire contract; they differ in parallelism, chip, and β€” for the two i80-bus peripherals (**i80** and **MoonI80**) β€” in who programs the DMA. RMT is its own driver; the parallel peripherals are the `peripheral` choices on the one **Parallel LED** driver above. **Lane, pin, strand.** A **lane** is one bus data line; a **strand** is one chain of LEDs. The i80 **bus** is 8 or 16 lanes wide (a hardware fact β€” `lcd_ll_set_data_wire_width` takes nothing else), but you configure only the **pins** that drive something, at any count from 1: the driver rounds the bus up around them and parks the spare lanes on a pin the peripheral already drives, where nothing reads them. - **Direct:** one pin = one lane = one strand. 1–16 strands. - **Through an expander:** each data pin feeds one '595 and fans out to 8 strands, so **1–8 data pins β†’ up to 64 strands** (the driver's ceiling). The **latch** also costs a lane β€” the peripheral has only one clock output, so it has to ride a data line β€” but the strand ceiling binds first. hpwit's board populates 6 pins β†’ **48 strands**. -| Driver | Chip | Strands | Extra controls | Notes | -|---|---|---|---|---| -| **RMT** ([detail](moxygen/RmtLedDriver.md)) | any ESP32 (classic 8 ch, S3 4, P4 4 DMA) | one per RMT TX channel | `loopbackFrame` | The general single-/few-strand output; default for classic + S3 board entries. `loopbackFrame` bit-verifies a *whole frame*, catching frame-rate / RF corruption a 24-bit burst misses. | -| **MultiPin** ([detail](moxygen/MultiPinLedDriver.md)) | S3 / P4 (LCD_CAM) Β· classic (I2S) | **1–16** | `clockPin` `dcPin` | One driver over IDF's `esp_lcd` i80 bus. The **bus** is 8 or 16 bits wide (≀8 pins β†’ 8-bit, 9–16 β†’ 16-bit) β€” but the **pin count is free**: configure only the pins that drive something and the driver rounds the bus up around them, parking the spare lanes on a pin the peripheral already drives. `clockPin`/`dcPin` are i80 bus lines the LEDs ignore. **Capped by one contiguous DMA buffer**: the classic backend is internal-RAM only (I2S can't reach PSRAM) β†’ **2048 lights**; LCD_CAM draws from PSRAM β†’ **16384**. Over the cap it idles with a status rather than crashing. | -| **Moon** ([detail](moxygen/MoonLedDriver.md)) | S3 / P4 (LCD_CAM only) | **1–16**; Γ—8 per pin with an expander (**6 pins β†’ 48 strands**) | `clockPin` `pinExpander` `latchPin` `useRing` `ringAuto`; πŸ”§ `shiftOverclock` `ringRows` `ringBufs` `ringPadUs` | The same LCD_CAM output as MultiPin on **our own GDMA chain**, which buys two things `esp_lcd` cannot: a frame **streamed** through a small buffer pool instead of held whole (so length stops being a memory question), and a **74HCT595 pin expander** β€” one GPIO fans out to 8 strands. `ringAuto` (default on) derives the streaming geometry per config, so the manual `ring*` knobs and `shiftOverclock` (a faster '595 clock for short-wired rigs) are expert-only tuning β€” the full guide is on the technical page. No `dcPin` at all, and WR is routed only when a '595 needs it as its shift clock. Not on the classic ESP32 (its i80 is the I2S peripheral). The prime-only ring (frame fits the buffer pool) and the pin expander are wall-solid; the **lapping** ring (very long strands, where the ISR refills from a PSRAM source) has a known last-row sparkle on the largest configs, tracked in [the backlog](../../backlog/backlog-light.md). Why + what it costs: [ADR-0014](../../adr/0014-own-i80-dma-driver-below-esp-lcd.md). | -| **Parlio** ([detail](moxygen/ParlioLedDriver.md)) | ESP32-P4 | **1–16** | β€” | The P4's parallel path; Parlio generates its own pixel clock, so no clock/dc pins to spend. Bus width follows the pin count. On P4-NANO a known-good 8-set is `20,21,22,23,24,25,26,27`. | +| Output | `peripheral` | Chip | Strands | Extra controls | Notes | +|---|---|---|---|---|---| +| **RMT** ([detail](moxygen/RmtLedDriver.md)) | *(own driver)* | any ESP32 (classic 8 ch, S3 4, P4 4 DMA) | one per RMT TX channel | `loopbackFrame` | The general single-/few-strand output; default for classic + S3 board entries. `loopbackFrame` bit-verifies a *whole frame*, catching frame-rate / RF corruption a 24-bit burst misses. | +| Parallel LED | **`i80`** | S3 / P4 (LCD_CAM) Β· classic (I2S) | **1–16** | `clockPin` `dcPin` | Over IDF's `esp_lcd` i80 bus. The **bus** is 8 or 16 bits wide (≀8 pins β†’ 8-bit, 9–16 β†’ 16-bit) β€” but the **pin count is free**: configure only the pins that drive something and the driver rounds the bus up around them, parking the spare lanes on a pin the peripheral already drives. `clockPin`/`dcPin` are i80 bus lines the LEDs ignore. **Capped by one contiguous DMA buffer**: the classic backend is internal-RAM only (I2S can't reach PSRAM) β†’ **2048 lights**; LCD_CAM draws from PSRAM β†’ **16384**. Over the cap it idles with a status rather than crashing. | +| Parallel LED | **`MoonI80`** | S3 / P4 (LCD_CAM only) | **1–16**; Γ—8 per pin with an expander (**6 pins β†’ 48 strands**) | `clockPin` `pinExpander` `latchPin` `useRing` `ringAuto`; πŸ”§ `shiftOverclock` `ringRows` `ringBufs` `ringPadUs` | The same LCD_CAM output as `i80` on **our own GDMA chain**, which buys two things `esp_lcd` cannot: a frame **streamed** through a small buffer pool instead of held whole (so length stops being a memory question), and a **74HCT595 pin expander** β€” one GPIO fans out to 8 strands. `ringAuto` (default on) derives the streaming geometry per config, so the manual `ring*` knobs and `shiftOverclock` (a faster '595 clock for short-wired rigs) are expert-only tuning β€” the full guide is on the technical page. No `dcPin` at all, and WR is routed only when a '595 needs it as its shift clock. Not on the classic ESP32 (its i80 is the I2S peripheral). The prime-only ring (frame fits the buffer pool) and the pin expander are wall-solid; the **lapping** ring (very long strands, where the ISR refills from a PSRAM source) has a known last-row sparkle on the largest configs, tracked in [the backlog](../../backlog/backlog-light.md). Why + what it costs: [ADR-0014](../../adr/0014-own-i80-dma-driver-below-esp-lcd.md). | +| Parallel LED | **`Parlio`** | ESP32-P4 | **1–16** | β€” | The P4's parallel path; Parlio generates its own pixel clock, so no clock/dc pins to spend. Bus width follows the pin count. On P4-NANO a known-good 8-set is `20,21,22,23,24,25,26,27`. | -The detail pages carry each driver's wire contract, buffer slicing, memory sizing, and the loopback self-test. +The [Parallel LED technical page](moxygen/ParallelLedDriver.md) carries the wire contract, buffer slicing, memory sizing, and the loopback self-test; each peripheral's own page ([i80](moxygen/MultiPinLedDriver.md) Β· [MoonI80](moxygen/MoonLedDriver.md) Β· [Parlio](moxygen/ParlioLedDriver.md)) covers its DMA specifics. -**What the parallel drivers share.** MultiPin, Moon and Parlio are thin peripheral shells over two common pieces β€” worth reading if you care how a frame is actually built: +**What the peripherals share.** The three parallel peripherals are thin shells the one Parallel LED driver selects between; two common pieces do the real work β€” worth reading if you care how a frame is actually built: -- **[Parallel LED driver base](moxygen/ParallelLedDriver.md)** β€” the shared body: strand slicing, the encode loop, the async double-buffer, the latch pad, the loopback self-test. A derived driver adds only its peripheral's DMA calls. +- **[Parallel LED driver](moxygen/ParallelLedDriver.md)** β€” the shared body: strand slicing, the encode loop, the async double-buffer, the latch pad, the loopback self-test. A peripheral backend adds only its own DMA calls. - **[Slot encoder](moxygen/ParallelSlots.md)** β€” the wire format itself. Each WS2812 bit becomes three bus slots (pulse start / data / tail), and the data slot is an **8Γ—8 bit transpose**: lanes in, bit-planes out, so one bus word carries the same bit of every strand. It is the render loop's measured hot spot. diff --git a/docs/reference/esp32-s31-coreboard.md b/docs/reference/esp32-s31-coreboard.md index 1160a5fd..aec5e42d 100644 --- a/docs/reference/esp32-s31-coreboard.md +++ b/docs/reference/esp32-s31-coreboard.md @@ -123,7 +123,7 @@ The two pins in **one column are physically stacked**, so a 2-pin jumper cap bri **Recommended assignment** (what the S31 catalog entry uses): - **LED strip data:** the onboard WS2812 is on **GPIO 60** (the catalog default). For an *external* strand, use **GPIO 42** as the single-lane pick; a parallel rig (RMT/Parlio) takes the free block (**36–49**, skipping 41 which isn't broken out) for several lanes. **GPIO 4** (col 16 top) also works as an LED data pin and sits one column from the `G` / `3V3` / `5V` power rail (cols 17–20), so a single strip's data + ground + 5 V wires land close together β€” handy for a tidy 3-wire pigtail. It's a plain I/O with no strap or peripheral tie on this board (the SD lines beside it, D0–D3 / CLK / CMD, are broken out by function name, not GPIO number, so GPIO 4 is *not* one of them; it just neighbours that cluster on the header). The only reason it reads as "distinct" from the rest of the free run is its header position β€” it's over by the SD/power group rather than in the low-block on cols 8–12. -- **Loopback self-test:** **Tx = GPIO 48, Rx = GPIO 47** β€” the two pins of **column 7** (48 top, 47 bottom), so a single jumper cap shorts them. A driver transmits a known WS2812 frame out Tx and reads it back on Rx to verify output on real silicon (same pattern as the P4-NANO bench's 32↔33). They sit at the top of the free run, clear of the operational LED pins so the strip wiring and the jumper don't interfere. **Bench-confirmed PASS on the S31 for both [RmtLedDriver](../moonmodules/light/drivers.md#rmtled) and [ParlioLedDriver](../moonmodules/light/drivers.md#parlioled)** β€” the two WS2812 output drivers the S31 supports. [LcdLedDriver](../moonmodules/light/drivers.md#led-drivers) is **not** one of them: it's the ESP32-S3-specific LCD_CAM i80 driver, and the RISC-V S31 has no LCD_CAM peripheral (it reports "no valid pins"). Testing several drivers in a row, they all default loopback to GPIO 48, so only one can hold the pin at a time β€” toggle each driver's `loopbackTest` off before testing the next. +- **Loopback self-test:** **Tx = GPIO 48, Rx = GPIO 47** β€” the two pins of **column 7** (48 top, 47 bottom), so a single jumper cap shorts them. A driver transmits a known WS2812 frame out Tx and reads it back on Rx to verify output on real silicon (same pattern as the P4-NANO bench's 32↔33). They sit at the top of the free run, clear of the operational LED pins so the strip wiring and the jumper don't interfere. **Bench-confirmed PASS on the S31 for both [RMT](../moonmodules/light/drivers.md#rmtled) and the [Parallel LED driver with peripheral `Parlio`](../moonmodules/light/drivers.md#parlioled)** β€” the two WS2812 output paths the S31 supports. The `i80` / `MoonI80` peripherals are **not** among them: they need the ESP32-S3/P4 LCD_CAM, and the RISC-V S31 has no LCD_CAM peripheral (the `peripheral` selector doesn't offer them, and forcing one reports "no valid pins"). Testing several drivers in a row, they all default loopback to GPIO 48, so only one can hold the pin at a time β€” toggle each driver's `loopbackTest` off before testing the next. ## SoC capabilities (from `components/soc/esp32s31/include/soc/soc_caps.h`) diff --git a/docs/reference/mhc-wled-esp32-p4-shield.md b/docs/reference/mhc-wled-esp32-p4-shield.md index 3edad817..6736ab52 100644 --- a/docs/reference/mhc-wled-esp32-p4-shield.md +++ b/docs/reference/mhc-wled-esp32-p4-shield.md @@ -22,11 +22,11 @@ The output/RS-485 terminals, left to right, with the P4 GPIO each carries: ### 12x outputs β€” level-shifted, single-ended (LED data) -The LED-data outputs. Each terminal is `O` on the silkscreen; a level shifter drives the 5 V strand from the P4's 3.3 V. The catalog wires the ParlioLedDriver to the first eight (`21,20,25,5,22,23,24,27`). +The LED-data outputs. Each terminal is `O` on the silkscreen; a level shifter drives the 5 V strand from the P4's 3.3 V. The catalog wires the Parallel LED driver (peripheral `Parlio`) to the first eight (`21,20,25,5,22,23,24,27`). | Terminal | GPIO | Note | |---|---|---| -| O21 O20 O25 O5 O23 O27 O22 O24 | 21 20 25 5 23 27 22 24 | LED lanes (ParlioLedDriver default) | +| O21 O20 O25 O5 O23 O27 O22 O24 | 21 20 25 5 23 27 22 24 | LED lanes (Parallel LED, peripheral `Parlio`, default) | | O7 / O8 | 7 / 8 | also the IΒ²C bus (SDA 7 / SCL 8, catalog I2cScan) | | O3 | 3 | also on RS-485 (`A-3-B`) β€” see note below | | O4 | 4 | also on RS-485 (`A-4-B`) β€” see note below | diff --git a/moondeck/_moondeck_config.py b/moondeck/_moondeck_config.py index 590f34b6..2a20ee61 100644 --- a/moondeck/_moondeck_config.py +++ b/moondeck/_moondeck_config.py @@ -69,9 +69,12 @@ def set_log_level(ips, index): never raised, so it can't fail the caller's real work (a KPI capture, a monitor session).""" body = json.dumps({"module": "System", "control": "logLevel", "value": index}).encode("utf-8") for ip in ips: - req = urllib.request.Request(f"http://{ip}/api/control", data=body, - headers={"Content-Type": "application/json"}, method="POST") try: + # Request() is inside the try too: a malformed IP makes its construction raise, and that + # must skip only this device β€” not abort the loop and strand the rest (which, under + # raised_log_level, would also skip the restore of every device after it). + req = urllib.request.Request(f"http://{ip}/api/control", data=body, + headers={"Content-Type": "application/json"}, method="POST") urllib.request.urlopen(req, timeout=3).read() except Exception: pass diff --git a/src/core/Control.cpp b/src/core/Control.cpp index 09203101..9ede4187 100644 --- a/src/core/Control.cpp +++ b/src/core/Control.cpp @@ -315,10 +315,38 @@ ApplyResult applyControlValue(const ControlDescriptor& c, mm::json::parseString(json, key, static_cast(c.ptr), maxLen); return ApplyResult::Ok; } - case ControlType::Select: - case ControlType::Palette: { + case ControlType::Select: { + const int hi = c.max > 0 ? c.max - 1 : 0; + // A Select value may be given as the option LABEL (a string) instead of the index. This is + // what makes a catalog config board-portable: the index into a board-FILTERED option list + // varies per chip (an S3 offers fewer peripherals than a P4), but the label is stable. Match + // the string against the options and use that row; fall back to the numeric index otherwise. + // Select-only: a Select's aux IS the options array (const char* const*); Palette's aux is a + // PaletteOptionsFn (a function pointer), so it must not reach this reinterpret_cast. + char label[24] = {}; + mm::json::parseString(json, key, label, sizeof(label)); + if (label[0]) { + auto* options = reinterpret_cast(c.aux); + if (options) + for (int i = 0; i <= hi; i++) + if (options[i] && std::strcmp(options[i], label) == 0) + return clampInto(static_cast(c.ptr), i, 0, hi); + // A label that names no current option (e.g. a peripheral this board can't run) is not an + // error in Lenient policy β€” the driver keeps its default; Strict rejects it. + if (policy == ApplyPolicy::Strict) return ApplyResult::OutOfRange; + return ApplyResult::Ok; + } int v = mm::json::parseInt(json, key); + if (policy == ApplyPolicy::Strict && (v < 0 || v > hi)) { + return ApplyResult::OutOfRange; + } + return clampInto(static_cast(c.ptr), v, 0, hi); + } + case ControlType::Palette: { + // Palette carries a PaletteOptionsFn in aux (not an options array), so it stays numeric-index + // only β€” no label match. A string value parses to 0 via parseInt, the harmless prior behavior. const int hi = c.max > 0 ? c.max - 1 : 0; + int v = mm::json::parseInt(json, key); if (policy == ApplyPolicy::Strict && (v < 0 || v > hi)) { return ApplyResult::OutOfRange; } diff --git a/src/core/SystemModule.h b/src/core/SystemModule.h index af38aab5..67af2737 100644 --- a/src/core/SystemModule.h +++ b/src/core/SystemModule.h @@ -337,7 +337,7 @@ class SystemModule : public MoonModule { // Serial log verbosity, persisted, default Warn. Controls how chatty the device is on the wire: // at Warn the once-a-second KPI tick line is suppressed (no serial write, so a status LED that // flickers on UART TX rests quiet) while ESP_LOGW/ESP_LOGE warnings and errors still print. The - // main loop reads logLevel() to gate the KPI line; affectsPrepare re-applies it to the platform + // main loop reads logLevel() to gate the KPI line; onControlChanged re-applies it to the platform // logger on change. The first 60 s of uptime always logs at Info regardless (the web installer // reads MM_IP off the tick line just after flash). Stored as the raw enum value for addSelect. uint8_t logLevel_ = static_cast(platform::LogLevel::Warn); diff --git a/src/light/drivers/DriverBase.h b/src/light/drivers/DriverBase.h index 89982507..07a26a04 100644 --- a/src/light/drivers/DriverBase.h +++ b/src/light/drivers/DriverBase.h @@ -20,6 +20,7 @@ #include "light/layers/Buffer.h" #include "light/layers/Layer.h" #include "light/drivers/Correction.h" +#include "light/drivers/LedPeripheral.h" // LedHwBlock β€” the peripheral-block claim guard's vocabulary #include "light/drivers/LightPresetsModule.h" // the shared preset library a driver references by id #include "platform/platform.h" @@ -50,6 +51,12 @@ class DriverBase : public MoonModule { ModuleRole role() const override { return ModuleRole::Driver; } virtual void setSourceBuffer(Buffer* buf) = 0; + /// The hardware peripheral block this driver drives, for the parallel-driver claim guard (two live + /// drivers on one block corrupt each other). Only ParallelLedDriver overrides it; every other driver + /// (RMT, NetworkSend, Hue, Preview) drives no shared parallel block and keeps None. Virtual, not + /// RTTI β€” ESP32 builds compile -fno-rtti, so the guard reads siblings through this, never a cast. + virtual LedHwBlock hwBlock() const { return LedHwBlock::None; } + /// Template method: every driver card leads with the per-driver output correction /// (localBrightness / lightPreset / whiteMode / Custom offsets), added once here in the base /// so no driver re-implements the placement (the No-duplication rule) β€” then the driver's own diff --git a/src/light/drivers/LedPeripheral.h b/src/light/drivers/LedPeripheral.h new file mode 100644 index 00000000..b4691cbb --- /dev/null +++ b/src/light/drivers/LedPeripheral.h @@ -0,0 +1,130 @@ +#pragma once + +#include +#include +#include "core/Control.h" // ControlList β€” a backend appends its own controls into the shared list +#include "platform/platform.h" // RmtLoopbackResult + +namespace mm { + +class ParallelLedDriver; // the orchestrator; a backend reads shared state through this back-pointer + +/// The physical peripheral block a backend drives. Two backends on the SAME block conflict β€” the chip +/// has exactly one of each β€” so the orchestrator refuses to bring up a second driver already claiming a +/// block a sibling holds. Note esp_lcd-i80 (on the S3/P4) and MoonI80 BOTH drive LcdCam: they are the +/// same silicon reached two ways, so they conflict with each other, not only with themselves. The +/// classic-ESP32 i80 is the I2S peripheral, a different block. +enum class LedHwBlock : uint8_t { None = 0, LcdCam, I2s, Parlio }; + +/// A parallel-WS2812 output peripheral, behind a runtime strategy interface. +/// +/// `ParallelLedDriver` (the one MoonModule) owns the controls, lifecycle, tick, and the shared +/// slice/encode/double-buffer/expander/loopback machinery, and drives ONE `LedPeripheral` chosen at +/// runtime (Parlio, esp_lcd i80, or MoonI80 own-GDMA). The peripheral supplies only the variant +/// operations β€” bring the bus up, hand back its DMA buffer, transmit a frame, tear down β€” plus a few +/// static descriptors (lane count, expander support, bus-width rounding) as virtuals, so the +/// orchestrator reads them through the one `LedPeripheral*` rather than a compile-time type. +/// +/// **Not a hot-path virtual boundary.** Every method here is called per-FRAME or per-reinit, never +/// per-light: the per-light encode operates on the raw `uint8_t*` `busBuffer()` hands back and never +/// calls into the peripheral. One vcall per frame against ~thousands of Β΅s of frame work is free β€” the +/// dispatch that mattered (per-light) stays a direct call inside the shared encode. +/// +/// **Shared state via a back-pointer.** A backend reaches the orchestrator's parsed lane list, latch +/// bit, correction, and loopback pin through `owner()` (set once by `attach()`), replacing what CRTP +/// inheritance gave for free. The orchestrator exposes exactly those as public const accessors. +/// +/// Prior art: the Strategy / pluggable-backend pattern; the projectMM `ListSource` / `DevicePlugin` +/// adapter shape (a generic owner + a variant object that travels with its own state). +class LedPeripheral { +public: + virtual ~LedPeripheral() = default; + + /// Bind the peripheral to its orchestrator. Called once, right after construction, before any + /// bus operation. The backend reads shared state (bus pin list, latch, correction, loopback pin) + /// through this pointer. + void attach(ParallelLedDriver* owner) { owner_ = owner; } + + // --- Static descriptors: per-peripheral constants the orchestrator reads through the interface --- + /// Parallel lanes this peripheral's silicon provides on the current chip (0 = not this chip). + virtual uint8_t lanesAvailable() const = 0; + /// Can this peripheral host the 74HCT595 pin expander? (Needs a DMA that reaches PSRAM.) + virtual bool supportsPinExpander() const = 0; + /// Does the bus width round up to a power of two (8/16), or is it the exact pin count? + virtual bool powerOfTwoBus() const = 0; + /// The status message when bus init fails on this peripheral. + virtual const char* initFailMsg() const = 0; + /// Must the loopback self-test build a full-width bus (true) or can it run on a private 1-lane + /// unit (false)? esp_lcd i80 / MoonI80 need the full width; Parlio can do a single lane. + virtual bool loopbackFullWidth() const = 0; + /// The physical peripheral block this backend drives β€” the orchestrator's claim guard refuses two + /// live drivers on the same block. On the classic ESP32 the esp_lcd-i80 backend is the I2S block; + /// on the S3/P4 it (and MoonI80) is LcdCam. + virtual LedHwBlock hwBlock() const = 0; + + // --- Required core (no default; every backend implements) --- + /// Create the bus + its DMA buffer(s) sized for `frameBytes`; `wantSecondBuffer` requests the + /// async double-buffer's second frame (allocated only if it fits). Returns whether init succeeded. + virtual bool busInit(size_t frameBytes, bool wantSecondBuffer) = 0; + /// Tear down the bus and its DMA buffer(s). + virtual void busDeinit() = 0; + /// DMA buffer `i` (0/1) the encoder writes into; buffer 1 is null in single-buffer mode. + virtual uint8_t* busBuffer(uint8_t i) = 0; + /// Per-buffer byte capacity (fixed at bus creation; both buffers equal). + virtual size_t busCapacity() const = 0; + /// Kick off the autonomous transfer of the first `bytes` of DMA buffer `i`; returns whether it + /// started. + virtual bool busTransmit(uint8_t i, size_t bytes) = 0; + /// Block up to `ms` for buffer `i`'s in-flight transfer to complete. + virtual bool busWait(uint8_t i, uint32_t ms) = 0; + /// The most recent DMA transfer's wire time (Β΅s) β€” the WS2812 output floor. + virtual uint32_t busLastTransmitUs() const = 0; + /// Run the loopback self-test on this peripheral (each builds its own bus, per loopbackFullWidth). + virtual platform::RmtLoopbackResult busLoopback(const uint8_t* frame, size_t frameBytes, + size_t dataBytes, uint8_t rowBits) = 0; + + // --- Ring cluster (default: no ring β€” only the MoonI80 backend overrides) --- + /// Bring the bus up as a streaming ring for `totalRows` rows of `rowBytes`; false if it won't fit. + virtual bool busInitRing(size_t /*rowBytes*/, uint32_t /*totalRows*/) { return false; } + /// Send one frame on the ring (prime + arm + ISR refill). False if the ring isn't up. + virtual bool busTransmitRing() { return false; } + /// Is the live bus a streaming ring? + virtual bool busIsRing() const { return false; } + /// Should reinit build a ring for the current config instead of the whole-frame path? + virtual bool wantsRing() const { return false; } + /// The ring's active-mode label for the status line, or nullptr for the whole-frame path. + virtual const char* busRingMode() const { return nullptr; } + /// Append this peripheral's ring controls into the shared list. Default: none. + virtual void addRingControls(ControlList& /*controls*/) {} + /// Refresh any peripheral-specific read-only KPIs (the ring diagnostic). Default: none. + virtual void refreshBusKpi() {} + /// Is the core-0 fork-join snapshot helper up (dual-core prime)? Default: no helper. + virtual bool snapHelperReady() const { return false; } + + // --- Bus-pin cluster (default: no extra pins β€” Parlio) --- + /// Append this peripheral's bus-pin controls (WR/DC clock pins) into the shared list. Default: none. + virtual void addBusControls(ControlList& /*controls*/) {} + /// Does a change to control `name` require a bus rebuild (a bus pin changed)? Default: no. + virtual bool busControlTriggersBuild(const char* /*name*/) const { return false; } + /// Snapshot the current bus pins so extraBusPinsCurrent can detect a later change. Default: none. + virtual void recordBusPins() {} + /// Are the recorded bus pins still current (no un-applied change)? Default: always current. + virtual bool extraBusPinsCurrent() const { return true; } + /// A per-peripheral fatal validation (returns a status message) run before bus init. Default: ok. + virtual const char* validateBusFatal() const { return nullptr; } + /// A per-peripheral lane-pin validation (returns a warning) β€” e.g. a data pin colliding with WR. + virtual const char* validateBusPins(const uint16_t* /*lanes*/, uint8_t /*n*/) const { return nullptr; } + /// The GPIO the bus parks spare (unused) lanes on (only reached when powerOfTwoBus rounds the + /// bus wider than the data-pin count β€” i80/MoonI80, which both override this to their WR pin). + /// The default 0 is never used by a peripheral whose bus is the exact pin count (Parlio, + /// powerOfTwoBus=false, never pads), so no owner lookup is needed here. + virtual uint16_t clockPinForBus() const { return 0; } + /// The whole-frame DMA byte budget: 0 = "no bound" (PSRAM-capable). A bounded peripheral (the + /// classic-ESP32 i80 = internal-RAM-only I2S) returns a positive ceiling. Default: no bound. + virtual size_t dmaBudgetBytes() const { return 0; } + +protected: + ParallelLedDriver* owner_ = nullptr; +}; + +} // namespace mm diff --git a/src/light/drivers/MoonLedDriver.h b/src/light/drivers/MoonLedDriver.h index dcd38856..97612ade 100644 --- a/src/light/drivers/MoonLedDriver.h +++ b/src/light/drivers/MoonLedDriver.h @@ -1,25 +1,25 @@ #pragma once -#include "light/drivers/ParallelLedDriver.h" // shared CRTP body +#include "light/drivers/ParallelLedDriver.h" // shared driver body + LedPeripheral #include "platform/platform.h" #include // the parallel-snapshot helper join flags namespace mm { -/// Output driver: parallel WS2812B on the **LCD_CAM** peripheral (ESP32-S3 / -P4), driven by **our own -/// DMA code** instead of ESP-IDF's `esp_lcd`. Same peripheral, pins and wire contract as -/// [MultiPinLedDriver](MultiPinLedDriver.md); the difference is underneath, and it buys two things -/// `esp_lcd` cannot give β€” a frame **streamed** rather than held whole, and a **74HCT595 pin expander** -/// (one GPIO driving 8 strands). +/// A `LedPeripheral` backend: parallel WS2812B on the **LCD_CAM** peripheral (ESP32-S3 / -P4), driven by +/// **our own DMA code** instead of ESP-IDF's `esp_lcd`. Same peripheral, pins and wire contract as the +/// `i80` backend (`I80Peripheral`); the difference is underneath, and it buys two things `esp_lcd` cannot +/// give β€” a frame **streamed** rather than held whole, and a **74HCT595 pin expander** (one GPIO driving +/// 8 strands). /// /// **Streamed, not held:** the DMA refills a small pool of internal buffers behind the read head, so RAM -/// stops scaling with strand length (`useRing` picks this path; `ringRows`/`ringBufs` size it). **Both -/// paths ship:** `MultiPinLedDriver` is the memory-capped **reference**, this is the streaming -/// **challenger**, and `useRing` A/Bs them on the same board with no reflash. LCD_CAM only β€” the classic -/// ESP32's i80 is the I2S peripheral, a different backend. Everything above the DMA (slicing, the fused -/// 3-slot encode, the async double-buffer, loopback, the `frameTime` KPI, the dead-frame guard) is -/// inherited from ParallelLedDriver, so this class is nearly all one-liners. +/// stops scaling with strand length (`useRing` picks this path; `ringRows`/`ringBufs` size it). The `i80` +/// backend is the memory-capped **reference**, this is the streaming **challenger**, and switching the +/// `peripheral` control A/Bs them on the same board with no reflash. LCD_CAM only β€” the classic ESP32's +/// i80 is the I2S peripheral, a separate backend. Everything above the DMA (slicing, the fused 3-slot +/// encode, the async double-buffer, loopback, the `frameTime` KPI, the dead-frame guard) lives in +/// ParallelLedDriver, so this backend is nearly all one-liners. /// /// The deep dives are under *More info*, below the attribute/method lists: /// @xref{why-our-own-dma-driver-below-the-read-head|why our own DMA driver}, @@ -136,14 +136,15 @@ namespace mm { /// `putdefaultones()` prefill has our own counterpart; the transpose is our own SWAR). He runs the S3 /// shift clock at ~19.2 MHz; we default to the same reliability point (20 MHz, a 28.8 Β΅s/light budget) /// with the `shiftOverclock` switch (26.67 MHz, 21.6 Β΅s/light) for short-wired rigs (see the control). -class MoonLedDriver : public ParallelLedDriver { +class MoonI80Peripheral : public LedPeripheral { public: // Data pins + loopback pin default to UNSET, for the same reason as the sibling: they are // user-soldered, so a hard-coded default would be a guess that could drive a pin the user - // committed elsewhere. The base declares pins="" / loopbackRxPin=-1, so nothing is needed here. + // committed elsewhere. The orchestrator declares pins="" / loopbackRxPin=-1, so nothing is + // needed here. /// WR β€” the pixel clock β€” and it is needed **only by a 74HCT595 expander**, which is why it is the - /// one bus control this driver keeps. + /// one bus control this backend keeps. /// /// WR toggles once per bus word in hardware, which is exactly what a '595's SRCLK needs: the pixel /// clock IS the shift clock. That is why the expander costs zero DMA bytes for its clock, and why @@ -250,107 +251,118 @@ class MoonLedDriver : public ParallelLedDriver { /// `sizeof` bounds the `snprintf`. char ringDbgStr_[176] = "β€”"; - // --- CRTP hooks the base calls (all non-virtual; no vtable) --- + // --- LedPeripheral descriptors --- - /// LCD_CAM lanes on this chip (0 = none, and then the base's guards make the driver inert). + /// LCD_CAM lanes on this chip (0 = none, and then the orchestrator's guards make the driver inert). /// Unlike the sibling this does NOT add `i2sLanes`: the classic ESP32's i80 is the I2S peripheral, /// which this backend does not implement. - static constexpr uint8_t lanesAvailable() { return platform::lcdLanes; } + uint8_t lanesAvailable() const override { return platform::lcdLanes; } /// The i80 bus width is 8 or 16 β€” a hardware fact (`lcd_ll_set_data_wire_width` takes nothing else). - /// The PIN count stays free: configure only the pins that drive something and the base rounds the bus - /// up around them, parking the spare lanes on WR (which the peripheral already drives, and nothing - /// reads). Parlio sets this false β€” its bus width IS its pin count. - static constexpr bool kPowerOfTwoBus = true; + /// The PIN count stays free: configure only the pins that drive something and the orchestrator rounds + /// the bus up around them, parking the spare lanes on WR (which the peripheral already drives, and + /// nothing reads). Parlio's backend sets this false β€” its bus width IS its pin count. + bool powerOfTwoBus() const override { return true; } /// The loopback cannot build a 1-lane private bus, so it rebuilds the full-width bus and carries /// the pattern on lane 0 β€” the test frame must therefore be encoded at the operational bus width. - static constexpr bool kLoopbackFullWidth = true; + bool loopbackFullWidth() const override { return true; } + /// MoonI80 programs LCD_CAM directly (its own GDMA below esp_lcd), so it claims the LcdCam block β€” + /// the same block the esp_lcd-i80 backend uses on the S3/P4, hence the two can't run together. + LedHwBlock hwBlock() const override { return LedHwBlock::LcdCam; } /// Status text when the bus will not come up, so the cause is on screen rather than in a serial log. /// The two real causes are named: a pin the peripheral cannot route, or no DMA-reachable memory for /// the frame (or the ring's pool). - static constexpr const char* kInitFailMsg = "MoonI80 bus init failed β€” check pins / memory"; - /// The expander needs a backend that can stream its Γ—8 frame; LCD_CAM is it, and this driver is - /// LCD_CAM-only, so the answer is simply "wherever this driver runs at all". - static constexpr bool kSupportsPinExpander = platform::lcdLanes > 0; + const char* initFailMsg() const override { return "MoonI80 bus init failed β€” check pins / memory"; } + /// The expander needs a backend that can stream its Γ—8 frame; LCD_CAM is it, and this backend is + /// LCD_CAM-only, so the answer is simply "wherever this backend runs at all". + bool supportsPinExpander() const override { return platform::lcdLanes > 0; } - /// The base pads spare bus lanes with this GPIO. Unrouted lanes cost nothing here, so the value is + /// The orchestrator pads spare bus lanes with this GPIO. Unrouted lanes cost nothing here, so the value is /// only ever *used* in shift mode β€” where WR is a real pad and the padding is genuinely inert. - uint16_t clockPinForBus() const { return static_cast(clockPin); } + uint16_t clockPinForBus() const override { return static_cast(clockPin); } /// WR is a '595 pin here, so the control follows the expander toggle: bound always (a saved value /// survives a round-trip through direct mode) but shown only when a shift register can read it. - void addBusControls() { - controls_.addPin("clockPin", clockPin); - controls_.setHidden(controls_.count() - 1, !pinExpanderMode()); + void addBusControls(ControlList& controls) override { + controls.addPin("clockPin", clockPin); + controls.setHidden(controls.count() - 1, !owner_->pinExpanderMode()); } /// The output path + the ring's geometry and instrument. A separate hook from addBusControls() so the - /// base can place these AFTER latchPin β€” clockPin and latchPin are one '595 wiring pair and belong - /// together in the UI, not split by a mode selector. - void addRingControls() { - // The shift-clock speed switch, below the clockPin/latchPin wiring pair (the base places this - // hook right after latchPin): OFF = 20 MHz (safe default), ON = 26.67 MHz (overclock). The fix - // for per-strand '595 corruption is OFF; see the member doc. Shift-mode only. - controls_.addBool("shiftOverclock", shiftOverclock); - controls_.setHidden(controls_.count() - 1, !pinExpanderMode()); - controls_.setAdvanced(controls_.count() - 1); // a '595 clock tuning knob β€” expert only + /// orchestrator can place these AFTER latchPin β€” clockPin and latchPin are one '595 wiring pair and + /// belong together in the UI, not split by a mode selector. + void addRingControls(ControlList& controls) override { + // The shift-clock speed switch, below the clockPin/latchPin wiring pair (the orchestrator places + // this hook right after latchPin): OFF = 20 MHz (safe default), ON = 26.67 MHz (overclock). The + // fix for per-strand '595 corruption is OFF; see the member doc. Shift-mode only. + controls.addBool("shiftOverclock", shiftOverclock); + controls.setHidden(controls.count() - 1, !owner_->pinExpanderMode()); + controls.setAdvanced(controls.count() - 1); // a '595 clock tuning knob β€” expert only // Path selector (pin-expander mode only): the ring, or the whole frame. A distinct axis from // ringSnapshot β€” this picks the PATH, ringSnapshot tunes how the RING reads its source; they // compose. Whole-frame is the A/B reference: it is how the whole-frame-PSRAM-at-the-expander-clock // question stays testable on the same board and content. - controls_.addBool("useRing", useRing); - controls_.setHidden(controls_.count() - 1, !pinExpanderMode()); + controls.addBool("useRing", useRing); + controls.setHidden(controls.count() - 1, !owner_->pinExpanderMode()); // The source-snapshot A/B knob, directly under useRing (the path it belongs to): the ring reads // its source through an immutable snapshot (ON, the safe default) or the live buffer (OFF, a bench // lever). Meaningful only when the ring is the chosen path, so hidden on wantsRing() like the - // geometry below. `ringSnapshot` lives on the base (ParallelLedDriver); the control binds it here. - controls_.addBool("ringSnapshot", ringSnapshot); - controls_.setHidden(controls_.count() - 1, !wantsRing()); + // geometry below. `ringSnapshot` lives on the orchestrator (ParallelLedDriver); the control binds + // it here through the mutable reference accessor. + controls.addBool("ringSnapshot", owner_->ringSnapshotRef()); + controls.setHidden(controls.count() - 1, !wantsRing()); // The geometry + the instrument, shown only when the RING is the chosen path β€” all meaningless on // the whole-frame one. (Gating on wantsRing() is safe: it reads plain members, pinExpanderMode + // useRing, not frameBytes_, so it resolves even before the source buffer is wired at boot.) - controls_.addBool("ringAuto", ringAuto); - controls_.setHidden(controls_.count() - 1, !wantsRing()); + controls.addBool("ringAuto", ringAuto); + controls.setHidden(controls.count() - 1, !wantsRing()); // ringRows/ringBufs/ringPadUs are DEV TUNING β€” ringAuto derives them for the end user (kept // visible above); the manual knobs are expert-only. (Once ringAuto is verified to always pick the // right geometry, ringAuto itself could go advanced too β€” for now it stays visible as the recourse.) - controls_.addUint8("ringRows", ringRows, 1, 64); - controls_.setHidden(controls_.count() - 1, !wantsRing()); - controls_.setAdvanced(controls_.count() - 1); - controls_.addUint8("ringBufs", ringBufs, platform::kRingBufsMin, platform::kRingBufsMax); - controls_.setHidden(controls_.count() - 1, !wantsRing()); - controls_.setAdvanced(controls_.count() - 1); - controls_.addUint8("ringPadUs", ringPadUs, 0, platform::kRingPadMaxUs); - controls_.setHidden(controls_.count() - 1, !wantsRing()); - controls_.setAdvanced(controls_.count() - 1); + controls.addUint8("ringRows", ringRows, 1, 64); + controls.setHidden(controls.count() - 1, !wantsRing()); + controls.setAdvanced(controls.count() - 1); + controls.addUint8("ringBufs", ringBufs, platform::kRingBufsMin, platform::kRingBufsMax); + controls.setHidden(controls.count() - 1, !wantsRing()); + controls.setAdvanced(controls.count() - 1); + controls.addUint8("ringPadUs", ringPadUs, 0, platform::kRingPadMaxUs); + controls.setHidden(controls.count() - 1, !wantsRing()); + controls.setAdvanced(controls.count() - 1); // Ring internals, so the streaming can be diagnosed by polling /api/state (reliable) rather than // scraping serial. The raw instrument β€” expert only; the full field-by-field legend lives on the // ringDbgStr_ member below (rendered into the technical page). - controls_.addReadOnly("ringDbg", ringDbgStr_, sizeof(ringDbgStr_)); - controls_.setHidden(controls_.count() - 1, !wantsRing()); - controls_.setAdvanced(controls_.count() - 1); + controls.addReadOnly("ringDbg", ringDbgStr_, sizeof(ringDbgStr_)); + controls.setHidden(controls.count() - 1, !wantsRing()); + controls.setAdvanced(controls.count() - 1); } - /// Refresh the ringDbg diagnostic string once a second (base tick1s chains here via refreshBusKpi). - /// Nothing to report on the whole-frame path β€” the control is hidden there, so leave it untouched - /// rather than writing a "no ring" status that only repeats what useRing says. - void refreshBusKpi() { + /// Refresh the ringDbg diagnostic string once a second (the orchestrator's tick1s chains here via + /// refreshBusKpi). Nothing to report on the whole-frame path β€” the control is hidden there, so leave + /// it untouched rather than writing a "no ring" status that only repeats what useRing says. + void refreshBusKpi() override { const platform::MoonI80RingStats s = platform::moonI80Ws2812RingStats(bus_); if (!s.isRing) return; // Read-and-clear the segment sums each 1 s window β€” a free-running uint32 sum wraps every // ~20 s at the ring's accumulation rate, which silently garbles the averages (measured: se "64"). - const uint32_t segGather = dbgSegGatherCy, segEmit = dbgSegEmitCy, segRows = dbgSegRows; - dbgSegGatherCy = 0; dbgSegEmitCy = 0; dbgSegRows = 0; + const uint32_t segGather = ParallelLedDriver::dbgSegGatherCy; + const uint32_t segEmit = ParallelLedDriver::dbgSegEmitCy; + const uint32_t segRows = ParallelLedDriver::dbgSegRows; + ParallelLedDriver::dbgSegGatherCy = 0; + ParallelLedDriver::dbgSegEmitCy = 0; + ParallelLedDriver::dbgSegRows = 0; // The extended fields (ld/tx/ipb/ci/tn) are the LAPPING-phase instruments β€” the same readouts that // isolated the prime-only bugs (ld = drain progress, tx = real wire time vs the physical frame // minimum, ipb/ci/tn = node accounting + the terminator). Their scope lives in the backlog's ring // entry. - // sn/lv: memory residency of the two encode sources β€” snapshotBuf_ (sn) and the live source (lv); - // P = PSRAM, I = internal, '-' = absent. The ISR reads one of these per byte, and a PSRAM 'sn' - // under a lapping ring is the measured 4-8x encode cost + the cache-contention corruption exposure. - const char snapWhere = this->snapshotBuf_ - ? (platform::ptrIsPsram(this->snapshotBuf_) ? 'P' : 'I') : '-'; - const char liveWhere = (this->sourceBuffer_ && this->sourceBuffer_->data()) - ? (platform::ptrIsPsram(this->sourceBuffer_->data()) ? 'P' : 'I') : '-'; + // sn/lv: memory residency of the two encode sources β€” the snapshot buffer (sn) and the live source + // (lv); P = PSRAM, I = internal, '-' = absent. The ISR reads one of these per byte, and a PSRAM + // 'sn' under a lapping ring is the measured 4-8x encode cost + the cache-contention corruption + // exposure. + const uint8_t* snap = owner_->snapshotBuf(); + const Buffer* src = owner_->sourceBuffer(); + const char snapWhere = snap + ? (platform::ptrIsPsram(snap) ? 'P' : 'I') : '-'; + const char liveWhere = (src && src->data()) + ? (platform::ptrIsPsram(src->data()) ? 'P' : 'I') : '-'; std::snprintf(ringDbgStr_, sizeof(ringDbgStr_), "sn%c lv%c sl%u/bf%u co%u cr%u ab%u dn%u ld%u lt%u tx%u ipb%u ci%u tn%d de%u enc%u ea%u sg%u se%u tw%u ts%u tp%u gap%u", snapWhere, liveWhere, static_cast(s.nSlices), static_cast(s.ringBufs), @@ -364,9 +376,9 @@ class MoonLedDriver : public ParallelLedDriver { static_cast(s.maxEncodeUs), static_cast(s.avgEncodeUs), static_cast(segRows ? segGather / segRows : 0), // avg gather cycles/row (last window) static_cast(segRows ? segEmit / segRows : 0), // avg emit cycles/row (last window) - static_cast(ParallelLedDriver::dbgTickWaitUs), // wire-wait Β΅s - static_cast(ParallelLedDriver::dbgTickSnapUs), // snapshot Β΅s - static_cast(ParallelLedDriver::dbgTickPrimeUs), // prime Β΅s + static_cast(ParallelLedDriver::dbgTickWaitUs), // wire-wait Β΅s + static_cast(ParallelLedDriver::dbgTickSnapUs), // snapshot Β΅s + static_cast(ParallelLedDriver::dbgTickPrimeUs), // prime Β΅s static_cast(s.maxIsrGapUs)); // co = lifetime cache-off ISR defers (flash/WiFi write; ~10/s at idle is normal). cr = // worst consecutive-defer run β‰ˆ buffers drained un-refilled in one window. ab = frames @@ -378,10 +390,10 @@ class MoonLedDriver : public ParallelLedDriver { // enc = worst ISR refill-encode Β΅s (producer); gap = worst EOF-to-EOF Β΅s (deadline). // enc >= gap == the refill can't keep pace (PACE); enc << gap but still fails == CURSOR/logic. } - /// Which of this driver's controls need the BUS rebuilt (not just a re-encode) when they change: + /// Which of this backend's controls need the BUS rebuilt (not just a re-encode) when they change: /// the WR pin, the output path, and the ring's geometry β€” buffers are sized and the DMA chain mounted /// at build time, so each of these is a rebuild. - bool busControlTriggersBuild(const char* name) const { + bool busControlTriggersBuild(const char* name) const override { return std::strcmp(name, "clockPin") == 0 || std::strcmp(name, "useRing") == 0 // path switch: rebuild the bus on the new path || std::strcmp(name, "ringAuto") == 0 // re-derive (or stop deriving) the geometry @@ -395,34 +407,53 @@ class MoonLedDriver : public ParallelLedDriver { /// WR only reaches a pad in shift mode, so it can only COLLIDE in shift mode. In direct mode the /// signal never leaves the peripheral, so `clockPin` naming a strand's GPIO is harmless β€” and /// rejecting it would forbid a perfectly good config for the sake of a signal nobody reads. - const char* validateBusFatal() const { - if (pinExpanderMode()) { + const char* validateBusFatal() const override { + if (owner_->pinExpanderMode()) { // The '595 needs WR on a real GPIO (it is the SRCLK). Unset (-1) would route the // peripheral's WR signal to GPIO 65535 β€” reject it before busInit reaches the pad. if (clockPin < 0) return "the 74HCT595 expander needs a clockPin (its shift clock)"; - if (latchPin >= 0 && latchPin == clockPin) + if (owner_->latchPin >= 0 && owner_->latchPin == clockPin) return "latchPin is on clockPin (WR) β€” the latch needs its own GPIO"; } return nullptr; } /// A data lane sharing WR's GPIO is silent corruption β€” the matrix routes both signals to the one /// pad and that strand emits the shift clock instead of pixel data. Only possible in shift mode. - const char* validateBusPins(const uint16_t* lanes, uint8_t n) const { - if (!pinExpanderMode()) return nullptr; + const char* validateBusPins(const uint16_t* lanes, uint8_t n) const override { + if (!owner_->pinExpanderMode()) return nullptr; for (uint8_t i = 0; i < n; i++) if (lanes[i] == static_cast(clockPin)) return "a data pin is on clockPin (WR)"; return nullptr; } /// Create the bus + its DMA buffer(s) for `frameBytes`. `busPinList()`/`busPinCount()` come from - /// the base (in shift mode the list appends the latch β€” it is a bus lane), and + /// the orchestrator (in shift mode the list appends the latch β€” it is a bus lane), and /// `busClockMultiplier()` tells the platform how many bus words one WS2812 slot is shifted out /// over, so it can scale the pixel clock and the slot keeps its wire duration. - bool busInit(size_t frameBytes, bool wantSecondBuffer) { + bool busInit(size_t frameBytes, bool wantSecondBuffer) override { platform::moonI80SetShiftClockDiv(shiftOverclock ? 3 : 4); // ON = 26.67 MHz, OFF = 20 MHz - return platform::moonI80Ws2812Init(bus_, this->busPinList(), this->busPinCount(), + return platform::moonI80Ws2812Init(bus_, owner_->busPinList(), owner_->busPinCount(), static_cast(clockPin), frameBytes, - wantSecondBuffer, this->busClockMultiplier()); + wantSecondBuffer, owner_->busClockMultiplier()); + } + void busDeinit() override { stopSnapHelper(); platform::moonI80Ws2812Deinit(bus_); } + uint8_t* busBuffer(uint8_t i) override { return platform::moonI80Ws2812Buffer(bus_, i); } + size_t busCapacity() const override { return platform::moonI80Ws2812BufferCapacity(bus_); } + bool busTransmit(uint8_t i, size_t bytes) override { return platform::moonI80Ws2812Transmit(bus_, i, bytes); } + bool busWait(uint8_t i, uint32_t ms) override { return platform::moonI80Ws2812Wait(bus_, i, ms); } + uint32_t busLastTransmitUs() const override { return platform::moonI80Ws2812LastTransmitUs(bus_); } + + /// Drive `frame` on a private bus and capture the wire back on `loopbackRxPin` (jumpered), so the + /// self-test bit-verifies what the peripheral ACTUALLY emitted β€” the one instrument that does not + /// take the driver's word for it. + platform::RmtLoopbackResult busLoopback(const uint8_t* frame, size_t frameBytes, + size_t dataBytes, uint8_t rowBits) override { + return platform::moonI80Ws2812Loopback(owner_->busPinList(), owner_->busPinCount(), + static_cast(clockPin), + static_cast(owner_->loopbackRxPin), + frame, frameBytes, dataBytes, rowBits, + owner_->busClockMultiplier(), + ringRows, ringBufs, useRing); } /// Should reinit build a RING for this config instead of the whole-frame path? Only in pin-expander @@ -434,17 +465,18 @@ class MoonLedDriver : public ParallelLedDriver { /// itself as a decision, and its silent fallback made the ACTIVE path invisible β€” the driver reported /// "driving N lights" while quietly running whole-frame from PSRAM, which does not clock at the /// expander's 26.67 MHz. The switch says what runs. - bool wantsRing() const { - if (!pinExpanderMode()) return false; // direct mode never rings (drives PSRAM fine) + bool wantsRing() const override { + if (!owner_->pinExpanderMode()) return false; // direct mode never rings (drives PSRAM fine) return useRing; } /// Bring the bus up as a streaming RING (the phase-2 path): the platform loops a few small internal /// buffers and calls back per drained buffer to refill it, so a frame too big for internal RAM never - /// materialises (see platform.h). `rowBytes`/`padBytes` come from the base's frame arithmetic; the - /// trampoline below is the encode seam. Returns false if even the small ring won't fit β€” the base - /// then falls back to busInit (whole-frame), which idles with a status if IT can't fit either. - bool busInitRing(size_t rowBytes, uint32_t totalRows) { + /// materialises (see platform.h). `rowBytes`/`padBytes` come from the orchestrator's frame arithmetic; + /// the trampoline below is the encode seam. Returns false if even the small ring won't fit β€” the + /// orchestrator then falls back to busInit (whole-frame), which idles with a status if IT can't fit + /// either. + bool busInitRing(size_t rowBytes, uint32_t totalRows) override { // AUTO geometry (see ringAuto): derive the winning combination for THIS config and write it into // the visible controls β€” rows = one-node max (fewest slices), bufs = as deep as fits. The RAM // budget takes free internal MINUS a reserve (WiFi/HTTP need their share; same spirit as the @@ -468,10 +500,10 @@ class MoonLedDriver : public ParallelLedDriver { ringBufs = static_cast(bufs >= platform::kRingBufsMin ? bufs : platform::kRingBufsMin); } platform::moonI80SetShiftClockDiv(shiftOverclock ? 3 : 4); // ON = 26.67 MHz, OFF = 20 MHz - const bool ok = platform::moonI80Ws2812InitRing(bus_, this->busPinList(), this->busPinCount(), + const bool ok = platform::moonI80Ws2812InitRing(bus_, owner_->busPinList(), owner_->busPinCount(), static_cast(clockPin), rowBytes, totalRows, - ringRows, ringBufs, ringPadUs, this->busClockMultiplier(), - &MoonLedDriver::ringEncodeTrampoline, this); + ringRows, ringBufs, ringPadUs, owner_->busClockMultiplier(), + &MoonI80Peripheral::ringEncodeTrampoline, this); // Ring up β†’ bring the parallel-snapshot helper up too (idempotent; parks in waitNotify). Torn down // in busDeinit with the bus. Spawned here (cold reinit path) so kick()/join() only ever notify. if (ok) ensureSnapHelper(); @@ -482,7 +514,7 @@ class MoonLedDriver : public ParallelLedDriver { // ring buffers are independent (each derives its rows from its index), so the helper primes the bottom // half of the pool on core 0 while this core primes the top half, the join fences both, then the arm // starts the DMA. Serial fallback: the platform's prime-all-then-arm combo. - bool busTransmitRing() { + bool busTransmitRing() override { if (snapHelperReady() && ringBufs >= 2) { // `done` is written-gated (leads the wire drain); the prime itself takes the wire barrier β€” // each prime call waits out the previous frame's deterministic wire end before writing (see @@ -499,17 +531,17 @@ class MoonLedDriver : public ParallelLedDriver { } /// The ring's regime for the driving-status suffix: "primed" (whole frame encoded before arming β€” /// no deadline, pixel-perfect) vs "lapping" (the ISR refills behind the DMA β€” the deadline regime). - const char* busRingMode() const { + const char* busRingMode() const override { const platform::MoonI80RingStats s = platform::moonI80Ws2812RingStats(bus_); if (!s.isRing) return nullptr; return s.nSlices <= s.ringBufs ? "primed" : "lapping"; } - /// Did the bus actually come up as a ring? The base routes tick() on this, so it reports what the - /// platform BUILT, not what was asked for β€” a ring that would not fit falls back to whole-frame. - bool busIsRing() const { return platform::moonI80Ws2812IsRing(bus_); } + /// Did the bus actually come up as a ring? The orchestrator routes tick() on this, so it reports what + /// the platform BUILT, not what was asked for β€” a ring that would not fit falls back to whole-frame. + bool busIsRing() const override { return platform::moonI80Ws2812IsRing(bus_); } - /// The platform's `MoonI80EncodeFn` seam: a plain function pointer (there is no CRTP hook for it), so - /// this static trampoline recovers `this` from `user` and encodes one slice into the ring buffer the + /// The platform's `MoonI80EncodeFn` seam: a plain function pointer (there is no virtual hook for it), + /// so this static trampoline recovers `this` from `user` and encodes one slice into the ring buffer the /// platform hands it. `dst` is the buffer; `firstRow`/`rowCount` name the slice; `closeFrame` gates /// the trailing latch pad (only the last slice emits it). /// @@ -522,14 +554,15 @@ class MoonLedDriver : public ParallelLedDriver { /// mode writes every slot word in encodeRows, so it needs no prefill. static void MM_RAMFUNC ringEncodeTrampoline(void* user, uint8_t* dst, uint32_t firstRow, uint32_t rowCount, bool closeFrame, bool needsPrefill) { - auto* self = static_cast(user); - const uint8_t outCh = self->correction_.outChannels; + auto* self = static_cast(user); + ParallelLedDriver* owner = self->owner_; + const uint8_t outCh = owner->correction().outChannels; const auto first = static_cast(firstRow); const auto count = static_cast(rowCount); if (rowCount == 0) { // The FRAME-CLOSE call (see MoonI80EncodeFn): write only the latch-only word, which presents // the register's final slot on the strand. Direct mode has no close word β€” zeros are LOW. - if (closeFrame) self->encodeFrameClose(dst); + if (closeFrame) owner->encodeFrameClose(dst); return; } // Prefill only when the buffer's constants are actually gone (`needsPrefill` β€” the platform's @@ -538,54 +571,23 @@ class MoonLedDriver : public ParallelLedDriver { // ~1/3 of the ISR encode cost β€” the difference between the refill fitting its drain deadline or not. // RAGGED strands still prefill every time: the active mask varies per ROW, so a buffer holding a // different slice needs that slice's row masks re-laid regardless of recycling. - const bool prefill = self->pinExpanderMode() && (needsPrefill || !self->uniformLaneCounts()); - if (self->slotBytes() == 1) { - if (prefill) self->prefillShiftRows(outCh, dst, first, count); - self->encodeRows(outCh, dst, first, count, closeFrame); + const bool prefill = owner->pinExpanderMode() && (needsPrefill || !owner->uniformLaneCounts()); + if (owner->slotBytes() == 1) { + if (prefill) owner->prefillShiftRows(outCh, dst, first, count); + owner->encodeRows(outCh, dst, first, count, closeFrame); } else { - if (prefill) self->prefillShiftRows(outCh, dst, first, count); - self->encodeRows(outCh, dst, first, count, closeFrame); + if (prefill) owner->prefillShiftRows(outCh, dst, first, count); + owner->encodeRows(outCh, dst, first, count, closeFrame); } } - /// The whole-frame path's DMA buffer `i` (0, or 1 with doubleBuffer on) β€” where the base encodes a - /// frame. Null on a ring handle, which has no whole-frame buffer to hand out. - uint8_t* busBuffer(uint8_t i) { return platform::moonI80Ws2812Buffer(bus_, i); } - /// Bytes that buffer holds β€” the base's guard against encoding past the end after a live resize. - size_t busCapacity() const { return platform::moonI80Ws2812BufferCapacity(bus_); } - /// Clock buffer `i` out: one gapless DMA transfer of `bytes`, returning as soon as it is armed. - bool busTransmit(uint8_t i, size_t bytes) { return platform::moonI80Ws2812Transmit(bus_, i, bytes); } - /// Block until buffer `i` has finished clocking (or `ms` elapses) β€” how the async double-buffer - /// defers its wait to the NEXT frame instead of stalling this one. - bool busWait(uint8_t i, uint32_t ms) { return platform::moonI80Ws2812Wait(bus_, i, ms); } - /// Measured wire time of the last frame, in Β΅s β€” the `frameTime` KPI's source, and the output floor - /// the encode is compared against. - uint32_t busLastTransmitUs() const { return platform::moonI80Ws2812LastTransmitUs(bus_); } - /// Tear the bus down: stop the DMA before freeing anything it could still read. Safe on a - /// half-built bus, so a failed init and a live one release through the same path. The snapshot helper - /// task goes down FIRST β€” it reads snapshotBuf_, which the base frees on release, so no wake may land - /// after; stopPinnedTask joins, so once it returns the helper is provably gone. - void busDeinit() { stopSnapHelper(); platform::moonI80Ws2812Deinit(bus_); } - - /// Drive `frame` on a private bus and capture the wire back on `loopbackRxPin` (jumpered), so the - /// self-test bit-verifies what the peripheral ACTUALLY emitted β€” the one instrument that does not - /// take the driver's word for it. - platform::RmtLoopbackResult busLoopback(const uint8_t* frame, size_t frameBytes, - size_t dataBytes, uint8_t rowBits) { - return platform::moonI80Ws2812Loopback(this->busPinList(), this->busPinCount(), - static_cast(clockPin), - static_cast(loopbackRxPin), - frame, frameBytes, dataBytes, rowBits, - this->busClockMultiplier(), - ringRows, ringBufs, useRing); - } /// WR is part of the bus identity, so a change to it rebuilds the bus β€” not just a data-pin edit. - void recordBusPins() { lastClockPin_ = clockPin; } - /// Do this driver's extra bus pins still match the live bus? WR is bus identity here, so the base - /// rebuilds when this goes false rather than routing a stale clock. - bool extraBusPinsCurrent() const { return lastClockPin_ == clockPin; } + void recordBusPins() override { lastClockPin_ = clockPin; } + /// Do this backend's extra bus pins still match the live bus? WR is bus identity here, so the + /// orchestrator rebuilds when this goes false rather than routing a stale clock. + bool extraBusPinsCurrent() const override { return lastClockPin_ == clockPin; } - // --- Fork-join helper (CRTP override of the base's default no-op hook) --- + // --- Fork-join helper (the ring's core-0 prime-half worker) --- // The pool PRIME (~14 ms at 48Γ—256) is embarrassingly parallel β€” each ring buffer derives its rows from // its own index β€” so under the render/encode split (ring tick on core 1) one core-0 helper task primes // the bottom half of the pool while core 1 primes the top, per frame. The task is spawned once at ring @@ -600,7 +602,7 @@ class MoonLedDriver : public ParallelLedDriver { /// β€” i.e. the render/encode split is active and core 0 is the idle one to hand the bottom half. On /// core 0 (single-core, or the split disengaged), there is no idle second core, so stay serial and /// avoid spawning contention onto the very core doing the render. - bool snapHelperReady() const { + bool snapHelperReady() const override { return snapHelper_.impl != nullptr && !snapHelperBroken_ && platform::currentCore() == 1; } @@ -659,7 +661,7 @@ class MoonLedDriver : public ParallelLedDriver { // very first kick doesn't wait on a park signal the helper only emits after it starts running. snapHelperParked_.store(true, std::memory_order_release); snapHelperDone_.store(true, std::memory_order_release); - platform::spawnPinnedTask(snapHelper_, "mmSnap", &MoonLedDriver::snapHelperTramp, this, + platform::spawnPinnedTask(snapHelper_, "mmSnap", &MoonI80Peripheral::snapHelperTramp, this, 4096, 5, /*core=*/0); } void stopSnapHelper() { @@ -669,7 +671,7 @@ class MoonLedDriver : public ParallelLedDriver { } static void snapHelperTramp(void* user) { - auto* self = static_cast(user); + auto* self = static_cast(user); while (!self->snapHelperStop_.load(std::memory_order_acquire)) { // Announce PARKED before blocking, so helperKick knows the previous job is fully done and the // helper is no longer reading helperJob_/the bounds β€” only then does it publish the next job. @@ -700,4 +702,10 @@ class MoonLedDriver : public ParallelLedDriver { int8_t lastClockPin_ = -1; }; +// Register the MoonI80 (own-GDMA below esp_lcd) backend into the peripheral registry once, at +// static-init. Gated by this header's CONFIG_SOC include in main.cpp (LCD_CAM chips only). No separate +// driver class β€” the one ParallelLedDriver drives it, chosen via the `peripheral` control. +inline const bool kMoonI80PeripheralRegistered = + ParallelLedDriver::registerPeripheral("MoonI80", []() -> LedPeripheral* { return new MoonI80Peripheral(); }); + } // namespace mm diff --git a/src/light/drivers/MultiPinLedDriver.h b/src/light/drivers/MultiPinLedDriver.h index 127e7a24..0e4de891 100644 --- a/src/light/drivers/MultiPinLedDriver.h +++ b/src/light/drivers/MultiPinLedDriver.h @@ -1,6 +1,6 @@ #pragma once -#include "light/drivers/ParallelLedDriver.h" // shared CRTP body +#include "light/drivers/ParallelLedDriver.h" // shared driver body + LedPeripheral #include "platform/platform.h" @@ -10,16 +10,17 @@ namespace mm { /// β€” the parallel scale path on **all three i80-capable ESP32 families**. RMT gives a chip 4-8 /// channels; this gives 8-16 lanes for the wall time of one. The magic is that ESP-IDF exposes ONE /// public i80 API (`esp_i80_new_i80_bus` / `esp_i80_panel_io_tx_color`) and routes it to whichever -/// peripheral the silicon has β€” so this single driver serves every chip: +/// peripheral the silicon has β€” so this single backend serves every chip: /// - **ESP32-S3 / -P4:** backed by the dedicated **LCD_CAM** peripheral. /// - **classic ESP32:** backed by the **I2S peripheral in i80/LCD mode** (the classic has no LCD_CAM; /// I2S-i80 is its only >8-lane route). IDF's own CMake picks the backend by chip; the two are /// mutually exclusive per silicon, so `lanesAvailable()` reads whichever lane-count constant is /// non-zero. Named for the **i80 bus** (the shared API), not a peripheral, since it isn't one -/// peripheral β€” same reason its siblings are named `Rmt`/`Parlio` (their APIs). +/// peripheral β€” same reason its sibling backend is named `Parlio` (its own API). /// /// The shared body (slicing, the whole-frame async double-buffer DMA, the fused encode, the loopback -/// self-test, the `frameTime` KPI) lives in ParallelLedDriver; this class adds only the i80-specific pieces: +/// self-test, the `frameTime` KPI) lives in ParallelLedDriver; this backend adds only the i80-specific +/// pieces: /// - The sacrificial WR (pixel clock) + DC GPIOs the i80 bus mandates even though WS2812 ignores /// both, and the "exactly 8 or 16 pins" rule (the i80 layer rejects a partial bus). A sub-16 board /// parks unused lanes + WR/DC on one spare GPIO (the ghost-pin trick). @@ -29,7 +30,7 @@ namespace mm { /// ~416 ns: newer WS2812B revisions spec T0H max β‰ˆ 380 ns, and a longer `0` on a direct 3.3 V line /// gets misread as `1` (the strip washes white). One bus word per slot (bus bit L = the L-th pin); /// unequal strands idle LOW once exhausted. Slot layout: ParallelSlots.h. -/// - Both backends do **whole-frame chained DMA** (autonomous, CPU out of the timing loop), so the +/// - Both silicon paths do **whole-frame chained DMA** (autonomous, CPU out of the timing loop), so the /// classic I2S path is WiFi-underrun-immune by construction β€” it does NOT need the ISR-refilled /// ring / large `nbDmaBuffer` cushion the raw-register I2S-clockless lineage requires. /// - The platform::i80Ws2812* calls (ESP-IDF's esp_lcd i80 bus + GDMA). @@ -37,7 +38,7 @@ namespace mm { /// Prior art: Adafruit's LCD_CAM discovery, hpwit's I2SClockless lineage (classic-ESP32 I2S parallel), /// FastLED's S3 driver β€” architecture studied, never copied. We build on IDF's maintained esp_lcd i80 /// abstraction rather than tracing the raw-register I2S driver (*Industry standards, our own code*). -class MultiPinLedDriver : public ParallelLedDriver { +class I80Peripheral : public LedPeripheral { public: // Data pins + loopback pin default to UNSET: they are user-soldered (the strand // runs to whatever GPIOs the user wired), so a hard-coded default would be a @@ -45,7 +46,7 @@ class MultiPinLedDriver : public ParallelLedDriver { // the driver idles meanwhile (the "default only when it cannot do harm" rule; // see lessons.md). The ESP32-S3 N16R8 Dev bench wiring is pins "1,2,4,5,6,7,8,9", // loopbackRxPin 12 (kept clear of the octal-PSRAM pins 26-37, USB 19/20, and - // strapping pins) β€” set those again to reproduce the bench. (Base declares + // strapping pins) β€” set those again to reproduce the bench. (The orchestrator declares // pins="" and loopbackRxPin=0, so the empty default needs no code here.) /// WR (pixel clock) and DC: the IDF i80 bus *requires* both on real GPIOs @@ -53,8 +54,8 @@ class MultiPinLedDriver : public ParallelLedDriver { /// ignore both β€” they are peripheral-fixed, not user-strand wiring, so a sensible overridable /// default cannot do harm (same class as the chip-fixed Ethernet pins). The data pins gate /// startup, so the bus stays idle until the user sets them regardless. (Dropping WR/DC entirely - /// needs a direct-LCD_CAM driver that bypasses esp_lcd, hpwit-style β€” backlogged, not this - /// increment.) + /// needs a direct-LCD_CAM backend that bypasses esp_lcd, hpwit-style β€” that is MoonI80Peripheral, + /// backlogged as this increment's sibling.) /// /// **`clockPin` is ONE pin doing TWO jobs, and with a 74HCT595 expander the second one is /// load-bearing.** WR toggles once per bus word in hardware β€” which is exactly what a '595's @@ -79,22 +80,22 @@ class MultiPinLedDriver : public ParallelLedDriver { /// ROM, not an API contract: the S3 and classic ROMs open with an unsigned bounds compare and return /// without writing (a silent no-op), but the **ESP32-P4 ROM has no such guard** and computes a store /// ~0x50120554 β€” a quarter-megabyte past the GPIO block, in another peripheral's window β€” plus a - /// >31-bit shift. This driver runs on the P4. IDF's own `esp_rom/patches/esp_rom_gpio.c` is unguarded + /// >31-bit shift. This backend runs on the P4. IDF's own `esp_rom/patches/esp_rom_gpio.c` is unguarded /// too, so the S3's check is an implementation detail a patch could remove, not a promise. FastLED's /// LCD_CAM driver parks both pins on a dummy GPIO for the same reason. To spend no GPIO at all, use - /// MoonLedDriver: owning the DMA below esp_lcd, it holds DC at a constant level and routes WR only + /// MoonI80Peripheral: owning the DMA below esp_lcd, it holds DC at a constant level and routes WR only /// when a '595 needs it as SRCLK. int8_t clockPin = 10; int8_t dcPin = 11; - // --- CRTP hooks the base calls (all non-virtual; no vtable) --- + // --- LedPeripheral descriptors --- - /// The number of i80 lanes this chip provides (0 = no i80 bus on this chip); the base's + /// The number of i80 lanes this chip provides (0 = no i80 bus on this chip); the orchestrator's /// inert-on-wrong-chip guards key off it. Reads whichever backend the silicon has β€” /// `lcdLanes` (LCD_CAM, S3/P4) or `i2sLanes` (I2S-i80, classic ESP32) β€” which are mutually /// exclusive per chip (at most one is non-zero), so the sum picks the right one. - static constexpr uint8_t lanesAvailable() { return platform::lcdLanes + platform::i2sLanes; } - static constexpr bool kPowerOfTwoBus = true; // the BUS rounds to 8/16; the pin count is free + uint8_t lanesAvailable() const override { return platform::lcdLanes + platform::i2sLanes; } + bool powerOfTwoBus() const override { return true; } // the BUS rounds to 8/16; the pin count is free /// Whole-frame DMA byte budget. On the classic ESP32 the i80 is the I2S peripheral: its DMA is /// INTERNAL-RAM only (no PSRAM) and it holds the whole frame (no streaming ring), so a frame larger @@ -105,8 +106,8 @@ class MultiPinLedDriver : public ParallelLedDriver { /// downgrades the optional second (doubleBuffer) buffer on its own when only one fits. The classic /// path is bounded by construction, so it never returns 0 (which means "no bound"): when the block /// is at or under the reserve, it reports a small positive floor so the fit gate still rejects. - /// On the LCD_CAM chips (S3/P4) the DMA reaches PSRAM β†’ 0 = no bound (the base default). COLD PATH. - size_t dmaBudgetBytes() const { + /// On the LCD_CAM chips (S3/P4) the DMA reaches PSRAM β†’ 0 = no bound (the interface default). COLD PATH. + size_t dmaBudgetBytes() const override { if constexpr (platform::i2sLanes > 0) { const size_t block = platform::maxInternalAllocBlock(); constexpr size_t kReserve = 16 * 1024; // descriptors + headroom for allocs after this query @@ -119,45 +120,39 @@ class MultiPinLedDriver : public ParallelLedDriver { // The i80 loopback can't build a 1-lane private bus, so it rebuilds the FULL-WIDTH bus and // carries the pattern on lane 0 β€” the loopback frame must be encoded at the operational bus - // width (16-bit for a 16-lane driver) to match. (Parlio can do a 1-lane unit, so it sets false.) - static constexpr bool kLoopbackFullWidth = true; - static constexpr const char* kInitFailMsg = "i80 bus init failed β€” check pins / memory"; + // width (16-bit for a 16-lane driver) to match. (Parlio can do a 1-lane unit, so its backend + // sets false.) + bool loopbackFullWidth() const override { return true; } + /// The classic ESP32's esp_lcd-i80 backend IS the I2S peripheral; on the S3/P4 it is LcdCam (shared + /// with MoonI80, which is why the two conflict). Keys on the same i2sLanes flag lanesAvailable does. + LedHwBlock hwBlock() const override { + if constexpr (platform::i2sLanes > 0) return LedHwBlock::I2s; + else return LedHwBlock::LcdCam; + } + const char* initFailMsg() const override { return "i80 bus init failed β€” check pins / memory"; } /// Spare bus lanes (shift mode, when the board has fewer data pins than the bus is wide) park on /// WR: the peripheral already drives it and the board already wires it, so the lane is inert. - /// (Hides the base default; this is the "ghost pin" the platform layer uses for the same reason.) - uint16_t clockPinForBus() const { return static_cast(clockPin); } + /// (Overrides the interface default; this is the "ghost pin" the platform layer uses for the same + /// reason.) + uint16_t clockPinForBus() const override { return static_cast(clockPin); } /// Bind the i80-specific bus controls: the sacrificial WR (clockPin) and DC pins /// the peripheral mandates. - void addBusControls() { - controls_.addPin("clockPin", clockPin); - controls_.addPin("dcPin", dcPin); + void addBusControls(ControlList& controls) override { + controls.addPin("clockPin", clockPin); + controls.addPin("dcPin", dcPin); } /// A clockPin or dcPin change triggers a bus rebuild via the prepare sweep. - bool busControlTriggersBuild(const char* name) const { + bool busControlTriggersBuild(const char* name) const override { return std::strcmp(name, "clockPin") == 0 || std::strcmp(name, "dcPin") == 0; } - /// Reject a data lane that collides with the WR (clockPin) or DC pin. The i80 - /// peripheral routes a distinct output signal to each of the 8 data lanes plus - /// WR + DC via the GPIO matrix; IDF does NOT check that they differ, so a data - /// pin equal to clockPin/dcPin gets two signals on one GPIO and that lane emits - /// the clock/DC waveform instead of pixel data (silent corruption β€” the strip on - /// that lane shows garbage). Fail loud + idle instead, same shape as the other - /// parse errors. (Hides the base's no-op default; the base calls this via CRTP.) - // Returns a WARNING string (not an error) if a data lane sits on clockPin (WR) or - // dcPin: that lane emits the bus-control waveform instead of pixel data. It's a - // warning because on a board that wires all 8/16 lanes but drives fewer strands, - // parking WR/DC on an unused data pin is a valid choice β€” only a lane driving a - // real strand shows garbage. The base routes this to setConfigWarn; the driver - // keeps running. null when the WR/DC pins are clear of the data set. /// FATAL bus-pin check β†’ routed to the ERROR path (idles the driver), unlike validateBusPins' /// per-lane WARNINGS. WR and DC on the SAME GPIO breaks the i80 bus outright (it needs two /// distinct control lines β€” the bus won't init), so it can't be a warn-and-run like a data-lane - /// collision (which only corrupts that one lane). null = no fatal condition. (CRTP hook; the - /// base's default returns null, Parlio has no WR/DC and keeps the default.) - const char* validateBusFatal() const { + /// collision (which only corrupts that one lane). null = no fatal condition. + const char* validateBusFatal() const override { if (clockPin >= 0 && clockPin == dcPin) return "clockPin (WR) and dcPin are the same GPIO β€” they must differ"; // The '595 latch is a BUS LANE, so it needs its own GPIO: sharing it with WR would make the @@ -165,16 +160,29 @@ class MultiPinLedDriver : public ParallelLedDriver { // sharing it with DC would latch on the command phase. Both are fatal β€” the bus builds, but // the strands get garbage β€” so this is an error, not a warning. (Bench-found: WR defaults to // GPIO 10, which is the first pin a user reaches for when picking a latch.) - if (pinExpanderMode() && latchPin >= 0) { - if (latchPin == clockPin) + if (owner_->pinExpanderMode() && owner_->latchPin >= 0) { + if (owner_->latchPin == clockPin) return "latchPin is on clockPin (WR) β€” the latch needs its own GPIO"; - if (latchPin == dcPin) + if (owner_->latchPin == dcPin) return "latchPin is on dcPin β€” the latch needs its own GPIO"; } return nullptr; } - const char* validateBusPins(const uint16_t* lanes, uint8_t n) const { + /// Reject a data lane that collides with the WR (clockPin) or DC pin. The i80 + /// peripheral routes a distinct output signal to each of the 8 data lanes plus + /// WR + DC via the GPIO matrix; IDF does NOT check that they differ, so a data + /// pin equal to clockPin/dcPin gets two signals on one GPIO and that lane emits + /// the clock/DC waveform instead of pixel data (silent corruption β€” the strip on + /// that lane shows garbage). Fail loud + idle instead, same shape as the other + /// parse errors. + // Returns a WARNING string (not an error) if a data lane sits on clockPin (WR) or + // dcPin: that lane emits the bus-control waveform instead of pixel data. It's a + // warning because on a board that wires all 8/16 lanes but drives fewer strands, + // parking WR/DC on an unused data pin is a valid choice β€” only a lane driving a + // real strand shows garbage. The orchestrator routes this to setConfigWarn, the driver + // keeps running. null when the WR/DC pins are clear of the data set. + const char* validateBusPins(const uint16_t* lanes, uint8_t n) const override { for (uint8_t i = 0; i < n; i++) { // clockPin/dcPin are int8_t (-1 = unset); only a real GPIO can collide. if (clockPin >= 0 && lanes[i] == static_cast(clockPin)) @@ -188,62 +196,62 @@ class MultiPinLedDriver : public ParallelLedDriver { /// Create the i80 bus + its DMA buffer(s) sized for `frameBytes` on the current data lanes plus /// the WR/DC pins; `wantSecondBuffer` requests the async double-buffer's second frame buffer /// (allocated only if it fits β€” else single-buffer). Returns whether init succeeded. - /// **LCD_CAM** is the one backend that can host the 74HCT595 expander: it reaches PSRAM (so the + /// **LCD_CAM** is the one silicon path that can host the 74HCT595 expander: it reaches PSRAM (so the /// Γ—8 frame fits), it has no single-transfer cap, and its WR pixel-clock pin IS the shift clock a - /// '595 needs. The classic ESP32 shares this class but not that backend β€” its i80 is the I2S + /// '595 needs. The classic ESP32 shares this backend but not that silicon path β€” its i80 is the I2S /// peripheral, whose DMA cannot read PSRAM at all, so a 154 KB frame has nowhere to live. Keying /// the flag on `lcdLanes` (non-zero only on the LCD_CAM chips, S3/P4) makes the refusal a - /// compile-time property of the silicon rather than a runtime surprise, and the base then reports - /// it as a config error instead of letting the bus die at init with "check pins / memory". - static constexpr bool kSupportsPinExpander = platform::lcdLanes > 0; + /// compile-time property of the silicon rather than a runtime surprise, and the orchestrator then + /// reports it as a config error instead of letting the bus die at init with "check pins / memory". + bool supportsPinExpander() const override { return platform::lcdLanes > 0; } - /// The bus pin list comes from the base: in shift mode it appends the latch to the data pins + /// The bus pin list comes from the orchestrator: in shift mode it appends the latch to the data pins /// (the latch is a bus lane), so the peripheral drives it. busClockMultiplier() tells the platform /// how many bus words one WS2812 slot is shifted out over, so it can scale the pixel clock and the /// slot keeps its wire duration. - bool busInit(size_t frameBytes, bool wantSecondBuffer) { - return platform::i80Ws2812Init(i80_, this->busPinList(), this->busPinCount(), + bool busInit(size_t frameBytes, bool wantSecondBuffer) override { + return platform::i80Ws2812Init(i80_, owner_->busPinList(), owner_->busPinCount(), static_cast(clockPin), static_cast(dcPin), frameBytes, wantSecondBuffer, - this->busClockMultiplier()); + owner_->busClockMultiplier()); } - /// DMA buffer `i` (0/1) the base encodes into; buffer 1 is null when the second + /// DMA buffer `i` (0/1) the orchestrator encodes into; buffer 1 is null when the second /// buffer didn't fit (single-buffer mode). Both are the same size (busCapacity). - uint8_t* busBuffer(uint8_t i) { return platform::i80Ws2812Buffer(i80_, i); } + uint8_t* busBuffer(uint8_t i) override { return platform::i80Ws2812Buffer(i80_, i); } /// The per-buffer byte capacity (fixed at bus creation; both buffers equal). - size_t busCapacity() const { return platform::i80Ws2812BufferCapacity(i80_); } + size_t busCapacity() const override { return platform::i80Ws2812BufferCapacity(i80_); } /// Kick off the autonomous transfer of the first `bytes` of DMA buffer `i`; /// returns whether it started. - bool busTransmit(uint8_t i, size_t bytes) { return platform::i80Ws2812Transmit(i80_, i, bytes); } + bool busTransmit(uint8_t i, size_t bytes) override { return platform::i80Ws2812Transmit(i80_, i, bytes); } /// Block up to `ms` for buffer `i`'s in-flight transfer to complete. - bool busWait(uint8_t i, uint32_t ms) { return platform::i80Ws2812Wait(i80_, i, ms); } + bool busWait(uint8_t i, uint32_t ms) override { return platform::i80Ws2812Wait(i80_, i, ms); } /// The most recent DMA transfer's wire time (Β΅s) β€” the WS2812 output floor. - uint32_t busLastTransmitUs() const { return platform::i80Ws2812LastTransmitUs(i80_); } + uint32_t busLastTransmitUs() const override { return platform::i80Ws2812LastTransmitUs(i80_); } /// Tear down the i80 bus and its DMA buffer. - void busDeinit() { platform::i80Ws2812Deinit(i80_); } + void busDeinit() override { platform::i80Ws2812Deinit(i80_); } /// Run the loopback self-test. The i80 layer requires all 8 data GPIOs valid, so /// a 1-lane private bus is impossible; the loopback builds the full-width bus and /// carries the pattern on lane 0. Passes the WR/DC pins the init needs. platform::RmtLoopbackResult busLoopback(const uint8_t* frame, size_t frameBytes, - size_t dataBytes, uint8_t rowBits) { - // The private bus is built from the base's bus pin list (which appends the latch in shift - // mode β€” the latch is a bus lane) and at the shift-mode pclk, so the test transmits exactly - // what the render loop does. In direct mode both reduce to today's behaviour. - return platform::i80Ws2812Loopback(this->busPinList(), this->busPinCount(), + size_t dataBytes, uint8_t rowBits) override { + // The private bus is built from the orchestrator's bus pin list (which appends the latch in + // shift mode β€” the latch is a bus lane) and at the shift-mode pclk, so the test transmits + // exactly what the render loop does. In direct mode both reduce to today's behaviour. + return platform::i80Ws2812Loopback(owner_->busPinList(), owner_->busPinCount(), static_cast(clockPin), static_cast(dcPin), - static_cast(loopbackRxPin), + static_cast(owner_->loopbackRxPin), frame, frameBytes, dataBytes, rowBits, - this->busClockMultiplier()); + owner_->busClockMultiplier()); } /// Store WR/DC alongside the data pins, so a clockPin/dcPin edit rebuilds the /// bus too (not just a data-pin change). - void recordBusPins() { lastClockPin_ = clockPin; lastDcPin_ = dcPin; } + void recordBusPins() override { lastClockPin_ = clockPin; lastDcPin_ = dcPin; } /// Whether the live bus's WR/DC pins still match the current clockPin/dcPin (so - /// the base can skip a rebuild). - bool extraBusPinsCurrent() const { + /// the orchestrator can skip a rebuild). + bool extraBusPinsCurrent() const override { return lastClockPin_ == clockPin && lastDcPin_ == dcPin; } @@ -253,4 +261,11 @@ class MultiPinLedDriver : public ParallelLedDriver { int8_t lastDcPin_ = -1; }; +// Register the esp_lcd-i80 backend into the ParallelLedDriver peripheral registry once, at static-init. +// The label is what the `peripheral` Select shows. Gated by this header's own CONFIG_SOC include in +// main.cpp, so it only registers on i80-capable silicon. There is no separate driver class: the one +// registered ParallelLedDriver drives every backend, selected by the `peripheral` control. +inline const bool kI80PeripheralRegistered = + ParallelLedDriver::registerPeripheral("i80", []() -> LedPeripheral* { return new I80Peripheral(); }); + } // namespace mm diff --git a/src/light/drivers/ParallelLedDriver.h b/src/light/drivers/ParallelLedDriver.h index 2648d65e..a8318ab6 100644 --- a/src/light/drivers/ParallelLedDriver.h +++ b/src/light/drivers/ParallelLedDriver.h @@ -1,6 +1,7 @@ #pragma once #include "light/drivers/DriverBase.h" // DriverBase, Correction +#include "light/drivers/LedPeripheral.h" // runtime peripheral strategy (Parlio / i80 / MoonI80) #include "light/drivers/ParallelSlots.h" // encodeWs2812ParallelSlots (shared encoder) #include "light/drivers/LedDriverConfig.h" #include "light/drivers/PinList.h" // parsePinList / assignCounts (shared) @@ -10,10 +11,10 @@ namespace mm { -template -/// Base for the parallel WS2812B LED-output drivers β€” the S3's LCD_CAM i80 bus (MultiPinLedDriver) and -/// the P4's Parlio peripheral (ParlioLedDriver). Both drive up to 16 strands that clock out -/// SIMULTANEOUSLY, one GPIO lane each, fed consecutive slices of the source buffer (see kMaxLanes). +/// The one registered parallel WS2812B LED-output driver. It drives up to 16 strands that clock out +/// SIMULTANEOUSLY, one GPIO lane each, fed consecutive slices of the source buffer (see kMaxLanes), over +/// whichever bus peripheral the `peripheral` control selects at runtime (the S3's LCD_CAM i80 bus, its +/// own-GDMA MoonI80 shift-ring, or the P4's Parlio peripheral β€” see the LedPeripheral strategy below). /// (Vocabulary β€” strand / lane / slot / row β€” under @xref{terminology|More info β†’ Terminology}.) /// /// **How it works: encode the whole frame, then hand it to the DMA and walk away.** Every WS2812 bit of @@ -32,14 +33,16 @@ template /// by `ledsPerPin` with the remainder split evenly β€” the same rule (and the same parser) as /// RmtLedDriver, so a strand count means the same thing on every LED driver. /// -/// **CRTP, not virtual calls.** The base calls into the derived through -/// `static_cast(this)->busX()`, so the shared body costs no vtable and no runtime indirection -/// on the hot path, and the module tree stays the project's one deliberate class hierarchy (the only -/// virtual boundary is MoonModule -> DriverBase). A derived driver supplies only the peripheral-specific -/// pieces: the `bus*` platform wrappers, `lanesAvailable()` (which makes it inert on the wrong chip), -/// `kPowerOfTwoBus` (the i80 bus rounds to 8 or 16; Parlio's width IS its pin count), the slot rate -/// `kClockHz`, and any extra bus pins it owns. The two drivers were ~250 of ~370 lines byte-for-byte -/// identical before this base existed. +/// **A runtime `LedPeripheral` strategy, not compile-time CRTP.** The base calls into `peripheral_` +/// (a `LedPeripheral*`, see LedPeripheral.h) through one virtual-dispatch boundary per FRAME or per +/// reinit β€” never per light, so the per-light encode (the actual hot path) stays a direct call and pays +/// no vtable cost. A peripheral supplies only the variant-specific pieces: the `bus*` platform wrappers, +/// `lanesAvailable()` (which makes it inert on the wrong chip), `powerOfTwoBus()` (the i80 bus rounds to +/// 8 or 16; Parlio's width IS its pin count), and any extra bus pins it owns. Each backend header +/// (I80Peripheral, MoonI80Peripheral, ParlioPeripheral) self-registers its factory + label with the +/// peripheral registry, gated by its chip's CONFIG_SOC_*, so a board links only its usable backends and +/// the `peripheral` control offers that subset. A fresh driver wires the first usable backend so it is +/// functional out of the box; the control (or a catalog `peripheral` value) switches it live. /// /// @moreinfo /// @@ -58,9 +61,59 @@ template /// and an i80 bus word have the same meaning. class ParallelLedDriver : public DriverBase { public: - /// WS2812/SK6812 strips are GRB-wired, so a fresh parallel LED driver (and its MultiPinLedDriver - /// subclass) references the "GRB" preset by default. The user can pick any preset. - ParallelLedDriver() { this->setDefaultPresetName("GRB"); } + /// Test-only: swap in a peripheral backend for a test mock. Deinits + drops any existing peripheral + /// first (a rebuild-from-scratch, same as a real reinit would need). The caller retains ownership β€” + /// this borrows the pointer, exactly like a registered driver's own owned backend does not need a + /// test to manage its lifetime. + void setPeripheralForTest(LedPeripheral* p) { + if (peripheral_ && peripheralOwned_) { peripheral_->busDeinit(); delete peripheral_; } + else if (peripheral_) peripheral_->busDeinit(); + peripheral_ = p; + peripheralOwned_ = false; // the test owns a stack/heap mock; the orchestrator must not delete it + peripheralActiveReg_ = 0xFF; + if (p) p->attach(this); + } + + // --- Peripheral backend registry --- + // The set of peripheral backends compiled into THIS build. Each backend header self-registers its + // factory + label at static-init time (see MM_REGISTER_LED_PERIPHERAL below), gated by its chip's + // CONFIG_SOC_* β€” so a classic ESP32 only links the esp_lcd-i80 backend, an S3 links i80 + MoonI80, + // a P4 links all three. The `peripheral` Select then offers the linked-and-supported subset at + // runtime. Mirrors ModuleFactory's static-registration shape, one level down for the bus backend. + using PeripheralFactory = LedPeripheral* (*)(); + struct PeripheralEntry { const char* label; PeripheralFactory make; }; + static constexpr uint8_t kMaxPeripherals = 4; + static inline PeripheralEntry peripheralRegistry_[kMaxPeripherals] = {}; + static inline uint8_t peripheralRegistryCount_ = 0; + /// Register a backend factory under a UI label. Called once per linked backend at static-init. + /// Duplicate labels and overflow past kMaxPeripherals are ignored (the backstop is far above the + /// three real backends). + static bool registerPeripheral(const char* label, PeripheralFactory make) { + if (!label || !make || peripheralRegistryCount_ >= kMaxPeripherals) return false; + for (uint8_t i = 0; i < peripheralRegistryCount_; i++) + if (std::strcmp(peripheralRegistry_[i].label, label) == 0) return false; + peripheralRegistry_[peripheralRegistryCount_++] = {label, make}; + return true; + } + + /// WS2812/SK6812 strips are GRB-wired, so a fresh parallel LED driver references the "GRB" preset by + /// default (the user can pick any). A fresh driver also wires the first peripheral this chip supports + /// so it is functional out of the box; the `peripheral` control (or a catalog `peripheral` value) + /// switches it. On desktop no backend is linked, so peripheral_ stays null and the driver idles β€” + /// tests inject a mock via setPeripheralForTest. + ParallelLedDriver() { + this->setDefaultPresetName("GRB"); + selectDefaultPeripheral(nullptr); + } + + /// Free the owned backend. A registered driver's backend (created via the registry) is owned and + /// deleted here; a test-borrowed mock (setPeripheralForTest) is not β€” the ownership flag decides, + /// so the delete lives ONCE in the base rather than per thin subclass. The owner released()/removed + /// this driver before destruction (the DriverBase vptr-race contract), so the bus is already down. + ~ParallelLedDriver() override { + if (peripheral_ && peripheralOwned_) delete peripheral_; + peripheral_ = nullptr; + } /// Max parallel lanes = the peripheral's full 16 data lines. The bus width the driver /// actually builds is DERIVED from the configured pin count: ≀8 pins β†’ an 8-bit bus (uint8 @@ -257,10 +310,12 @@ class ParallelLedDriver : public DriverBase { /// The multiplier every size/clock/slot computation below is expressed in. uint8_t outputsPerPin() const { return pinExpander ? kPinExpanderOutputs : uint8_t(1); } - /// Bind the driver's controls: the window (start/count), the `pins` and - /// `ledsPerPin` text lists, any derived-supplied bus controls (i80 adds - /// clockPin/dcPin, Parlio none), and the loopback self-test controls (TX/RX pin - /// overrides always bound but shown only in test mode). + /// Bind the driver's controls: the peripheral-INVARIANT block first (window, `pins`, `ledsPerPin`, + /// doubleBuffer, frameTime, pinExpander β€” they describe *which LEDs and how many*, the same on any + /// backend), THEN the `peripheral` selector as a divider, THEN the peripheral-SPECIFIC controls the + /// chosen backend surfaces (i80's clockPin/dcPin, MoonI80's ring cluster). The loopback cluster is + /// last (expert). This ordering makes the card read top-down: everything above `peripheral` is + /// invariant; everything below is what that peripheral needs. void defineDriverControls() override { addWindowControls(); // start / count β€” the slice of the shared buffer this driver outputs controls_.addText("pins", pins, sizeof(pins)); @@ -273,26 +328,36 @@ class ParallelLedDriver : public DriverBase { // floor (independent of render load), so it shows how much headroom remains as the pipeline // improves β€” and it reflects an overclocked slot rate directly. Refreshed in tick1s(). controls_.addReadOnly("frameTime", frameTimeStr_, sizeof(frameTimeStr_)); - // A checkbox: the expander is fitted or it isn't. The '595's width (8) is the chip's, not a - // setting, so there is nothing to type β€” and a boolean can't be half-configured. + // The peripheral selector β€” the divider between the invariant block above and the + // peripheral-specific controls below. buildPeripheralOptions syncs peripheralSel_ to the live + // backend (or clamps it); when a peripheral CHANGE triggered this rebuild, peripheralSel_ already + // holds the NEW index (applyControlValue wrote it before rebuildControls), so + // ensurePeripheralMatchesSelection() makes the live object agree BEFORE addBusControls/addRingControls + // surface the chosen backend's controls. Always shown, even with a single option: with one backend + // it reads as a labelled indicator of what's driving the LEDs (e.g. "i80" on the classic). + buildPeripheralOptions(); + ensurePeripheralMatchesSelection(); + controls_.addSelect("peripheral", peripheralSel_, peripheralOptions_, peripheralOptionCount_); + // The bus pins sit UNDER the peripheral selector because they ARE peripheral-specific: for a driver + // that owns its own GPIO routing they are '595 pins: MoonI80 routes WR only when a shift register + // needs it as SRCLK, and hides the control otherwise. (I80 goes through esp_lcd, which mandates a + // valid WR *and* DC GPIO whatever the mode, so it shows both unconditionally β€” same hook, different answer.) + if (peripheral_) peripheral_->addBusControls(controls_); + // The 74HCT595 pin expander toggle + its latch pin. It comes BEFORE the ring cluster (below) + // because that cluster DEPENDS on it β€” the ring/shift controls are shown only when the expander + // is on, so the switch that controls them must sit above them (the dependent-below-controlling + // rule). Peripheral-specific β€” shown only when the SELECTED peripheral can host the '595 (i80 / + // MoonI80 on LCD_CAM; not Parlio, whose single-shot transfer can't carry the Γ—8 fan-out frame β€” + // a hardware limit, see supportsPinExpander). The '595's width (8) is the chip's, not a setting, + // so the toggle is a plain checkbox; latchPin is bound always (a saved value survives a + // round-trip through direct mode) but shown only when the expander is on. controls_.addBool("pinExpander", pinExpander); - // Hidden where the silicon can't host the '595 (the classic ESP32 i80 is the I2S peripheral, - // whose DMA can't read PSRAM, so the expander's Γ—8 frame has nowhere to live β€” see - // kSupportsPinExpander). Turning it on there only ever produces a config error, so don't offer - // the switch. A compile-time property of the chip; the control stays for S3/P4 (LCD_CAM). - controls_.setHidden(controls_.count() - 1, !Derived::kSupportsPinExpander); - // The bus pins sit UNDER the expander toggle because for a driver that owns its own GPIO - // routing they are '595 pins: MoonI80 routes WR only when a shift register needs it as SRCLK, - // and hides the control otherwise. (I80 goes through esp_lcd, which mandates a valid WR *and* - // DC GPIO whatever the mode, so it shows both unconditionally β€” same hook, different answer.) - derived()->addBusControls(); - // Always bound, shown only when the expander is on β€” the conditional-control shape - // (bound regardless so a saved latchPin survives a round-trip through direct mode). + controls_.setHidden(controls_.count() - 1, !(peripheral_ && peripheral_->supportsPinExpander())); controls_.addPin("latchPin", latchPin); controls_.setHidden(controls_.count() - 1, !pinExpanderMode()); - // A ring-capable backend's geometry, AFTER latchPin so the bus pins stay one unbroken group - // (clockPin and latchPin are a wiring pair). Default no-op; only MoonI80 rings. - derived()->addRingControls(); + // The ring cluster (MoonI80 only; default no-op) β€” shift-mode geometry, all gated on the + // expander being on, so it sits UNDER the pinExpander switch that governs it. + if (peripheral_) peripheral_->addRingControls(controls_); // The on-device loopback self-test + its wiring β€” a dev/bring-up instrument (jumper a lane to the // rx pin), not a casual-user setting, so the whole cluster is expert-only. controls_.addBool("loopbackTest", loopbackTest); @@ -330,7 +395,7 @@ class ParallelLedDriver : public DriverBase { || std::strcmp(name, "doubleBuffer") == 0 || std::strcmp(name, "pinExpander") == 0 || std::strcmp(name, "latchPin") == 0 || isWindowControl(name) - || derived()->busControlTriggersBuild(name); // clockPin/dcPin on i80 + || (peripheral_ && peripheral_->busControlTriggersBuild(name)); // clockPin/dcPin on i80 } /// React to a control change off the render loop. loopbackTest is a persistent @@ -338,6 +403,21 @@ class ParallelLedDriver : public DriverBase { /// lane-config refresh first, since onControlChanged precedes the prepare sweep); /// turning it OFF clears the verdict and re-derives the real driver status. void onControlChanged(const char* name) override { + // Peripheral swap: bring the newly-selected backend's bus up. Scheduler::setControl already ran + // rebuildControls() BEFORE this, and defineDriverControls calls ensurePeripheralMatchesSelection() + // off peripheralSel_ (the just-written index) β€” so the live backend was ALREADY swapped during the + // rebuild and the control list is bound to it. We must NOT swap again here: a second swapPeripheral + // would free that backend and build a third, leaving every backend-owned control (clockPin, ring + // cluster, ...) dangling into freed memory. ensurePeripheralMatchesSelection() is a no-op now + // (peripheralActiveReg_ already equals the wanted reg); we only re-parse against the new backend's + // descriptors (powerOfTwoBus differs Parlio vs i80) and reinit to bring the bus up. + if (std::strcmp(name, "peripheral") == 0) { + ensurePeripheralMatchesSelection(); + parseConfig(); + reinit(); + DriverBase::onControlChanged(name); + return; + } const bool isTestControl = std::strcmp(name, "loopbackTest") == 0; // Every control that reshapes the lane config the self-test transmits through. pinExpander // and latchPin belong here for the same reason `pins` does: they change laneList_, @@ -451,7 +531,7 @@ class ParallelLedDriver : public DriverBase { /// lifted the P4 whole-board rate 48β†’76 fps; OFF is the sound-reactive 0-latency opt-out and pays /// for exactly one buffer β€” see the doubleBuffer control + docs/history/lessons.md.) void tick() override { - if constexpr (Derived::lanesAvailable() == 0) return; // inert off this chip + if (!peripheral_ || peripheral_->lanesAvailable() == 0) return; // no backend / inert off this chip // Loopback mode owns the peripheral EXCLUSIVELY. While it is on, the render loop must not // transmit β€” the loopback tears the bus down, drives its own private frame, and rebuilds it. if (loopbackTest) return; @@ -467,15 +547,15 @@ class ParallelLedDriver : public DriverBase { // small internal buffers refilled by the platform, so it does NOT hold the whole frame and the // busCapacity() guard below (which the other two need) does not apply. The whole-frame paths keep // their guard and their proven behavior byte-for-byte. - if (derived()->busIsRing()) { tickRing(outCh); return; } - if (frameBytes_ > derived()->busCapacity()) return; + if (peripheral_->busIsRing()) { tickRing(outCh); return; } + if (frameBytes_ > peripheral_->busCapacity()) return; // Two explicitly-separate whole-frame paths so the OFF path is PROVABLY the pre-Step-1.5 behavior // (no regression) and pays nothing for the double-buffer it isn't using. The mode is fixed by // whether the second buffer was allocated (busInit(async) β€” ON allocs it, OFF doesn't), so a // stale flag can't route a single-buffer bus down the async path. - if (derived()->busBuffer(1)) tickAsync(outCh); // double-buffer (doubleBuffer ON) - else tickSync(outCh); // synchronous (doubleBuffer OFF / no 2nd buf) + if (peripheral_->busBuffer(1)) tickAsync(outCh); // double-buffer (doubleBuffer ON) + else tickSync(outCh); // synchronous (doubleBuffer OFF / no 2nd buf) } // Synchronous single-buffer path β€” the ORIGINAL tick, verbatim: encode buffer 0, transmit, wait @@ -488,7 +568,7 @@ class ParallelLedDriver : public DriverBase { // A previous frame's wait may have timed out, leaving the DMA still reading buffer 0 β€” re-wait // rather than encoding over a live transfer. (Normally a no-op: the wait below completes.) if (!busWaitIfBusy(0)) return; - uint8_t* buf = derived()->busBuffer(0); + uint8_t* buf = peripheral_->busBuffer(0); if (!buf) return; // Branch on the BUS WIDTH (slotBytes), not the strand count β€” with a '595 expander the // strands ride the shift cycles, so 48 strands on 6 pins is still an 8-bit bus. @@ -498,7 +578,7 @@ class ParallelLedDriver : public DriverBase { // LOW >=300 Β΅s. Wait only when the transfer started β€” a failed transmit gives no done-callback, // so an unconditional wait would block the full timeout. A timed-out wait leaves the buffer // marked in-flight so the next tick re-waits instead of corrupting the live transfer. - if (derived()->busTransmit(0, frameBytes_)) { + if (peripheral_->busTransmit(0, frameBytes_)) { inFlight_[0] = true; busWaitIfBusy(0); // synchronous: wait it out here; clears the flag on completion } @@ -520,14 +600,14 @@ class ParallelLedDriver : public DriverBase { // instead of emitting garbage, and it self-heals the moment the transfer completes. if (!busWaitIfBusy(active_)) return; // 2. Fused per-ROW encode into buffer `active_`, one branch on the bus width (see encodeRows). - uint8_t* buf = derived()->busBuffer(active_); + uint8_t* buf = peripheral_->busBuffer(active_); if (!buf) return; // Branch on the BUS WIDTH (slotBytes), not the strand count β€” with a '595 expander the // strands ride the shift cycles, so 48 strands on 6 pins is still an 8-bit bus. if (slotBytes() == 1) encodeRows(outCh, buf); else encodeRows(outCh, buf); // 3. Kick this buffer's DMA and return WITHOUT waiting; flip to the other buffer for next tick. - if (derived()->busTransmit(active_, frameBytes_)) { + if (peripheral_->busTransmit(active_, frameBytes_)) { inFlight_[active_] = true; active_ ^= 1; } @@ -570,7 +650,7 @@ class ParallelLedDriver : public DriverBase { if (ringSnapshot) { if (!snapshotSourceForRing()) return; } else encodeSrc_ = nullptr; // OFF: encodeRows reads the live sourceBuffer_ const uint32_t tkW2 = platform::cycleCount(); - if (derived()->busTransmitRing()) { + if (peripheral_->busTransmitRing()) { inFlight_[0] = true; // kicked; DO NOT wait here β€” the next tick waits, freeing the core now } const uint32_t tkW3 = platform::cycleCount(); @@ -591,17 +671,14 @@ class ParallelLedDriver : public DriverBase { /// the render loop can never beat it, so it's the target the multicore work drives the system tick /// toward, and it tracks an overclocked slot rate directly. "β€”" until the first transfer completes. void tick1s() override { - const uint32_t us = derived()->busLastTransmitUs(); + if (!peripheral_) return; + const uint32_t us = peripheral_->busLastTransmitUs(); if (us == 0) std::snprintf(frameTimeStr_, sizeof(frameTimeStr_), "β€”"); else std::snprintf(frameTimeStr_, sizeof(frameTimeStr_), "%u Β΅s (%u fps max)", static_cast(us), static_cast(1000000u / us)); - derived()->refreshBusKpi(); // per-backend extra read-only KPIs (MoonI80's ring diagnostic); base no-op + peripheral_->refreshBusKpi(); // per-backend extra read-only KPIs (MoonI80's ring diagnostic); base no-op } - /// CRTP hook: refresh any backend-specific read-only KPI once a second (off the hot path). Base is a - /// no-op; MoonLedDriver overrides it to publish its ring diagnostic counters (see ringDbg). - void refreshBusKpi() {} - // Wait for buffer `i`'s in-flight transfer to finish. Returns TRUE when the buffer is free to // reuse β€” either nothing was outstanding (first tick, or a transmit that failed to start, so an // unconditional wait can't block the full timeout) or the transfer completed. Returns FALSE when @@ -613,7 +690,7 @@ class ParallelLedDriver : public DriverBase { /// so callers arm it unconditionally instead of tracking state themselves. bool busWaitIfBusy(uint8_t i) { if (!inFlight_[i]) return true; - if (!derived()->busWait(i, waitBudgetMs())) { + if (!peripheral_ || !peripheral_->busWait(i, waitBudgetMs())) { // The transfer did not complete within many times its own wire time, so it is not going // to. Count it: a bus that keeps doing this is broken, and the ONLY thing that matters // then is that the driver stops spending the render thread on it (see deadFrames_). @@ -725,11 +802,11 @@ class ParallelLedDriver : public DriverBase { /// already carries data or is a zero the buffer's memset provides). Called from reinit(), the cold /// path, whenever the buffers are (re)established or re-zeroed. void prefillShiftConstantsIfNeeded() { - if (!pinExpanderMode() || !inited_) return; + if (!peripheral_ || !pinExpanderMode() || !inited_) return; const uint8_t outCh = correction_.outChannels; if (outCh == 0 || maxLaneLights_ == 0) return; for (uint8_t i = 0; i < 2; i++) { - uint8_t* buf = derived()->busBuffer(i); + uint8_t* buf = peripheral_->busBuffer(i); if (!buf) continue; // buffer 1 is null in single-buffer mode if (slotBytes() == 1) prefillShiftFrame(outCh, buf); else prefillShiftFrame(outCh, buf); @@ -936,6 +1013,11 @@ class ParallelLedDriver : public DriverBase { /// Test-only accessors β€” pin the lane slicing and frame-size arithmetic on the /// host (unit_{I80,Parlio}LedDriver.cpp); the hardware half is proven on device. uint8_t laneCount() const { return laneCount_; } + /// Which DMA buffer this tick encodes into (0/1) β€” the deferred-wait double-buffer's alternation + /// state. Test-only. + uint8_t activeForTest() const { return active_; } + /// Is buffer `i`'s DMA transfer outstanding (awaiting its wait)? Test-only. + bool inFlightForTest(uint8_t i) const { return inFlight_[i]; } /// Lights on lane `i` (0 if out of range). Test-only. nrOfLightsType laneLightCount(uint8_t i) const { return i < laneCount_ ? laneCounts_[i] : 0; } /// All POPULATED strands the same length? Gates the ring's prefill-skip: what the skip actually @@ -971,9 +1053,164 @@ class ParallelLedDriver : public DriverBase { /// Total DMA frame size in bytes (rows + latch pad). Test-only. size_t frameBytes() const { return frameBytes_; } + // --- Peripheral-facing accessors: a backend reaches the orchestrator's parsed lane list, latch + // bit, correction, and loopback pin through these (the back-pointer's read side β€” see owner_ in + // LedPeripheral.h). Replaces what CRTP inheritance gave a derived class for free. + /// Bus-bit index of the latch line (shift mode only) β€” a backend's addRingControls/encode seam + /// reads this through the owner pointer (e.g. masking the latch bit out of a bit-verify). + uint8_t latchBit() const { return latchBit_; } + /// The parsed physical data GPIOs (bus-width bound) β€” a backend's encode trampoline reads lane + /// state through the owner pointer instead of inheriting the array directly. + const uint16_t* laneList() const { return laneList_; } + /// The live output Correction (channel count, role wiring) β€” a backend's encode/prefill helpers + /// read `outChannels` through this instead of inheriting `correction_` directly. + const Correction& correction() const { return correction_; } + /// Mutable reference to the ring-snapshot A/B knob, for a backend's addRingControls to bind + /// (`controls.addBool("ringSnapshot", owner_->ringSnapshotRef())`) β€” addBool binds by reference, + /// so the control needs the member's address, not a copy. + bool& ringSnapshotRef() { return ringSnapshot; } + /// The ring snapshot buffer (null when unallocated / off the ring path) β€” a backend's KPI refresh + /// (MoonLedDriver::refreshBusKpi) reads this to report the buffer's memory residency (PSRAM vs + /// internal) through the owner pointer. + const uint8_t* snapshotBuf() const { return snapshotBuf_; } + /// The wired source buffer (null before setSourceBuffer) β€” same KPI-residency use as snapshotBuf(). + const Buffer* sourceBuffer() const { return sourceBuffer_; } + +protected: + // Fill peripheralOptions_/peripheralIndex_ from the registry, keeping only backends this chip can + // run (lanesAvailable() > 0), and reconcile peripheralSel_ so it still points at the SAME backend + // after the filter (or clamps into range). Built each defineDriverControls, so the Select always + // offers exactly what the board supports. A backend is created briefly to read its lanesAvailable() + // (a cheap object β€” no bus is brought up until busInit), then discarded. + void buildPeripheralOptions() { + // Remember which backend is selected now (by label) so we can re-find it after filtering. + const char* current = (peripheralSel_ < peripheralOptionCount_) ? peripheralOptions_[peripheralSel_] + : nullptr; + peripheralOptionCount_ = 0; + for (uint8_t i = 0; i < peripheralRegistryCount_ && peripheralOptionCount_ < kMaxPeripherals; i++) { + LedPeripheral* probe = peripheralRegistry_[i].make(); + const bool usable = probe && probe->lanesAvailable() > 0; + delete probe; + if (!usable) continue; + peripheralOptions_[peripheralOptionCount_] = peripheralRegistry_[i].label; + peripheralIndex_[peripheralOptionCount_] = i; + peripheralOptionCount_++; + } + if (peripheralOptionCount_ == 0) { // no usable backend on this chip (desktop) β€” a single inert row + peripheralOptions_[0] = "(none)"; + peripheralIndex_[0] = 0; + peripheralOptionCount_ = 1; + } + // Re-point the Select at the same backend it named before (labels are stable), else clamp. + uint8_t sel = 0; + if (current) + for (uint8_t k = 0; k < peripheralOptionCount_; k++) + if (std::strcmp(peripheralOptions_[k], current) == 0) { sel = k; break; } + peripheralSel_ = sel; + } + + // Tear down the current backend and build the one at filtered option slot `k`. Frees the old + // backend's bus + heap (only the selected peripheral costs memory β€” the product-owner requirement). + // Guarded so a bad index or an empty registry leaves peripheral_ null (tick() then idles). + void swapPeripheral(uint8_t k) { + deinit(); // stop any in-flight transfer on the old bus first + if (peripheral_) { + peripheral_->busDeinit(); + if (peripheralOwned_) delete peripheral_; // never delete a test-borrowed mock + peripheral_ = nullptr; + } + peripheralActiveReg_ = 0xFF; + peripheralOwned_ = false; + if (k >= peripheralOptionCount_) return; + const uint8_t reg = peripheralIndex_[k]; + if (reg >= peripheralRegistryCount_) return; + peripheral_ = peripheralRegistry_[reg].make(); + if (peripheral_) { peripheral_->attach(this); peripheralActiveReg_ = reg; peripheralOwned_ = true; } + } + + // Seed the default peripheral for a registered driver (called from its constructor with the backend's + // registry label). Builds the filtered options, points peripheralSel_ at `label` if this chip + // supports it (else the first usable backend β€” a board that names an unavailable default still gets a + // working driver), and swaps the live backend to match. From here the base's selector owns the rest. + void selectDefaultPeripheral(const char* label) { + buildPeripheralOptions(); + peripheralSel_ = 0; // fallback: the first usable backend (a board naming an absent default + // still gets a working driver, and `label == nullptr` means "first"). + if (label) + for (uint8_t k = 0; k < peripheralOptionCount_; k++) + if (std::strcmp(peripheralOptions_[k], label) == 0) { peripheralSel_ = k; break; } + swapPeripheral(peripheralSel_); + } + + // Make the live backend match peripheralSel_. When a `peripheral` control change triggered a + // control rebuild, peripheralSel_ already holds the new index but peripheral_ is still the old + // backend β€” this swaps it so the schema below surfaces the right controls. A no-op when they + // already agree (the common rebuild-for-another-reason case), so it's cheap on every rebuild. + void ensurePeripheralMatchesSelection() { + // A test-borrowed mock (setPeripheralForTest β†’ !peripheralOwned_) is deliberate β€” never swap it + // out from under the test for a registry backend. + if (peripheral_ && !peripheralOwned_) return; + const uint8_t wantReg = (peripheralSel_ < peripheralOptionCount_) ? peripheralIndex_[peripheralSel_] + : 0xFF; + if (peripheral_ && peripheralActiveReg_ == wantReg) return; // already correct + swapPeripheral(peripheralSel_); + } + + // The peripheral-block claim guard: is a SIBLING driver under the same Drivers container already + // driving the hardware block this driver's peripheral wants? The chip has one of each block (one + // LcdCam, one Parlio, one I2S), so two live drivers on the same block corrupt each other. Returns + // true when the block is already claimed. RTTI-free (ESP32 builds -fno-rtti): siblings are compared + // through the virtual `hwBlock()` on every module β€” a non-parallel driver (RMT, NetworkSend) and any + // other module return None, so no cast is needed. Walks the parent's children; skips self + disabled. + bool siblingClaimsBlock() const { + if (!peripheral_) return false; + const LedHwBlock mine = peripheral_->hwBlock(); + if (mine == LedHwBlock::None) return false; + const MoonModule* p = parent(); + if (!p) return false; + for (uint8_t i = 0; i < p->childCount(); i++) { + const MoonModule* sib = p->child(i); + if (sib == this || !sib || !sib->enabled()) continue; + // Every child of Drivers is a DriverBase (role Driver), so this static_cast is safe once + // role() confirms it β€” no RTTI. A non-parallel driver returns None from hwBlock(). + if (sib->role() != ModuleRole::Driver) continue; + if (static_cast(sib)->hwBlock() == mine) return true; + } + return false; + } + +public: + /// The hardware peripheral block this driver is DRIVING, for the sibling claim guard (overrides + /// DriverBase). Gated on inited_: a driver reports its block only while it actually holds the bus, + /// not merely from having a backend selected. Without this a driver that was itself refused (or has + /// no pins yet) would still "claim" the block, so the next prepare sweep β€” re-running a working + /// sibling's reinit() for an unrelated reason (a grid resize, a pin edit) β€” would see the phantom + /// claim and dark the live wall too. The claim must mean "the bus is up", which is exactly inited_. + /// siblingClaimsBlock() derives its OWN block from peripheral_ directly, so gating here only affects + /// how OTHER drivers see this one β€” precisely the intent. + LedHwBlock hwBlock() const override { + return (inited_ && peripheral_) ? peripheral_->hwBlock() : LedHwBlock::None; + } + protected: - Derived* derived() { return static_cast(this); } - const Derived* derived() const { return static_cast(this); } + + + /// The runtime backend. Null only before a registered driver's constructor wires its default + /// backend (or after a test detaches one) β€” every method that dereferences it guards first. + LedPeripheral* peripheral_ = nullptr; + + // The `peripheral` Select's state. peripheralSel_ indexes into the BOARD-FILTERED option list + // (only backends with lanesAvailable() > 0 on this chip), whose labels are held in peripheralOptions_ + // β€” a stable member array because addSelect borrows the pointer (same pattern as presetOptions_). + // peripheralIndex_[k] maps filtered slot k back to its registry index, so a Select change can create + // the right backend. All three are (re)built by buildPeripheralOptions(). + uint8_t peripheralSel_ = 0; + const char* peripheralOptions_[kMaxPeripherals] = {}; + uint8_t peripheralIndex_[kMaxPeripherals] = {}; + uint8_t peripheralOptionCount_ = 0; + uint8_t peripheralActiveReg_ = 0xFF; // registry index the LIVE peripheral_ came from (0xFF = none) + bool peripheralOwned_ = false; // does the orchestrator own peripheral_ (delete it) β€” false + // for a test-borrowed mock (setPeripheralForTest) Buffer* sourceBuffer_ = nullptr; @@ -1183,57 +1420,14 @@ class ParallelLedDriver : public DriverBase { // can keep the same frameBytes_ yet needs // a rebuild, so the fast path checks it too - static constexpr uint8_t maxLanesForTarget() { - return (Derived::lanesAvailable() > 0 && Derived::lanesAvailable() < kMaxLanes) - ? Derived::lanesAvailable() - : kMaxLanes; + /// The pin-list parser's cap: the peripheral's own lane count when it's narrower than kMaxLanes + /// (Parlio may report fewer), else the full kMaxLanes. Falls back to kMaxLanes with no peripheral + /// attached yet (parseConfig then has nothing to parse anyway). + uint8_t maxLanesForTarget() const { + const uint8_t avail = peripheral_ ? peripheral_->lanesAvailable() : 0; + return (avail > 0 && avail < kMaxLanes) ? avail : kMaxLanes; } - /// CRTP hook (default: no extra bus pins to validate). A derived driver whose - /// peripheral commits its own GPIOs beyond the data lanes (the i80 bus's WR/DC) - /// HIDES this to flag a data lane that overlaps them. Returns a WARNING string - /// (the driver keeps running β€” see MultiPinLedDriver::validateBusPins for why it's a - /// warning, not a blocker) or null when the data pins are clean. Parlio has no - /// such pins, so it uses this default. - const char* validateBusPins(const uint16_t* /*lanes*/, uint8_t /*n*/) const { return nullptr; } - - /// FATAL bus-pin check β†’ the ERROR path (idles the driver), for a bus-pin misconfig the peripheral - /// can't init at all (MultiPinLedDriver's clockPin==dcPin). Distinct from validateBusPins' per-lane - /// warnings. Default null; a peripheral with bus control pins overrides it. Parlio has none. - const char* validateBusFatal() const { return nullptr; } - - /// CRTP ring hooks (default: this peripheral has no streaming ring, so it never rings). Only MoonI80 - /// β€” which owns its DMA β€” overrides these to stream a frame too big for internal RAM (see its - /// busInitRing / the tickRing path). The esp_lcd I80 (the memory-capped reference) and Parlio use - /// these defaults: busIsRing() is always false, so tick() never selects tickRing and the ring transmit - /// is never called. reinit() consults wantsRing() to decide whether to attempt a ring build at all. - bool wantsRing() const { return false; } // should reinit try the ring for this config? - void addRingControls() {} // a ring-capable backend's geometry controls - bool busInitRing(size_t /*rowBytes*/, uint32_t /*totalRows*/) { return false; } - bool busIsRing() const { return false; } - bool busTransmitRing() { return false; } - /// The ring's regime as a one-word status suffix ("primed" / "lapping"), or null when not ringing β€” - /// so the driving-status line shows which side of the streaming boundary a config sits on. - const char* busRingMode() const { return nullptr; } - /// Byte ceiling on a whole-frame DMA buffer, or 0 for "no bound". Default 0: the PSRAM-DMA chips - /// (S3/P4 LCD_CAM) and the streaming ring (never materialises a whole frame) have no such limit. - /// Only a driver whose DMA is internal-RAM-only AND holds the whole frame overrides it (MultiPin on - /// the classic ESP32). reinit() pre-checks frameBytes_ against this and idles with a clear status if - /// it won't fit, rather than choking the bus init on an impossible allocation. Cold path. - size_t dmaBudgetBytes() const { return 0; } - /// Core-0 helper hook (default: no helper). Only the ring driver overrides it, spawning a core-0 - /// worker that primes half the ring pool while core 1 primes the other half (busTransmitRing's - /// fork-join). ready() is true only when the render/encode split is engaged AND the helper task is up. - /// (The snapshot copy is always serial β€” forking it saturated core 0; see snapshotSourceForRing.) - bool snapHelperReady() const { return false; } - - /// CRTP hook: the GPIO a SPARE bus lane is parked on when the pin list is narrower than the bus - /// width (shift mode β€” the board decides the data-pin count, the peripheral decides the width). - /// The i80 driver hides this to return its WR pin, which the peripheral already drives; a - /// peripheral that accepts NC lanes (Parlio) never calls it. Default: lane 0's pin, so a spare - /// lane is at worst a harmless duplicate of a pin the bus already owns. - uint16_t clockPinForBus() const { return laneList_[0]; } - // Frame bytes: longest lane Γ— channels Γ— 24 slots, plus a zeroed latch pad of // >=300 Β΅s at the slot rate (800 slots) with clock-tolerance slack (64), each // scaled by `slotBytes` (1 for an 8-bit bus, 2 for a 16-bit bus β€” a slot is one @@ -1278,12 +1472,6 @@ class ParallelLedDriver : public DriverBase { return budgetBytes == 0 || frameBytes <= budgetBytes; } - // Bytes per bus slot: 1 for the 8-bit bus, 2 for the 16-bit bus. Keys on the PHYSICAL - // pin count, not laneCount_ β€” with a '595 expander the lanes ride the shift cycles, not - // extra bus bits, so 48 lanes on 6 pins is still an 8-bit bus. (In direct mode the two - // counts are equal, so this is the original behaviour.) - uint8_t slotBytes() const { return busWidthPins() > 8 ? 2 : 1; } - // The i80 bus width is a POWER OF TWO (8 or 16) β€” a peripheral fact, independent of how many // strands the board drives. In direct mode the pin list already fills it exactly. In shift mode // the board decides the data-pin count (how many '595s are populated), so the driver rounds up to @@ -1310,12 +1498,18 @@ class ParallelLedDriver : public DriverBase { // the peripheral a short array while busPinCount() claims the full width β€” a read past the end. // Kept in the base (one owner of the latch + the padding), so both derived busInit()s just pass // these two calls. +public: + /// Public: a backend (a separate LedPeripheral, reached through the owner_ back-pointer) builds its + /// bus from this + busPinCount()/busClockMultiplier(), same as busPinList()/busPinCount()/slotBytes() + /// below β€” the bus-geometry accessors a backend needs are public, everything else in this block stays + /// protected (this driver's own cold-path config machinery). const uint16_t* busPinList() { const uint8_t width = busWidthPins(); + const uint16_t clockPin = peripheral_ ? peripheral_->clockPinForBus() : laneList_[0]; for (uint8_t i = 0; i < width && i < kMaxLanes; i++) { if (i < physPins_) busPinBuf_[i] = laneList_[i]; // data else if (pinExpanderMode() && i == latchBit_) busPinBuf_[i] = static_cast(latchPin); - else busPinBuf_[i] = derived()->clockPinForBus(); + else busPinBuf_[i] = clockPin; } return busPinBuf_; } @@ -1324,6 +1518,13 @@ class ParallelLedDriver : public DriverBase { // that much faster to hold the same 375 ns slot on the wire. The platform picks the exact rate // its clock tree can divide to (see platform_esp32_i80.cpp); this is the multiplier. uint8_t busClockMultiplier() const { return outputsPerPin(); } + // Bytes per bus slot: 1 for the 8-bit bus, 2 for the 16-bit bus. Keys on the PHYSICAL + // pin count, not laneCount_ β€” with a '595 expander the lanes ride the shift cycles, not + // extra bus bits, so 48 lanes on 6 pins is still an 8-bit bus. (In direct mode the two + // counts are equal, so this is the original behaviour.) A backend's encode trampoline + // (MoonLedDriver::ringEncodeTrampoline) branches on this through the owner_ pointer. + uint8_t slotBytes() const { return busWidthPins() > 8 ? 2 : 1; } +protected: // (Re)size the per-row correction scratch to kMaxLanes Γ— outCh bytes. Grows-only, off the hot // path (called from parseConfig). Sizing to outCh β€” not a fixed 4 β€” is what lets encodeRows lay @@ -1349,12 +1550,13 @@ class ParallelLedDriver : public DriverBase { const char* err = parsePinList(pins, laneList_, maxLanesForTarget(), n); // (Nothing to validate about the fan-out itself: pinExpander is a bool, so the only two // wirings that physically exist are the only two it can express.) - // The shift-register expander needs a backend that can DMA the 8Γ— frame from PSRAM: - // the LCD_CAM i80 path (S3 / P4). Refuse it elsewhere rather than emit a waveform the hardware - // can't sustain β€” classic-ESP32 i80 is internal-DMA-only (it walls ~76 KB; its route in is the - // PSRAM refill ring), and Parlio caps a single transfer at 65,535 B. - if (!err && pinExpanderMode() && !Derived::kSupportsPinExpander) - err = "the 74HCT595 expander needs the LCD_CAM i80 bus (ESP32-S3 / -P4)"; + // The shift-register expander needs a backend that can DMA the 8Γ— frame from PSRAM: the LCD_CAM + // i80 path (S3 / P4). On a peripheral that can't (classic-ESP32 i80 = internal-DMA-only I2S, or + // Parlio's 65,535 B single-transfer cap), SILENTLY drop back to direct mode rather than erroring: + // the `pinExpander` control is HIDDEN on such a peripheral (see supportsPinExpander), so a user + // who lands here β€” via a saved config or a peripheral switch β€” has no toggle to turn it off. An + // unfixable error status is the wrong answer; degrade to the working direct path (robust-to-any-input). + if (pinExpander && !(peripheral_ && peripheral_->supportsPinExpander())) pinExpander = false; // The latch is a real GPIO and a real bus bit; without it the '595s never present a byte. if (!err && pinExpanderMode() && latchPin < 0) err = "the 74HCT595 expander needs a latchPin"; // **The BUS width is a peripheral fact; the PIN COUNT is a board fact. They are not the same @@ -1367,7 +1569,7 @@ class ParallelLedDriver : public DriverBase { // // In shift mode the LATCH also occupies a bus bit, so it costs one of the width's lanes β€” // hence kMaxLanes - 1 data pins there against kMaxLanes here. - if constexpr (Derived::kPowerOfTwoBus) { + if (peripheral_ && peripheral_->powerOfTwoBus()) { const uint8_t maxData = static_cast(kMaxLanes - (pinExpanderMode() ? 1 : 0)); if (!err && (n == 0 || n > maxData)) err = pinExpanderMode() ? "shift mode needs 1..15 data pins (one per populated 74HCT595)" @@ -1386,15 +1588,15 @@ class ParallelLedDriver : public DriverBase { // Fatal bus-pin misconfig (MultiPinLedDriver's clockPin==dcPin β€” the i80 bus can't init) β†’ the // error path below, which idles the driver. Checked before the per-lane WARNINGS: a broken // bus is worse than a garbled lane, so it wins the status. - if (!err) err = derived()->validateBusFatal(); + if (!err && peripheral_) err = peripheral_->validateBusFatal(); // Peripheral-specific data-pin check (i80's WR/DC on a data lane routes two // output signals to one pin, so that lane emits the clock/DC waveform, not // pixel data). This is a WARNING, not a blocker: on a board that wires all // 8/16 lanes but drives fewer strands, an unused data pin is a legitimate // WR/DC candidate β€” only the lanes that actually drive a strand would show // garbage, and the user opted into that. Parlio has no WR/DC and returns null. - // Kept a CRTP hook so the base stays peripheral-neutral. - const char* warn = err ? nullptr : derived()->validateBusPins(laneList_, n); + // Kept a peripheral hook so the base stays backend-neutral. + const char* warn = (err || !peripheral_) ? nullptr : peripheral_->validateBusPins(laneList_, n); // STRAND lanes: each physical pin fans out to outputsPerPin() strands through its '595. // This is the count ledsPerPin distributes over and the encoder indexes β€” from here on // "lane" means a strand, and physPins_ holds the GPIO count. @@ -1453,7 +1655,17 @@ class ParallelLedDriver : public DriverBase { // row bytes. --- void reinit() { - if constexpr (Derived::lanesAvailable() == 0) return; + if (!peripheral_ || peripheral_->lanesAvailable() == 0) return; + // Peripheral-block claim guard: the chip has ONE of each block (one LcdCam, one Parlio, one + // I2S), so a second live driver on the same block would corrupt the first's DMA. If a sibling + // already holds this peripheral's block, idle with a clear status instead of fighting over the + // hardware β€” the same fail-clean spirit as the DMA-budget gate. (Two DIFFERENT peripherals β€” + // RMT + Parlio + i80 on a P4 β€” coexist fine; only same-block collides.) + if (siblingClaimsBlock()) { + deinit(); + setConfigErr("peripheral already in use by another driver β€” pick a different one"); + return; + } // A rebuild is the user fixing the setting that broke the bus: give the new bus a clean slate // so a driver that gave up starts transmitting again (the live-reconfiguration rule β€” no reboot). deadFrames_ = 0; @@ -1480,7 +1692,7 @@ class ParallelLedDriver : public DriverBase { // path, which then idles with a status if the frame won't fit either (the always-available // degrade). The ring owns its own buffers + refill task, so a plain deinit()+rebuild is correct; // ring-reuse is a later optimization (a config change already forces a rebuild). - if (derived()->wantsRing()) { + if (peripheral_->wantsRing()) { deinit(); const uint8_t outCh = correction_.outChannels; // Rows only β€” a ring buffer carries no latch pad (the reset comes from stopping the @@ -1493,20 +1705,20 @@ class ParallelLedDriver : public DriverBase { // reads the live source, so the buffer isn't needed β€” free it (ringSnapshot triggers a rebuild, // so this branch re-runs on the toggle) and skip the alloc, keeping the memory readout honest. if (!ringSnapshot) freeSnapshot(); - if (derived()->busInitRing(rowBytes, static_cast(maxLaneLights_)) + if (peripheral_->busInitRing(rowBytes, static_cast(maxLaneLights_)) && (!ringSnapshot || ensureSnapshotCap())) { inited_ = true; - dmaBuf_ = derived()->busBuffer(0); // ring[0] β€” a real pointer, the "inited" sentinel + dmaBuf_ = peripheral_->busBuffer(0); // ring[0] β€” a real pointer, the "inited" sentinel for (uint8_t i = 0; i < kMaxLanes; i++) busPins_[i] = laneList_[i]; busLaneCount_ = laneCount_; - derived()->recordBusPins(); - if (status() == Derived::kInitFailMsg) clearStatus(); + peripheral_->recordBusPins(); + if (status() == peripheral_->initFailMsg()) clearStatus(); // Re-issue the driving status WITH the ring's regime word β€” the regime (primed vs // lapping) is a platform fact that exists only now, after the ring build; parseConfig // set the plain form before it could know. Same numbers, same severity rules. // Only when the plain form is what's showing β€” a clamp warning (or any more urgent // status) must keep winning, same rule as parseConfig's `!warn` guard. - if (const char* mode = derived()->busRingMode(); + if (const char* mode = peripheral_->busRingMode(); mode && status() && std::strncmp(status(), "driving ", 8) == 0) { nrOfLightsType driven = 0; for (uint8_t i = 0; i < laneCount_; i++) driven += laneCounts_[i]; @@ -1524,7 +1736,7 @@ class ParallelLedDriver : public DriverBase { // deinit() would walk straight past, and the whole-frame busInit below would overwrite the // handle of. That leaks the scarcest memory on the chip on exactly the OOM path most likely // to hit it, and repeats on every prepare rebuild. busDeinit is idempotent and null-safe. - derived()->busDeinit(); + peripheral_->busDeinit(); deinit(); } @@ -1534,13 +1746,13 @@ class ParallelLedDriver : public DriverBase { // buffer the current path never touches. (deinit/drain above stopped any refill that read it.) freeSnapshot(); - const bool haveSecond = derived()->busBuffer(1) != nullptr; + const bool haveSecond = peripheral_->busBuffer(1) != nullptr; const bool wantSecond = doubleBuffer; - if (inited_ && !derived()->busIsRing() && derived()->busCapacity() == frameBytes_ + if (inited_ && !peripheral_->busIsRing() && peripheral_->busCapacity() == frameBytes_ && busPinsCurrent() && busLaneCount_ == laneCount_ && haveSecond == wantSecond) { // Clear stale latch-pad bytes in BOTH buffers (buffer 1 is null in single-buffer mode). - std::memset(dmaBuf_, 0, derived()->busCapacity()); - if (uint8_t* b1 = derived()->busBuffer(1)) std::memset(b1, 0, derived()->busCapacity()); + std::memset(dmaBuf_, 0, peripheral_->busCapacity()); + if (uint8_t* b1 = peripheral_->busBuffer(1)) std::memset(b1, 0, peripheral_->busCapacity()); prefillShiftConstantsIfNeeded(); // the zeroing above wiped them return; } @@ -1551,7 +1763,7 @@ class ParallelLedDriver : public DriverBase { // that chip the failing esp_lcd path can BUSY-WAIT to a watchdog reset rather than return an // error. So refuse cleanly with a clear, actionable status instead of choking the init. Budget 0 // (PSRAM-capable chips, or the streaming ring) means "no bound" β†’ always passes. Cold path. - if (const size_t budget = derived()->dmaBudgetBytes(); + if (const size_t budget = peripheral_->dmaBudgetBytes(); !frameFitsDmaBudget(frameBytes_, budget)) { // deinit() above already cleared the bus and inited_ β€” just report and bail. if (char* b = failBufEnsure()) { @@ -1560,35 +1772,35 @@ class ParallelLedDriver : public DriverBase { static_cast(budget / 1024)); setStatus(b, Severity::Error); } else { - setStatus(Derived::kInitFailMsg, Severity::Error); + setStatus(peripheral_->initFailMsg(), Severity::Error); } return; } // Pass doubleBuffer so busInit allocates the second buffer only when the double-buffer is // wanted β€” OFF (default) costs exactly one DMA buffer, no async overhead, no second alloc. - inited_ = derived()->busInit(frameBytes_, doubleBuffer); - dmaBuf_ = inited_ ? derived()->busBuffer(0) : nullptr; + inited_ = peripheral_->busInit(frameBytes_, doubleBuffer); + dmaBuf_ = inited_ ? peripheral_->busBuffer(0) : nullptr; if (inited_) { for (uint8_t i = 0; i < kMaxLanes; i++) busPins_[i] = laneList_[i]; busLaneCount_ = laneCount_; - derived()->recordBusPins(); // i80 also stores WR/DC; Parlio no-op + peripheral_->recordBusPins(); // i80 also stores WR/DC; Parlio no-op prefillShiftConstantsIfNeeded(); } if (!inited_) { clearFailBuf(); - setStatus(Derived::kInitFailMsg, Severity::Error); - } else if (status() == Derived::kInitFailMsg) { + setStatus(peripheral_->initFailMsg(), Severity::Error); + } else if (status() == peripheral_->initFailMsg()) { clearStatus(); } } void deinit() { - if constexpr (Derived::lanesAvailable() == 0) return; + if (!peripheral_ || peripheral_->lanesAvailable() == 0) return; // Free is a use-after-free if a transfer is still reading the buffer β€” drain first. // (reinit already drains before calling here; release()/onCorrectionChanged reach // deinit directly, so the guard belongs here too. Idempotent no-op when idle.) drainInFlight(); - if (inited_) derived()->busDeinit(); + if (inited_) peripheral_->busDeinit(); inited_ = false; dmaBuf_ = nullptr; active_ = 0; // next init starts on buffer 0 @@ -1608,7 +1820,7 @@ class ParallelLedDriver : public DriverBase { bool busPinsCurrent() const { for (uint8_t i = 0; i < laneCount_; i++) if (busPins_[i] != laneList_[i]) return false; - return derived()->extraBusPinsCurrent(); // i80 also checks WR/DC + return peripheral_ && peripheral_->extraBusPinsCurrent(); // i80 also checks WR/DC } // --- loopback self-test (control-driven; same status shapes as RMT). Builds @@ -1646,15 +1858,15 @@ class ParallelLedDriver : public DriverBase { patternHoldStrand_ = static_cast(strand); platform::delayMs(40); // a handful of 100 fps frames so the held pattern is on the wire before capture const uint8_t pat[3] = {kPatternRGB_[0], kPatternRGB_[1], kPatternRGB_[2]}; - const auto r = derived()->busLoopbackRide(pat, outCh < 3 ? outCh : uint8_t{3}, dataBytes, - static_cast(outCh * 8)); + const auto r = busLoopbackRide(pat, outCh < 3 ? outCh : uint8_t{3}, dataBytes, + static_cast(outCh * 8)); patternHoldStrand_ = -1; // release the hold β€” the strand returns to the live effect next frame // Report with the shared verdict formatter (same status strings as the private-bus path). reportLoopbackResult(r, outCh); } void runLoopbackSelfTest() { - if constexpr (Derived::lanesAvailable() == 0) { + if (!peripheral_ || peripheral_->lanesAvailable() == 0) { clearFailBuf(); setStatus("loopback: not supported on this platform", Severity::Warning); return; @@ -1693,7 +1905,7 @@ class ParallelLedDriver : public DriverBase { // the FULL-WIDTH private bus (it can't do a 1-lane bus), so a 16-lane driver's frame must // be 16-bit slots to match β€” and this then genuinely exercises the 16-bit transpose+DMA on // real silicon. Parlio builds a 1-lane private unit, so its loopback stays 8-bit regardless. - const uint8_t sb = Derived::kLoopbackFullWidth ? slotBytes() : 1; + const uint8_t sb = peripheral_->loopbackFullWidth() ? slotBytes() : 1; // The expander multiplies the SLOT COUNT (a '595 is serial-in: each WS2812 slot is shifted // out over 8 bus words), exactly as frameBytesFor does for the operational frame. Omitting it // here would build a frame 8Γ— too small and transmit a truncated waveform. @@ -1768,8 +1980,8 @@ class ParallelLedDriver : public DriverBase { // anything). const uint16_t realLane0 = laneList_[0]; if (loopbackTxPin >= 0 && !pinExpanderMode()) laneList_[0] = static_cast(loopbackTxPin); - const auto r = derived()->busLoopback(frame, testFrameBytes, dataBytes, - static_cast(outCh * 8)); + const auto r = peripheral_->busLoopback(frame, testFrameBytes, dataBytes, + static_cast(outCh * 8)); laneList_[0] = realLane0; platform::free(frame); // Loopback result first, then reinit: if rebuilding the real bus fails diff --git a/src/light/drivers/ParlioLedDriver.h b/src/light/drivers/ParlioLedDriver.h index 0d2a2d4b..0f2c4d1d 100644 --- a/src/light/drivers/ParlioLedDriver.h +++ b/src/light/drivers/ParlioLedDriver.h @@ -1,6 +1,6 @@ #pragma once -#include "light/drivers/ParallelLedDriver.h" // shared CRTP body +#include "light/drivers/ParallelLedDriver.h" // shared driver body + LedPeripheral #include "platform/platform.h" @@ -8,88 +8,91 @@ namespace mm { /// Output driver: parallel WS2812B over the ESP32-P4 Parlio (Parallel IO) TX peripheral β€” the P4's /// scale path, sibling of MultiPinLedDriver. The shared body (slicing, encode, single-shot DMA, loopback) -/// lives in ParallelLedDriver; Parlio is the SIMPLER peripheral, so this class adds LESS than the -/// i80 driver: +/// lives in ParallelLedDriver; Parlio is the SIMPLER peripheral, so this backend adds LESS than the +/// i80 backend: /// - NO clockPin/dcPin: Parlio generates the pixel clock itself (kClockHz), so there are no /// sacrificial WR/DC lines (addBusControls is empty). -/// - kPowerOfTwoBus = false: Parlio's bus width IS the pin count (any 1..16), so nothing rounds. The +/// - powerOfTwoBus() = false: Parlio's bus width IS the pin count (any 1..16), so nothing rounds. The /// i80 bus is 8 or 16 bits wide whatever the pin count, and parks the lanes it doesn't need on WR. /// Either way the user names only the pins that drive a strand. /// /// Prior art: the ESP32-P4 Parlio peripheral, the hpwit/FastLED parallel-WS2812 lineage β€” /// architecture studied, never copied. -class ParlioLedDriver : public ParallelLedDriver { +class ParlioPeripheral : public LedPeripheral { public: // All controls default to UNSET β€” pins="", ledsPerPin="" (= all lights on the // first lane, even-split with one lane), loopbackRxPin=-1 β€” so no constructor is - // needed (the base default-initialises them). Pins/loopback are unset because the + // needed (the orchestrator default-initialises them). Pins/loopback are unset because the // strand is user-soldered: a hard-coded pin would guess the user's wiring and // could drive a pin committed elsewhere ("default only when it cannot do harm", // see lessons.md). The P4-NANO bench uses pins "20,21,22,23,24,25,26,27", // loopbackRxPin 33 (clear of the NANO's strapping 34-38, Ethernet RMII // 28-31/49-52, C6 SDIO 14-19/54, I2C 7-8 β€” clear GPIOs are 20-27, 32-33, 39-48). - // --- CRTP hooks the base calls (all non-virtual; no vtable) --- + // --- LedPeripheral descriptors --- - /// The number of Parlio lanes this chip provides (0 = not this chip); the base's + /// The number of Parlio lanes this chip provides (0 = not this chip); the orchestrator's /// inert-on-wrong-chip guards key off it. - static constexpr uint8_t lanesAvailable() { return platform::parlioLanes; } - static constexpr bool kPowerOfTwoBus = false; // 1..16 lanes all valid + uint8_t lanesAvailable() const override { return platform::parlioLanes; } + bool powerOfTwoBus() const override { return false; } // 1..16 lanes all valid // Parlio builds a 1-lane private unit for the loopback, so the loopback frame stays 8-bit // regardless of the operational bus width (unlike i80, which needs a full-width bus). - static constexpr bool kLoopbackFullWidth = false; - static constexpr const char* kInitFailMsg = "Parlio init failed β€” check pins / memory"; + bool loopbackFullWidth() const override { return false; } + /// Parlio is its own TX peripheral block, distinct from LcdCam/I2S β€” it coexists with an i80 or + /// MoonI80 driver on the same chip (the P4 has both). + LedHwBlock hwBlock() const override { return LedHwBlock::Parlio; } + const char* initFailMsg() const override { return "Parlio init failed β€” check pins / memory"; } - // The WS2812 slot rate (375 ns @ 2.67 MHz) β€” identical to the LCD driver's; + // The WS2812 slot rate (375 ns @ 2.67 MHz) β€” identical to the LCD backend's; // the P4 Parlio's 160 MHz PLL clock divides to it exactly (/60). static constexpr uint32_t kClockHz = 2'666'666; /// No bus controls: Parlio has no sacrificial clock/DC pins (the bus rebuilds on /// a data-pin change alone). - void addBusControls() {} + void addBusControls(ControlList&) override {} /// No extra bus controls, so none can trigger a rebuild. - bool busControlTriggersBuild(const char*) const { return false; } + bool busControlTriggersBuild(const char*) const override { return false; } /// No extra pins to record (Parlio has no WR/DC). - void recordBusPins() {} + void recordBusPins() override {} /// No extra pins to track, so they are always current. - bool extraBusPinsCurrent() const { return true; } + bool extraBusPinsCurrent() const override { return true; } + + /// No 74HCT595 expander on Parlio: its single-shot transfer caps at 65,535 bytes + /// (PARLIO_LL_TX_MAX_BITS_PER_FRAME), and the Γ—8 fan-out frame is ~145 KB β€” 2.2Γ— over. The + /// orchestrator refuses shift mode here with a status rather than emitting a frame the peripheral + /// drops. (The P4's route to the expander is its LCD_CAM/i80 bus, which I80Peripheral already + /// drives; lifting this needs the chunked-transfer work, not a flag flip.) + bool supportsPinExpander() const override { return false; } /// Create the Parlio bus + its DMA buffer(s) sized for `frameBytes` on the current lanes, driving /// the pixel clock at kClockHz; `wantSecondBuffer` requests the async double-buffer's second frame /// buffer (allocated only if it fits). Returns whether init succeeded. - /// No 74HCT595 expander on Parlio: its single-shot transfer caps at 65,535 bytes - /// (PARLIO_LL_TX_MAX_BITS_PER_FRAME), and the Γ—8 fan-out frame is ~145 KB β€” 2.2Γ— over. The base - /// refuses shift mode here with a status rather than emitting a frame the peripheral drops. - /// (The P4's route to the expander is its LCD_CAM/i80 bus, which MultiPinLedDriver already drives; - /// lifting this needs the chunked-transfer work, not a flag flip.) - static constexpr bool kSupportsPinExpander = false; - - bool busInit(size_t frameBytes, bool wantSecondBuffer) { - return platform::parlioWs2812Init(parlio_, laneList_, laneCount_, + bool busInit(size_t frameBytes, bool wantSecondBuffer) override { + return platform::parlioWs2812Init(parlio_, owner_->laneList(), owner_->laneCount(), kClockHz, frameBytes, wantSecondBuffer); } - /// DMA buffer `i` (0/1) the base encodes into; buffer 1 is null when the second + /// DMA buffer `i` (0/1) the orchestrator encodes into; buffer 1 is null when the second /// buffer didn't fit (single-buffer mode). Both are the same size (busCapacity). - uint8_t* busBuffer(uint8_t i) { return platform::parlioWs2812Buffer(parlio_, i); } + uint8_t* busBuffer(uint8_t i) override { return platform::parlioWs2812Buffer(parlio_, i); } /// The per-buffer byte capacity (fixed at bus creation; both buffers equal). - size_t busCapacity() const { return platform::parlioWs2812BufferCapacity(parlio_); } + size_t busCapacity() const override { return platform::parlioWs2812BufferCapacity(parlio_); } /// Kick off the autonomous transfer of the first `bytes` of DMA buffer `i`; /// returns whether it started. - bool busTransmit(uint8_t i, size_t bytes) { return platform::parlioWs2812Transmit(parlio_, i, bytes); } + bool busTransmit(uint8_t i, size_t bytes) override { return platform::parlioWs2812Transmit(parlio_, i, bytes); } /// Block up to `ms` for buffer `i`'s in-flight transfer to complete. - bool busWait(uint8_t i, uint32_t ms) { return platform::parlioWs2812Wait(parlio_, i, ms); } + bool busWait(uint8_t i, uint32_t ms) override { return platform::parlioWs2812Wait(parlio_, i, ms); } /// The most recent DMA transfer's wire time (Β΅s) β€” the WS2812 output floor. - uint32_t busLastTransmitUs() const { return platform::parlioWs2812LastTransmitUs(parlio_); } + uint32_t busLastTransmitUs() const override { return platform::parlioWs2812LastTransmitUs(parlio_); } /// Tear down the Parlio bus and its DMA buffer. - void busDeinit() { platform::parlioWs2812Deinit(parlio_); } + void busDeinit() override { platform::parlioWs2812Deinit(parlio_); } /// Run the loopback self-test. Parlio runs on a single lane, so the loopback /// builds its own private 1-lane unit on lane 0 (no i80 full-bus workaround /// needed; no WR/DC to pass). platform::RmtLoopbackResult busLoopback(const uint8_t* frame, size_t frameBytes, - size_t dataBytes, uint8_t rowBits) { - return platform::parlioWs2812Loopback(laneList_, laneCount_, - static_cast(loopbackRxPin), + size_t dataBytes, uint8_t rowBits) override { + return platform::parlioWs2812Loopback(owner_->laneList(), owner_->laneCount(), + static_cast(owner_->loopbackRxPin), frame, frameBytes, dataBytes, rowBits); } @@ -97,4 +100,10 @@ class ParlioLedDriver : public ParallelLedDriver { platform::ParlioWs2812Handle parlio_; }; +// Register the Parlio backend into the peripheral registry once, at static-init. Gated by this header's +// CONFIG_SOC include in main.cpp (Parlio-capable silicon = the P4). No separate driver class β€” the one +// ParallelLedDriver drives it, chosen via the `peripheral` control. +inline const bool kParlioPeripheralRegistered = + ParallelLedDriver::registerPeripheral("Parlio", []() -> LedPeripheral* { return new ParlioPeripheral(); }); + } // namespace mm diff --git a/src/main.cpp b/src/main.cpp index 2ff86dee..c7aa6fea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -90,14 +90,17 @@ #if defined(CONFIG_SOC_RMT_SUPPORTED) #include "light/drivers/RmtLedDriver.h" #endif +// The parallel-WS2812 driver + its peripheral backends. Each backend header self-registers its factory +// into ParallelLedDriver's peripheral registry (gated by the chip's CONFIG_SOC_*), so including the ones +// this silicon supports is what populates the `peripheral` control's options. #if defined(CONFIG_SOC_LCD_I80_SUPPORTED) -#include "light/drivers/MultiPinLedDriver.h" +#include "light/drivers/MultiPinLedDriver.h" // esp_lcd i80 backend (I80Peripheral) #endif #if defined(CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED) -#include "light/drivers/MoonLedDriver.h" +#include "light/drivers/MoonLedDriver.h" // MoonI80 own-GDMA backend (MoonI80Peripheral) #endif #if defined(CONFIG_SOC_PARLIO_SUPPORTED) -#include "light/drivers/ParlioLedDriver.h" +#include "light/drivers/ParlioLedDriver.h" // Parlio backend (ParlioPeripheral) #endif #include "core/HttpServerModule.h" #include "core/SystemModule.h" @@ -214,19 +217,13 @@ static void registerModuleTypes() { #if defined(CONFIG_SOC_RMT_SUPPORTED) mm::ModuleFactory::registerType("RmtLedDriver", "light/drivers.md#rmtled"); #endif - // MultiPinLedDriver β€” 8/16 parallel strands over IDF's esp_lcd i80 bus (LCD_CAM on S3/P4, I2S-i80 - // on classic ESP32); IDF picks the backend by chip, so ONE driver serves all i80-capable silicon. -#if defined(CONFIG_SOC_LCD_I80_SUPPORTED) - mm::ModuleFactory::registerType("MultiPinLedDriver", "light/drivers.md#multipinled"); -#endif -#if defined(CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED) - // The same LCD_CAM output on our own DMA code instead of esp_lcd (ADR-0014). Registered ALONGSIDE - // MultiPinLedDriver, not instead of it: that one is the reference implementation and the default, - // this is the challenger, and having both registered makes the A/B a swap in the UI. - mm::ModuleFactory::registerType("MoonLedDriver", "light/drivers.md#moonled"); -#endif -#if defined(CONFIG_SOC_PARLIO_SUPPORTED) - mm::ModuleFactory::registerType("ParlioLedDriver", "light/drivers.md#parlioled"); + // ParallelLedDriver β€” ONE driver for the parallel-WS2812 output, whatever the DMA peripheral. The + // three backends (esp_lcd i80, MoonI80 own-GDMA, Parlio) each self-register into the driver's + // peripheral registry when their header is included above (gated by the same CONFIG_SOC_* below), so + // the `peripheral` control offers exactly the ones this chip links. Registered once, on any chip that + // links at least one parallel backend. +#if defined(CONFIG_SOC_LCD_I80_SUPPORTED) || defined(CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED) || defined(CONFIG_SOC_PARLIO_SUPPORTED) + mm::ModuleFactory::registerType("ParallelLedDriver", "light/drivers.md#parallelled"); #endif mm::ModuleFactory::registerType("HttpServerModule", "core/system.md"); mm::ModuleFactory::registerType("SystemModule", "core/system.md#system"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 94241cb6..a001d532 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -113,6 +113,7 @@ add_executable(mm_tests unit/light/unit_ParallelLedDriver_doublebuffer.cpp unit/light/unit_ParallelLedDriver_pinexpander.cpp unit/light/unit_ParallelLedDriver_ring.cpp + unit/light/unit_ParallelLedDriver_swap.cpp unit/light/unit_RmtLedEncoder.cpp unit/light/unit_RmtLedDriver_lifecycle.cpp unit/light/unit_RmtLedDriver_pins.cpp diff --git a/test/scenarios/light/scenario_perf_full.json b/test/scenarios/light/scenario_perf_full.json index 7a18a8a3..688bd6c8 100644 --- a/test/scenarios/light/scenario_perf_full.json +++ b/test/scenarios/light/scenario_perf_full.json @@ -9,8 +9,7 @@ "PreviewDriver", "NetworkSendDriver", "RmtLedDriver", - "MultiPinLedDriver", - "ParlioLedDriver", + "ParallelLedDriver", "MultiplyModifier", "SpiralEffect", "NoiseEffect" @@ -836,16 +835,19 @@ }, { "name": "add-i80-driver", - "description": "+MultiPinLedDriver capped to 64 LEDs on lane 0 (i80 needs all 8 data pins; unused lanes get 0 LEDs). S3 ONLY β€” the pins below are the S3's clean set. MultiPinLedDriver also registers on the classic ESP32 (I2S backend) and the P4 (LCD_CAM), but NO 8-pin set is safe on all three (only GPIO 21 is common: the classic's 6-11 are the SPI flash bus, the P4 exposes a different range), so one shared step cannot measure them. On a non-S3 target the driver fails to init and the measure below is meaningless β€” the observed blocks are therefore S3/desktop only. Diff = the i80 per-frame cost.", + "description": "+ParallelLedDriver (peripheral=i80) capped to 64 LEDs on lane 0 (i80 needs all 8 data pins; unused lanes get 0 LEDs). S3 ONLY β€” the pins below are the S3's clean set. The i80 peripheral also runs on the classic ESP32 (I2S backend) and the P4 (LCD_CAM), but NO 8-pin set is safe on all three (only GPIO 21 is common: the classic's 6-11 are the SPI flash bus, the P4 exposes a different range), so one shared step cannot measure them. On a non-S3 target the driver fails to init and the measure below is meaningless β€” the observed blocks are therefore S3/desktop only. Diff = the i80 per-frame cost.", "op": "add_module", "id": "MultiPin", - "type": "MultiPinLedDriver", + "type": "ParallelLedDriver", "parent_id": "Drivers", "props": { "pins": "1,2,3,4,5,6,7,8", "ledsPerPin": "64,0,0,0,0,0,0,0" }, - "optional": true + "optional": true, + "controls": { + "peripheral": "i80" + } }, { "name": "measure-i80", @@ -936,16 +938,19 @@ }, { "name": "add-parlio-driver", - "description": "+ParlioLedDriver capped to 64 LEDs on lane 0. Optional β€” P4 only. Diff = the Parlio per-frame cost.", + "description": "+ParallelLedDriver (peripheral=Parlio) capped to 64 LEDs on lane 0. Optional β€” P4 only. Diff = the Parlio per-frame cost.", "op": "add_module", "id": "Parlio", - "type": "ParlioLedDriver", + "type": "ParallelLedDriver", "parent_id": "Drivers", "props": { "pins": "20", "ledsPerPin": "64" }, - "optional": true + "optional": true, + "controls": { + "peripheral": "Parlio" + } }, { "name": "measure-parlio", diff --git a/test/unit/core/unit_Control_apply_absent_key.cpp b/test/unit/core/unit_Control_apply_absent_key.cpp index 9ee9bf05..ce30e99f 100644 --- a/test/unit/core/unit_Control_apply_absent_key.cpp +++ b/test/unit/core/unit_Control_apply_absent_key.cpp @@ -19,6 +19,7 @@ #include "doctest.h" #include "core/Control.h" #include "core/JsonUtil.h" +#include "core/JsonSink.h" // PaletteOptionsFn's JsonSink parameter (the palette-crash regression) #include #include @@ -169,3 +170,47 @@ TEST_CASE("a Text control with no validator accepts anything that fits") { "label", mm::ApplyPolicy::Clamp) == mm::ApplyResult::Ok); CHECK(std::strcmp(label, "hi") == 0); } + +// A Palette control's aux holds a PaletteOptionsFn (a FUNCTION POINTER), not an options array. The +// Select label-match path must therefore NOT run for Palette: reinterpreting a function pointer as a +// char* const* and walking it dereferences code bytes β€” undefined behavior, a near-certain crash on +// ESP32. The regression: a string value on a palette must fall to numeric-index apply (parseInt β†’ 0), +// exactly the harmless behavior before the label-match feature existed. (Robust to any input.) +static void paletteOptions(mm::JsonSink& sink) { + sink.append("[\"Rainbow\",\"Ocean\",\"Forest\"]"); // a real fn body; never read via the aux cast +} +TEST_CASE("applyControlValue: a string palette value does not crash and applies numerically") { + mm::ControlList controls; + uint8_t palette = 1; + controls.addPalette("palette", palette, paletteOptions, 3); + + // A STRING value (as a hand-edited config or a mistaken client could send). Before the fix this + // walked the function pointer as an options array. After: string β†’ parseInt β†’ 0, clamped in range. + CHECK(mm::applyControlValue(controls[0], "{\"palette\":\"Rainbow\"}", "palette", + mm::ApplyPolicy::Clamp) == mm::ApplyResult::Ok); + CHECK(palette == 0); // numeric fallback, no function-pointer deref + + // A numeric value still applies straight through. + CHECK(mm::applyControlValue(controls[0], "{\"palette\":2}", "palette", + mm::ApplyPolicy::Clamp) == mm::ApplyResult::Ok); + CHECK(palette == 2); +} + +// The complement: a Select's aux IS the options array, so a string LABEL value matches an option by +// name (the board-portable catalog path β€” a peripheral label is stable while its filtered index is +// not). This keeps the label-match feature working where it is safe. +TEST_CASE("applyControlValue: a Select accepts an option label as a string value") { + mm::ControlList controls; + uint8_t sel = 0; + static const char* const opts[] = {"i80", "MoonI80", "Parlio"}; + controls.addSelect("peripheral", sel, opts, 3); + + CHECK(mm::applyControlValue(controls[0], "{\"peripheral\":\"Parlio\"}", "peripheral", + mm::ApplyPolicy::Clamp) == mm::ApplyResult::Ok); + CHECK(sel == 2); // matched the "Parlio" label β†’ index 2 + + // A numeric index still works alongside the label path. + CHECK(mm::applyControlValue(controls[0], "{\"peripheral\":1}", "peripheral", + mm::ApplyPolicy::Clamp) == mm::ApplyResult::Ok); + CHECK(sel == 1); +} diff --git a/test/unit/light/unit_MoonLedDriver.cpp b/test/unit/light/unit_MoonLedDriver.cpp index c504fc0c..f509459c 100644 --- a/test/unit/light/unit_MoonLedDriver.cpp +++ b/test/unit/light/unit_MoonLedDriver.cpp @@ -6,18 +6,20 @@ #include "correction_presets.h" #include "light/drivers/MoonLedDriver.h" #include "light/layers/Buffer.h" +#include "unit/core/conditional_controls.h" // controlIndex/setControlValue β€” clockPin now lives on the backend #include // MoonLedDriver is the SAME LCD_CAM output as MultiPinLedDriver, on our own DMA code instead of -// esp_lcd (ADR-0014). It is a CRTP sibling of the same ParallelLedDriver base, so the base's whole -// body β€” lane slicing, frame sizing, the fused encode, the async double-buffer, the shift-register -// expander, the dead-frame guard β€” is ALREADY covered by the Mock-driver suites +// esp_lcd (ADR-0014). It is a thin ParallelLedDriver subclass whose constructor wires a +// MoonI80Peripheral backend (a runtime LedPeripheral strategy, not compile-time CRTP), so the +// orchestrator's whole body β€” lane slicing, frame sizing, the fused encode, the async double-buffer, +// the shift-register expander, the dead-frame guard β€” is ALREADY covered by the Mock-driver suites // (unit_ParallelLedDriver_doublebuffer / _shiftregister) and by unit_I80LedDriver. Re-testing it // here through a second concrete driver would assert the same base twice. // // So these cases pin only what is genuinely MoonI80's own: -// - it satisfies the CRTP contract (it instantiates and configures at all); +// - it satisfies the LedPeripheral contract (it instantiates and configures at all); // - the constants that DIFFER from its sibling β€” chiefly that it is LCD_CAM-only; // - its own bus-pin validation, and the fact that it needs FEWER pins than the sibling: no DC at // all, and WR only under the expander (owning the GPIO matrix is what buys that). @@ -27,8 +29,23 @@ namespace { -void wire(mm::MoonLedDriver& d, mm::Buffer& src, mm::Correction& corr, +// On the host `platform::lcdLanes` is 0, so the real MoonI80Peripheral reports supportsPinExpander() +// == false β€” which the orchestrator now honours by SILENTLY dropping pinExpander back to direct mode +// (a peripheral that can't host the '595 has its expander toggle hidden, so an unfixable error would be +// wrong β€” see parseConfig). That degradation is correct on hardware but hides the SHIFT-MODE validation +// (WR collision, latch-on-WR, clockPin required) these cases exist to pin. So the shift-mode cases use +// this tiny subclass that reports the expander as supported, exactly as the real backend does on an +// LCD_CAM chip β€” the validation then runs on the host. +struct ExpanderMoonI80 : mm::MoonI80Peripheral { + bool supportsPinExpander() const override { return true; } +}; + +// The peripheral is declared BEFORE the driver at every call site (see this helper's parameter +// order) so it outlives the driver β€” setPeripheralForTest borrows, it does not own (see +// unit_ParallelLedDriver_doublebuffer.cpp's wire()). +void wire(mm::ParallelLedDriver& d, mm::MoonI80Peripheral& peripheral, mm::Buffer& src, mm::Correction& corr, mm::nrOfLightsType lights) { + d.setPeripheralForTest(&peripheral); if (d.pins[0] == '\0') std::strcpy(d.pins, "1,2,4,5,6,7,8,9"); REQUIRE(src.allocate(lights, 3) == (lights > 0)); mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); @@ -45,18 +62,24 @@ void wire(mm::MoonLedDriver& d, mm::Buffer& src, mm::Correction& corr, // programs LCD_CAM directly, so it must NOT claim the classic chip: `lanesAvailable()` reads // `lcdLanes` alone, without the `+ i2sLanes` its sibling adds. Getting this wrong would offer the // driver on a chip whose peripheral it cannot drive. +// +// lanesAvailable()/kSupportsPinExpander/kPowerOfTwoBus/kLoopbackFullWidth moved from static constexpr +// on the driver to virtuals on the MoonI80Peripheral backend β€” a bare instance reaches them without a +// live driver's peripheral_ (protected on ParallelLedDriver). TEST_CASE("MoonLedDriver is LCD_CAM-only β€” it does not claim the classic ESP32's I2S i80") { - CHECK(mm::MoonLedDriver::lanesAvailable() == mm::platform::lcdLanes); + mm::MoonI80Peripheral peripheral; + CHECK(peripheral.lanesAvailable() == mm::platform::lcdLanes); // The expander needs LCD_CAM, which is exactly where this driver runs β€” so the two agree. - CHECK(mm::MoonLedDriver::kSupportsPinExpander == (mm::platform::lcdLanes > 0)); + CHECK(peripheral.supportsPinExpander() == (mm::platform::lcdLanes > 0)); } -// The i80 BUS is 8 or 16 bits wide whatever the pin count, so the base rounds it up (kPowerOfTwoBus) +// The i80 BUS is 8 or 16 bits wide whatever the pin count, so the base rounds it up (powerOfTwoBus()) // and parks the lanes the board does not use. And the loopback cannot build a 1-lane private bus, so // its test frame is encoded at the full operational width. TEST_CASE("MoonLedDriver keeps the i80 bus rules: power-of-two bus, full-width loopback") { - CHECK(mm::MoonLedDriver::kPowerOfTwoBus); - CHECK(mm::MoonLedDriver::kLoopbackFullWidth); + mm::MoonI80Peripheral peripheral; + CHECK(peripheral.powerOfTwoBus()); + CHECK(peripheral.loopbackFullWidth()); } // **The bus control pins are a '595 cost, not an i80 cost β€” and owning the DMA is what proves it.** @@ -71,12 +94,13 @@ TEST_CASE("MoonLedDriver keeps the i80 bus rules: power-of-two bus, full-width l // GPIO that a strand also uses, because the signal never leaves the peripheral. Rejecting that would // forbid a working config to protect a signal nobody reads. TEST_CASE("MoonLedDriver direct mode: clockPin is unrouted, so it cannot collide") { - mm::MoonLedDriver d; + mm::MoonI80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.pins, "1,2,4,5,6,7,8,10"); // pin 10 IS the default clockPin (WR) β€” fine here - wire(d, src, corr, 8 * 16); - CHECK(d.severity() != mm::MoonLedDriver::Severity::Error); + wire(d, peripheral, src, corr, 8 * 16); + CHECK(d.severity() != mm::ParallelLedDriver::Severity::Error); CHECK(d.laneCount() == 8); // it drives all eight strands } @@ -84,58 +108,74 @@ TEST_CASE("MoonLedDriver direct mode: clockPin is unrouted, so it cannot collide // sharing it is silent corruption: the matrix drives both signals onto the one pad and that strand // emits the shift clock instead of pixel data. TEST_CASE("MoonLedDriver shift mode: a data pin on clockPin (WR) is caught") { - mm::MoonLedDriver d; + ExpanderMoonI80 peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; d.pinExpander = true; d.latchPin = 12; std::strcpy(d.pins, "1,2,10"); // pin 10 IS clockPin, and here WR is a real pad - wire(d, src, corr, 8 * 16); - CHECK(d.severity() != mm::MoonLedDriver::Severity::Status); // it complains + wire(d, peripheral, src, corr, 8 * 16); + CHECK(d.severity() != mm::ParallelLedDriver::Severity::Status); // it complains } // The '595 latch rides a DATA lane (the peripheral gives only one clock output, and WR is already the // shift clock), so it must not land on WR β€” the latch would ride the shift clock itself and nothing // would ever latch, which looks like a dead strip rather than a config error. +// +// clockPin now lives on the MoonI80Peripheral backend (not a MoonLedDriver member), so it is read/set +// through the control API defineDriverControls() binds β€” the same mechanism the UI and persistence use. TEST_CASE("MoonLedDriver rejects a latchPin on WR") { - mm::MoonLedDriver d; + ExpanderMoonI80 peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); + d.defineControls(); d.pinExpander = true; - d.latchPin = d.clockPin; - wire(d, src, corr, 8 * 16); - CHECK(d.severity() == mm::MoonLedDriver::Severity::Error); + const int idx = mm::test::controlIndex(d, "clockPin"); + REQUIRE(idx >= 0); + d.latchPin = *static_cast(d.controls()[static_cast(idx)].ptr); + wire(d, peripheral, src, corr, 8 * 16); + CHECK(d.severity() == mm::ParallelLedDriver::Severity::Error); } // The '595's shift clock IS WR, so shift mode needs clockPin on a real GPIO. Unset (-1) would route // the peripheral's WR signal to GPIO 65535 β€” catch it as a config error, not a bad pad write. Direct // mode does not care (WR is unrouted there), so the same unset pin is fine without the expander. TEST_CASE("MoonLedDriver shift mode requires a clockPin; direct mode does not") { - mm::MoonLedDriver d; + ExpanderMoonI80 peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); + d.defineControls(); d.pinExpander = true; d.latchPin = 12; - d.clockPin = -1; // unset - wire(d, src, corr, 8 * 16); - CHECK(d.severity() == mm::MoonLedDriver::Severity::Error); + mm::test::setControlValue(d, "clockPin", -1); // unset + wire(d, peripheral, src, corr, 8 * 16); + CHECK(d.severity() == mm::ParallelLedDriver::Severity::Error); - mm::MoonLedDriver d2; // same unset clockPin, DIRECT mode β†’ fine + ExpanderMoonI80 peripheral2; + mm::ParallelLedDriver d2; // same unset clockPin, DIRECT mode β†’ fine mm::Buffer src2; mm::Correction corr2; - d2.clockPin = -1; + d2.setPeripheralForTest(&peripheral2); + d2.defineControls(); + mm::test::setControlValue(d2, "clockPin", -1); std::strcpy(d2.pins, "1,2,4,5,6,7,8,9"); - wire(d2, src2, corr2, 8 * 16); - CHECK(d2.severity() != mm::MoonLedDriver::Severity::Error); + wire(d2, peripheral2, src2, corr2, 8 * 16); + CHECK(d2.severity() != mm::ParallelLedDriver::Severity::Error); } // Sanity: with a valid config the driver is a working CRTP sibling β€” it slices lanes and reports the // lights it drives, exactly like its sibling. (The lane/frame ARITHMETIC itself is the base's, and is // covered once, in unit_I80LedDriver and the Mock suites.) TEST_CASE("MoonLedDriver drives a valid config like its sibling") { - mm::MoonLedDriver d; + mm::MoonI80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 8 * 32); // 8 lanes Γ— 32 lights + wire(d, peripheral, src, corr, 8 * 32); // 8 lanes Γ— 32 lights CHECK(d.laneCount() == 8); } diff --git a/test/unit/light/unit_MultiPinLedDriver.cpp b/test/unit/light/unit_MultiPinLedDriver.cpp index 3b584aaa..015c9e5c 100644 --- a/test/unit/light/unit_MultiPinLedDriver.cpp +++ b/test/unit/light/unit_MultiPinLedDriver.cpp @@ -15,11 +15,20 @@ // growth), and the parse-error/recovery shape. The hardware half (bus init, // DMA transmit) is inert on the host β€” desktop stubs return false/nullptr β€” // and is proven on the S3. +// +// mm::ParallelLedDriver is the ONE registered driver; this file drives it with an +// injected mm::I80Peripheral backend (the esp_lcd i80 bus), the backend this header +// defines and registers under the "i80" peripheral label. namespace { -void wire(mm::MultiPinLedDriver& d, mm::Buffer& src, mm::Correction& corr, +// The peripheral is declared BEFORE the driver in every case below (via this helper's +// parameter order + the caller's declaration order) so it outlives the driver β€” reverse +// destruction order tears the driver down first, matching setPeripheralForTest's borrow +// contract (see unit_ParallelLedDriver_doublebuffer.cpp's wire()). +void wire(mm::ParallelLedDriver& d, mm::I80Peripheral& peripheral, mm::Buffer& src, mm::Correction& corr, mm::nrOfLightsType lights) { + d.setPeripheralForTest(&peripheral); // Pins default to UNSET now (the "default only when it cannot do harm" rule β€” // a user solders the strand to its own GPIOs), so a fresh driver idles until // configured. These slicing/frame tests exercise the lane logic, not the @@ -52,11 +61,12 @@ size_t expectFrame(mm::nrOfLightsType maxLights, uint8_t outCh, uint8_t slotByte // LONGEST lane. The bus always has all 8 lanes β€” unused strands take the // 0-light remainder and idle LOW. TEST_CASE("MultiPinLedDriver slices lanes and sizes the frame by the longest") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.ledsPerPin, "50,20,20"); // lanes 3..7 share the remainder: 0 - wire(d, src, corr, 90); + wire(d, peripheral, src, corr, 90); REQUIRE(d.laneCount() == 8); CHECK(d.laneLightCount(0) == 50); @@ -73,10 +83,11 @@ TEST_CASE("MultiPinLedDriver slices lanes and sizes the frame by the longest") { // Empty ledsPerPin splits evenly β€” same PinList semantics the RMT driver uses. TEST_CASE("MultiPinLedDriver even split over the default 8 lanes") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 256); // default pins: 8 lanes + wire(d, peripheral, src, corr, 256); // default pins: 8 lanes REQUIRE(d.laneCount() == 8); CHECK(d.laneLightCount(0) == 32); @@ -87,11 +98,12 @@ TEST_CASE("MultiPinLedDriver even split over the default 8 lanes") { // An RGBβ†’RGBW preset toggle grows the frame (32 vs 24 slot bytes per light). TEST_CASE("MultiPinLedDriver frame grows on RGBW preset") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.ledsPerPin, "50,50"); // lanes 2..7 idle - wire(d, src, corr, 100); + wire(d, peripheral, src, corr, 100); CHECK(d.frameBytes() == expectFrame(50, 3)); // The driver owns its Correction, so mutate that copy (not the external one). @@ -108,12 +120,13 @@ TEST_CASE("MultiPinLedDriver frame grows on RGBW preset") { // the classic chip, so this refactor changes nothing on every non-classic target. The hardware behavior // (a too-big frame on the real classic i80 idles with the clear "over DMA" status) is proven on the Olimex. TEST_CASE("MultiPinLedDriver: the DMA-fit gate is inert off the classic i80 (budget 0)") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.pins, "1"); // one lane β†’ the whole grid lands on it, a big frame std::strcpy(d.ledsPerPin, ""); // even-split all onto the one pin - wire(d, src, corr, 4096); // a large grid, far past any real classic i80 DMA budget + wire(d, peripheral, src, corr, 4096); // a large grid, far past any real classic i80 DMA budget // The frame was computed (a real size), and the status is NOT the size-rejection message β€” desktop // dmaBudgetBytes() is 0, so frameFitsDmaBudget() always passes. (The desktop bus stub is inert, so @@ -127,10 +140,10 @@ TEST_CASE("MultiPinLedDriver: the DMA-fit gate is inert off the classic i80 (bud // oversized frame and accepts one that fits; a ZERO budget ("no bound", the LCD_CAM/PSRAM/desktop case) // never rejects, whatever the frame size. TEST_CASE("MultiPinLedDriver::frameFitsDmaBudget rejects only over a finite budget") { - // frameFitsDmaBudget is a protected static on the CRTP base; a tiny subclass exposes it for the - // test without widening the production class surface. - struct Expose : mm::MultiPinLedDriver { - using mm::MultiPinLedDriver::frameFitsDmaBudget; + // frameFitsDmaBudget is a protected static on ParallelLedDriver; a tiny subclass exposes it for + // the test without widening the production class surface. + struct Expose : mm::ParallelLedDriver { + using mm::ParallelLedDriver::frameFitsDmaBudget; }; // finite budget: reject strictly-larger, accept equal-or-smaller CHECK_FALSE(Expose::frameFitsDmaBudget(1025, 1024)); @@ -142,11 +155,12 @@ TEST_CASE("MultiPinLedDriver::frameFitsDmaBudget rejects only over a finite budg // A bad pin list idles the driver with the parse literal in the status; fixing it recovers. TEST_CASE("MultiPinLedDriver bad pins β†’ status error β†’ recovery") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.pins, "1,nope"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 0); CHECK(d.frameBytes() == 0); @@ -165,9 +179,11 @@ TEST_CASE("MultiPinLedDriver bad pins β†’ status error β†’ recovery") { // the 8 data GPIOs on its own. (wire() back-fills empty pins for the slicing // cases, so this one wires the buffer directly to keep pins empty.) TEST_CASE("MultiPinLedDriver with the empty default pins idles cleanly") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); REQUIRE(d.pins[0] == '\0'); // the empty default, not a bench guess REQUIRE(src.allocate(64, 3)); mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); @@ -191,9 +207,10 @@ TEST_CASE("MultiPinLedDriver drives any pin count; the bus rounds up around it") mm::Buffer src; mm::Correction corr; { // 3 pins β†’ 3 lanes on the 8-bit bus, the spare 5 parked on WR. - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; std::strcpy(d.pins, "1,2,4"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 3); CHECK(d.severity() != mm::MoonModule::Severity::Error); // 64 lights over 3 lanes β†’ the longest is 22. ≀8 pins β†’ the 8-bit bus β†’ 1-byte slots, which is @@ -202,11 +219,17 @@ TEST_CASE("MultiPinLedDriver drives any pin count; the bus rounds up around it") CHECK(d.frameBytes() == expectFrame(22, 3)); } { // 16 pins β†’ the full 16-bit bus, nothing parked. clock/dc moved clear of the data set - // (defaults 10/11 would collide with data pins 10/11 β†’ the collision guard). - mm::MultiPinLedDriver d; - d.clockPin = 20; d.dcPin = 21; + // (defaults 10/11 would collide with data pins 10/11 β†’ the collision guard). clockPin/dcPin + // live on the I80Peripheral backend, so set them via the control API ParallelLedDriver + // binds (defineDriverControls -> peripheral_->addBusControls) rather than a direct member. + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); + d.defineControls(); + mm::test::setControlValue(d, "clockPin", 20); + mm::test::setControlValue(d, "dcPin", 21); std::strcpy(d.pins, "1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 16); CHECK(d.severity() != mm::MoonModule::Severity::Error); CHECK(d.maxLaneLights() == 4); @@ -214,10 +237,14 @@ TEST_CASE("MultiPinLedDriver drives any pin count; the bus rounds up around it") } { // 10 pins β€” the case the old "exactly 8 or 16" rule rejected outright. It is a perfectly good // config: 10 data lanes on the 16-bit bus, the other 6 parked. This is the point of the change. - mm::MultiPinLedDriver d; - d.clockPin = 20; d.dcPin = 21; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); + d.defineControls(); + mm::test::setControlValue(d, "clockPin", 20); + mm::test::setControlValue(d, "dcPin", 21); std::strcpy(d.pins, "1,2,4,5,6,7,8,9,12,13"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 10); CHECK(d.severity() != mm::MoonModule::Severity::Error); // 64 over 10 lanes β†’ 6 each, the last taking the remainder (PinList's even-split rule) β†’ 10. @@ -237,19 +264,23 @@ TEST_CASE("MultiPinLedDriver warns (does not idle) when a data pin is on clockPi mm::Buffer src; mm::Correction corr; { // lane on GPIO 10 == default clockPin β†’ warns but still drives all 8 lanes - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; std::strcpy(d.pins, "18,5,6,7,8,9,10,11"); // 10 == clockPin, 11 == dcPin - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 8); // still built + driving REQUIRE(d.status() != nullptr); // a warning is present CHECK(std::strstr(d.status(), "clockPin") != nullptr); } { // move clock/dc clear of the data set β†’ no warning - mm::MultiPinLedDriver d; - d.clockPin = 12; - d.dcPin = 13; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); + d.defineControls(); + mm::test::setControlValue(d, "clockPin", 12); + mm::test::setControlValue(d, "dcPin", 13); std::strcpy(d.pins, "18,5,6,7,8,9,10,11"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 8); // No collision warning β†’ the neutral consumption info instead (not a null status). CHECK(d.severity() != mm::MoonModule::Severity::Error); @@ -259,11 +290,14 @@ TEST_CASE("MultiPinLedDriver warns (does not idle) when a data pin is on clockPi // needs two distinct control lines, so this breaks the bus outright (unlike a data-lane // collision, which only corrupts that one lane and is a warn-and-run). Routed through the // error path (validateBusFatal), so the driver idles: laneCount 0, error severity. - mm::MultiPinLedDriver d; - d.clockPin = 20; - d.dcPin = 20; // same as clockPin + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); + d.defineControls(); + mm::test::setControlValue(d, "clockPin", 20); + mm::test::setControlValue(d, "dcPin", 20); // same as clockPin std::strcpy(d.pins, "1,2,3,4,5,6,7,8"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); REQUIRE(d.status() != nullptr); CHECK(std::strstr(d.status(), "same GPIO") != nullptr); CHECK(d.severity() == mm::MoonModule::Severity::Error); // idles, not warn-and-run @@ -273,10 +307,11 @@ TEST_CASE("MultiPinLedDriver warns (does not idle) when a data pin is on clockPi // A 0Γ—0Γ—0 grid is a clean idle: zero counts, zero frame (no pad for an empty frame), no crash. TEST_CASE("MultiPinLedDriver tolerates a zero-light buffer") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 0); + wire(d, peripheral, src, corr, 0); CHECK(d.laneCount() == 8); // pins parse fine CHECK(d.maxLaneLights() == 0); @@ -287,9 +322,11 @@ TEST_CASE("MultiPinLedDriver tolerates a zero-light buffer") { // setup/release cycles leave no residue (status clean, ASAN-checked heap). TEST_CASE("MultiPinLedDriver setup/release is repeatable") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); src.allocate(64, 3); mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); std::strcpy(d.pins, "1,2,4,5,6,7,8,9"); // pins now default UNSET @@ -307,7 +344,9 @@ TEST_CASE("MultiPinLedDriver setup/release is repeatable") { // loopbackRxPin is bound always, visible only while loopbackTest is on. TEST_CASE("MultiPinLedDriver loopbackRxPin tracks the loopbackTest toggle") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); bool found = false; for (uint8_t i = 0; i < d.controls().count(); i++) { @@ -325,7 +364,9 @@ TEST_CASE("MultiPinLedDriver loopbackRxPin tracks the loopbackTest toggle") { // contract is host-testable here via the shared helper (toggles loopbackTest both // ways and asserts the control stays bound while flipping visibility). TEST_CASE("MultiPinLedDriver loopbackTxPin tracks the loopbackTest toggle") { - mm::MultiPinLedDriver d; + mm::I80Peripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); auto setTest = [&](bool on) { mm::test::setControlValue(d, "loopbackTest", on); @@ -333,16 +374,22 @@ TEST_CASE("MultiPinLedDriver loopbackTxPin tracks the loopbackTest toggle") { mm::test::checkConditionalControl(d, "loopbackTxPin", setTest, /*visibleWhenTrue=*/true); } -// The pinExpander switch is HIDDEN where the silicon can't host the '595 (kSupportsPinExpander false: +// The pinExpander switch is HIDDEN where the silicon can't host the '595 (supportsPinExpander() false: // the classic ESP32 i80 = the I2S peripheral, whose DMA can't read PSRAM, so the Γ—8 expander frame has // nowhere to live). Desktop has lcdLanes==0 too, so the control is hidden here β€” the same compile-time // gate the classic build takes. On the LCD_CAM chips (S3/P4) the flag is true and the control shows; // that path is exercised on-device. Turning it on where unsupported only ever yields a config error, so // not offering the switch is the honest UI. (Before this, the toggle was shown on every chip.) +// +// kSupportsPinExpander moved from a static constexpr on the driver to a virtual on the I80Peripheral +// backend (supportsPinExpander()) β€” a bare I80Peripheral instance reaches it without needing a live +// driver's peripheral_ (which is protected). TEST_CASE("MultiPinLedDriver hides pinExpander where the chip can't host it") { - CHECK_FALSE(mm::MultiPinLedDriver::kSupportsPinExpander); // desktop lcdLanes==0 β†’ unsupported + mm::I80Peripheral peripheral; + CHECK_FALSE(peripheral.supportsPinExpander()); // desktop lcdLanes==0 β†’ unsupported - mm::MultiPinLedDriver d; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); bool found = false; for (uint8_t i = 0; i < d.controls().count(); i++) { @@ -350,7 +397,7 @@ TEST_CASE("MultiPinLedDriver hides pinExpander where the chip can't host it") { found = true; // Hidden exactly when the chip can't host the expander β€” ties the assertion to the flag // rather than to the desktop's happens-to-be-unsupported value, so it stays correct on any target. - CHECK(d.controls()[i].hidden == !mm::MultiPinLedDriver::kSupportsPinExpander); + CHECK(d.controls()[i].hidden == !peripheral.supportsPinExpander()); } } CHECK(found); // still BOUND (a saved value survives), just not shown diff --git a/test/unit/light/unit_ParallelLedDriver_doublebuffer.cpp b/test/unit/light/unit_ParallelLedDriver_doublebuffer.cpp index 89d8550b..bd84dbf5 100644 --- a/test/unit/light/unit_ParallelLedDriver_doublebuffer.cpp +++ b/test/unit/light/unit_ParallelLedDriver_doublebuffer.cpp @@ -14,9 +14,10 @@ // Host test of the deferred-wait DOUBLE-BUFFER logic in ParallelLedDriver::tick() // (Step 1.5). The real LCD/Parlio peripherals are inert on the host (desktop stubs // return null), so the alternation/wait/drain invariants can't be exercised through -// them. Instead a MockDriver supplies the CRTP bus* hooks against two in-memory -// buffers and RECORDS the call sequence, so the base loop's behavior is pinned on -// the host exactly where the hardware would run it: +// them. Instead a MockPeripheral (a runtime LedPeripheral backend) supplies the bus* +// hooks against two in-memory buffers and RECORDS the call sequence, so the +// orchestrator's loop behavior is pinned on the host exactly where the hardware +// would run it: // - double-buffer mode alternates encode target 0,1,0,1,… and waits on a buffer // only right before it's REUSED (never after every transmit); // - single-buffer mode (mock offers no buffer 1) stays on buffer 0 and waits every @@ -28,43 +29,35 @@ namespace { using mm::nrOfLightsType; -// A record of one bus call, so a test can assert the exact ordering the base emits. +// A record of one bus call, so a test can assert the exact ordering the orchestrator emits. struct Call { enum Kind { Transmit, Wait } kind; uint8_t buffer; }; -// CRTP peripheral mock: two heap buffers, a settable "double-buffer available" flag, -// and a call log. Everything the base's tick()/reinit()/deinit() reach is here. -class MockParallelDriver : public mm::ParallelLedDriver { +// LedPeripheral mock: two heap buffers, a settable "double-buffer available" flag, +// and a call log. Everything the orchestrator's tick()/reinit()/deinit() reach is here. +class MockPeripheral : public mm::LedPeripheral { public: // --- test knobs / observation --- bool twoBuffers = true; // false β†’ single-buffer mode (busBuffer(1) == null) std::vector calls; // transmit/wait order, in call sequence - uint8_t activeForTest() const { return active_; } - bool inFlightForTest(uint8_t i) const { return inFlight_[i]; } - // --- CRTP hooks (mock, host-only) --- - static constexpr uint8_t lanesAvailable() { return 8; } // pretend this chip has lanes - static constexpr bool kPowerOfTwoBus = false; - static constexpr bool kLoopbackFullWidth = false; + // --- LedPeripheral hooks (mock, host-only) --- + uint8_t lanesAvailable() const override { return 8; } // pretend this chip has lanes + bool powerOfTwoBus() const override { return false; } + bool loopbackFullWidth() const override { return false; } // The mock bus is memory, not a peripheral, so it can host the 74HCT595 expander β€” which is what // lets the shift-register lane/frame arithmetic be pinned on the host (unit_ParallelSlots covers // the encoded bits; here it's the driver plumbing). - static constexpr bool kSupportsPinExpander = true; - static constexpr const char* kInitFailMsg = "mock init failed"; + bool supportsPinExpander() const override { return true; } + const char* initFailMsg() const override { return "mock init failed"; } + mm::LedHwBlock hwBlock() const override { return mm::LedHwBlock::None; } // mock drives no real block - void addBusControls() {} - bool busControlTriggersBuild(const char*) const { return false; } - void recordBusPins() {} - bool extraBusPinsCurrent() const { return true; } - const char* validateBusPins(const uint16_t*, uint8_t) const { return nullptr; } - const char* validateBusFatal() const { return nullptr; } - - // busInit gets `wantSecond` from the base (= doubleBuffer). The mock allocates the second + // busInit gets `wantSecond` from the orchestrator (= doubleBuffer). The mock allocates the second // buffer only when BOTH the flag wants it AND the test's twoBuffers knob allows it (so a test // can simulate a memory-tight board that refuses the second buffer even with async on). - bool busInit(size_t frameBytes, bool wantSecond) { + bool busInit(size_t frameBytes, bool wantSecond) override { cap_ = frameBytes; buf_[0].assign(frameBytes, 0); if (wantSecond && twoBuffers) buf_[1].assign(frameBytes, 0); @@ -72,26 +65,26 @@ class MockParallelDriver : public mm::ParallelLedDriver { inited_ = true; return true; } - uint8_t* busBuffer(uint8_t i) { + uint8_t* busBuffer(uint8_t i) override { if (i >= 2 || buf_[i].empty()) return nullptr; return buf_[i].data(); } - size_t busCapacity() const { return cap_; } - bool busTransmit(uint8_t i, size_t /*bytes*/) { + size_t busCapacity() const override { return cap_; } + bool busTransmit(uint8_t i, size_t /*bytes*/) override { calls.push_back({Call::Transmit, i}); return true; // the mock transfer always "starts" } // Returns whether the transfer completed. `waitTimesOut` makes every wait report a TIMEOUT, so a // test can prove the driver refuses to re-encode into a buffer the DMA may still be reading. - bool busWait(uint8_t i, uint32_t) { + bool busWait(uint8_t i, uint32_t) override { calls.push_back({Call::Wait, i}); return !waitTimesOut; } bool waitTimesOut = false; - uint32_t busLastTransmitUs() const { return lastTransmitUs; } // mock wire-time KPI + uint32_t busLastTransmitUs() const override { return lastTransmitUs; } // mock wire-time KPI uint32_t lastTransmitUs = 0; // a test can set this to check the frameTime string formatting - void busDeinit() { cap_ = 0; buf_[0].clear(); buf_[1].clear(); inited_ = false; } - mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) { + void busDeinit() override { cap_ = 0; buf_[0].clear(); buf_[1].clear(); inited_ = false; } + mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) override { return {}; } @@ -102,12 +95,13 @@ class MockParallelDriver : public mm::ParallelLedDriver { }; // Wire a mock driver onto a `lights`-light source buffer + a GRB correction, and drive it ready. -// `async` sets doubleBuffer (whether the base requests a second buffer); `canSecond` is the mock's -// board-fits-a-second-buffer knob (lets a test simulate a memory-tight board that refuses it even -// with async on). Mirrors the other parallel-driver test helpers. -void wire(MockParallelDriver& d, mm::Buffer& src, mm::Correction& corr, +// `async` sets doubleBuffer (whether the orchestrator requests a second buffer); `canSecond` is the +// mock's board-fits-a-second-buffer knob (lets a test simulate a memory-tight board that refuses it +// even with async on). Mirrors the other parallel-driver test helpers. +void wire(mm::ParallelLedDriver& d, MockPeripheral& peripheral, mm::Buffer& src, mm::Correction& corr, nrOfLightsType lights, bool async, bool canSecond = true) { - d.twoBuffers = canSecond; + peripheral.twoBuffers = canSecond; + d.setPeripheralForTest(&peripheral); d.doubleBuffer = async; std::strcpy(d.pins, "1,2,3,4"); REQUIRE(src.allocate(lights, 3) == (lights > 0)); @@ -125,10 +119,11 @@ void wire(MockParallelDriver& d, mm::Buffer& src, mm::Correction& corr, // the first two ticks transmit without a preceding wait (both buffers start idle), // and from tick 3 on each tick waits on the buffer it's about to reuse. TEST_CASE("ParallelLedDriver double-buffer alternates and defers the wait") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true); + wire(d, peripheral, src, corr, 64, /*async=*/true); // Tick 1: buffer 0 idle β†’ no wait, transmit 0, flip to 1. d.tick(); @@ -145,24 +140,25 @@ TEST_CASE("ParallelLedDriver double-buffer alternates and defers the wait") { d.tick(); CHECK(d.activeForTest() == 0); - // The exact call order the base emitted. - REQUIRE(d.calls.size() == 6); - CHECK(d.calls[0].kind == Call::Transmit); CHECK(d.calls[0].buffer == 0); - CHECK(d.calls[1].kind == Call::Transmit); CHECK(d.calls[1].buffer == 1); - CHECK(d.calls[2].kind == Call::Wait); CHECK(d.calls[2].buffer == 0); - CHECK(d.calls[3].kind == Call::Transmit); CHECK(d.calls[3].buffer == 0); - CHECK(d.calls[4].kind == Call::Wait); CHECK(d.calls[4].buffer == 1); - CHECK(d.calls[5].kind == Call::Transmit); CHECK(d.calls[5].buffer == 1); + // The exact call order the orchestrator emitted. + REQUIRE(peripheral.calls.size() == 6); + CHECK(peripheral.calls[0].kind == Call::Transmit); CHECK(peripheral.calls[0].buffer == 0); + CHECK(peripheral.calls[1].kind == Call::Transmit); CHECK(peripheral.calls[1].buffer == 1); + CHECK(peripheral.calls[2].kind == Call::Wait); CHECK(peripheral.calls[2].buffer == 0); + CHECK(peripheral.calls[3].kind == Call::Transmit); CHECK(peripheral.calls[3].buffer == 0); + CHECK(peripheral.calls[4].kind == Call::Wait); CHECK(peripheral.calls[4].buffer == 1); + CHECK(peripheral.calls[5].kind == Call::Transmit); CHECK(peripheral.calls[5].buffer == 1); } // Single-buffer mode (no second buffer): the driver stays on buffer 0 and waits on // it EVERY frame before re-encoding β€” the old synchronous wait-after-transmit path, // so a memory-tight board keeps its old fps rather than failing to init. TEST_CASE("ParallelLedDriver single-buffer mode waits every frame on buffer 0") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/false); // default: no second buffer, synchronous path + wire(d, peripheral, src, corr, 64, /*async=*/false); // default: no second buffer, synchronous path d.tick(); // tickSync: transmit 0, wait 0 CHECK(d.activeForTest() == 0); @@ -171,15 +167,15 @@ TEST_CASE("ParallelLedDriver single-buffer mode waits every frame on buffer 0") d.tick(); // transmit 0, wait 0 // tickSync waits RIGHT AFTER each transmit (the original synchronous order): T0,W0 Γ—3. - REQUIRE(d.calls.size() == 6); - CHECK(d.calls[0].kind == Call::Transmit); CHECK(d.calls[0].buffer == 0); - CHECK(d.calls[1].kind == Call::Wait); CHECK(d.calls[1].buffer == 0); - CHECK(d.calls[2].kind == Call::Transmit); CHECK(d.calls[2].buffer == 0); - CHECK(d.calls[3].kind == Call::Wait); CHECK(d.calls[3].buffer == 0); - CHECK(d.calls[4].kind == Call::Transmit); CHECK(d.calls[4].buffer == 0); - CHECK(d.calls[5].kind == Call::Wait); CHECK(d.calls[5].buffer == 0); + REQUIRE(peripheral.calls.size() == 6); + CHECK(peripheral.calls[0].kind == Call::Transmit); CHECK(peripheral.calls[0].buffer == 0); + CHECK(peripheral.calls[1].kind == Call::Wait); CHECK(peripheral.calls[1].buffer == 0); + CHECK(peripheral.calls[2].kind == Call::Transmit); CHECK(peripheral.calls[2].buffer == 0); + CHECK(peripheral.calls[3].kind == Call::Wait); CHECK(peripheral.calls[3].buffer == 0); + CHECK(peripheral.calls[4].kind == Call::Transmit); CHECK(peripheral.calls[4].buffer == 0); + CHECK(peripheral.calls[5].kind == Call::Wait); CHECK(peripheral.calls[5].buffer == 0); // Buffer 1 is never allocated or touched. - for (const auto& c : d.calls) CHECK(c.buffer == 0); + for (const auto& c : peripheral.calls) CHECK(c.buffer == 0); } // doubleBuffer is the on/off knob AND drives allocation: OFF (default) allocates ONE buffer and @@ -188,63 +184,66 @@ TEST_CASE("ParallelLedDriver single-buffer mode waits every frame on buffer 0") // it off never holds the second buffer. This mirrors the live toggle (the A/B knob), which routes // through applyState()/prepare() the same way. TEST_CASE("ParallelLedDriver doubleBuffer toggles allocation and path") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/false); + wire(d, peripheral, src, corr, 64, /*async=*/false); // OFF: single buffer only β€” buffer 1 was never allocated, and tick runs synchronous. - CHECK(d.busBuffer(1) == nullptr); + CHECK(peripheral.busBuffer(1) == nullptr); d.tick(); - REQUIRE(d.calls.size() == 2); // T0, W0 β€” synchronous - CHECK(d.calls[0].kind == Call::Transmit); - CHECK(d.calls[1].kind == Call::Wait); + REQUIRE(peripheral.calls.size() == 2); // T0, W0 β€” synchronous + CHECK(peripheral.calls[0].kind == Call::Transmit); + CHECK(peripheral.calls[1].kind == Call::Wait); // Flip ON and re-prepare (what a live control change does): the second buffer is now allocated. d.doubleBuffer = true; d.applyState(); - CHECK(d.busBuffer(1) != nullptr); - d.calls.clear(); + CHECK(peripheral.busBuffer(1) != nullptr); + peripheral.calls.clear(); d.tick(); // async: transmit 0, no wait, flip to 1 d.tick(); // async: transmit 1, no wait, flip to 0 CHECK(d.activeForTest() == 0); // Two transmits, no interleaved wait (both buffers idle at start) β€” the deferred-wait pattern. - REQUIRE(d.calls.size() == 2); - CHECK(d.calls[0].kind == Call::Transmit); CHECK(d.calls[0].buffer == 0); - CHECK(d.calls[1].kind == Call::Transmit); CHECK(d.calls[1].buffer == 1); + REQUIRE(peripheral.calls.size() == 2); + CHECK(peripheral.calls[0].kind == Call::Transmit); CHECK(peripheral.calls[0].buffer == 0); + CHECK(peripheral.calls[1].kind == Call::Transmit); CHECK(peripheral.calls[1].buffer == 1); // Flip back OFF and re-prepare: the second buffer is freed, back to synchronous. d.doubleBuffer = false; d.applyState(); - CHECK(d.busBuffer(1) == nullptr); + CHECK(peripheral.busBuffer(1) == nullptr); } // A board that WANTS async but can't fit the second buffer (memory-tight) degrades to single-buffer // synchronous β€” never fails to init. doubleBuffer is on, but the mock refuses the second buffer. TEST_CASE("ParallelLedDriver async degrades to synchronous when second buffer won't fit") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true, /*canSecond=*/false); - CHECK(d.busBuffer(1) == nullptr); // requested but didn't fit + wire(d, peripheral, src, corr, 64, /*async=*/true, /*canSecond=*/false); + CHECK(peripheral.busBuffer(1) == nullptr); // requested but didn't fit d.tick(); - REQUIRE(d.calls.size() == 2); // synchronous path (T0, W0) - CHECK(d.calls[0].kind == Call::Transmit); - CHECK(d.calls[1].kind == Call::Wait); + REQUIRE(peripheral.calls.size() == 2); // synchronous path (T0, W0) + CHECK(peripheral.calls[0].kind == Call::Transmit); + CHECK(peripheral.calls[1].kind == Call::Wait); } // The frameTime KPI: tick1s() pulls the platform's measured wire time via busLastTransmitUs(). The // string formatting + the actual DMA timing are verified on hardware (the metric's whole point is a // real wire measurement); here we just pin that tick1s reads the seam without crashing pre-first-frame. TEST_CASE("ParallelLedDriver frameTime tick1s is safe before the first transfer") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true); + wire(d, peripheral, src, corr, 64, /*async=*/true); d.tick1s(); // lastTransmitUs == 0 β†’ placeholder path, must not divide by zero - d.lastTransmitUs = 7680; // the 256-light WS2812 floor + peripheral.lastTransmitUs = 7680; // the 256-light WS2812 floor d.tick1s(); // real path (1e6/7680 = 130 fps) β€” must not crash - CHECK(d.busLastTransmitUs() == 7680); + CHECK(peripheral.busLastTransmitUs() == 7680); } // Robustness + no-caps (regression for a live bootloop): a correction can carry ANY channel count @@ -254,7 +253,9 @@ TEST_CASE("ParallelLedDriver frameTime tick1s is safe before the first transfer" // driver must DRIVE it (size the frame + encode), not idle and not crash. TEST_CASE("ParallelLedDriver drives an N-channel (>4) correction without overflow") { using R = mm::ChannelRole; - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; + d.setPeripheralForTest(&peripheral); mm::Buffer src; mm::Correction corr; d.doubleBuffer = true; @@ -273,16 +274,16 @@ TEST_CASE("ParallelLedDriver drives an N-channel (>4) correction without overflo // frameBytes scales with 8). The encode runs and transmits; the ASan/valgrind-clean run (and the // hardware regression on the SE16) is the overflow proof β€” a 4-byte stride would have corrupted // memory here. - CHECK(d.severity() != MockParallelDriver::Severity::Error); + CHECK(d.severity() != mm::ParallelLedDriver::Severity::Error); CHECK(d.frameBytes() > 0); // The status reports the total channel count for a multi-channel fixture (lights Γ— channels) β€” // the DMX-universe footprint the user sizes against, not just the light count. CHECK(std::string(d.status()).find("(") != std::string::npos); // "... (N channels)" CHECK(std::string(d.status()).find("channels") != std::string::npos); - d.calls.clear(); + peripheral.calls.clear(); d.tick(); - REQUIRE(d.calls.size() >= 1); - CHECK(d.calls[0].kind == Call::Transmit); // it actually drove the fixture + REQUIRE(peripheral.calls.size() >= 1); + CHECK(peripheral.calls[0].kind == Call::Transmit); // it actually drove the fixture } // A reinit (grid resize / pin edit) must drain BOTH buffers' in-flight transfers @@ -290,16 +291,17 @@ TEST_CASE("ParallelLedDriver drives an N-channel (>4) correction without overflo // use-after-free. After two ticks both buffers are in flight; the resize's reinit // waits on both before rebuilding. (async on β†’ two buffers.) TEST_CASE("ParallelLedDriver reinit drains both in-flight buffers") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true); + wire(d, peripheral, src, corr, 64, /*async=*/true); d.tick(); // transmit 0 (in flight) d.tick(); // transmit 1 (in flight) CHECK(d.inFlightForTest(0) == true); CHECK(d.inFlightForTest(1) == true); - const size_t before = d.calls.size(); + const size_t before = peripheral.calls.size(); // Force a rebuild by growing the grid, which changes frameBytes β†’ reinit(). REQUIRE(src.allocate(256, 3) == true); @@ -308,9 +310,9 @@ TEST_CASE("ParallelLedDriver reinit drains both in-flight buffers") { // Both buffers were waited on during the drain (order-independent β€” assert both present). bool waited0 = false, waited1 = false; - for (size_t i = before; i < d.calls.size(); i++) { - if (d.calls[i].kind == Call::Wait && d.calls[i].buffer == 0) waited0 = true; - if (d.calls[i].kind == Call::Wait && d.calls[i].buffer == 1) waited1 = true; + for (size_t i = before; i < peripheral.calls.size(); i++) { + if (peripheral.calls[i].kind == Call::Wait && peripheral.calls[i].buffer == 0) waited0 = true; + if (peripheral.calls[i].kind == Call::Wait && peripheral.calls[i].buffer == 1) waited1 = true; } CHECK(waited0); CHECK(waited1); @@ -326,32 +328,33 @@ TEST_CASE("ParallelLedDriver reinit drains both in-flight buffers") { // inFlight_ either way; πŸ‡ CodeRabbit caught it.) The contract now: on timeout the buffer STAYS // in-flight, the frame is skipped, and the driver re-waits next tick β€” self-healing, never corrupting. TEST_CASE("ParallelLedDriver: a timed-out wait never re-encodes into the live buffer") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true); + wire(d, peripheral, src, corr, 64, /*async=*/true); d.tick(); // encode+transmit buffer 0 β†’ in flight d.tick(); // encode+transmit buffer 1 β†’ in flight; next tick must reuse buffer 0 REQUIRE(d.inFlightForTest(0) == true); - d.waitTimesOut = true; // buffer 0's transfer is wedged (the DMA never completes) - const size_t before = d.calls.size(); + peripheral.waitTimesOut = true; // buffer 0's transfer is wedged (the DMA never completes) + const size_t before = peripheral.calls.size(); d.tick(); // must NOT encode/transmit into buffer 0 // It waited on 0 and then gave up β€” no Encode, no Transmit followed. bool transmitted = false; - for (size_t i = before; i < d.calls.size(); i++) - if (d.calls[i].kind == Call::Transmit) transmitted = true; + for (size_t i = before; i < peripheral.calls.size(); i++) + if (peripheral.calls[i].kind == Call::Transmit) transmitted = true; CHECK_FALSE(transmitted); // the live buffer was NOT reused CHECK(d.inFlightForTest(0) == true); // still marked in flight, so the next tick re-waits // The DMA completes: the very next tick proceeds normally β€” it self-heals, no reinit needed. - d.waitTimesOut = false; + peripheral.waitTimesOut = false; d.tick(); bool transmittedNow = false; - for (size_t i = before; i < d.calls.size(); i++) - if (d.calls[i].kind == Call::Transmit) transmittedNow = true; + for (size_t i = before; i < peripheral.calls.size(); i++) + if (peripheral.calls[i].kind == Call::Transmit) transmittedNow = true; CHECK(transmittedNow); } @@ -362,29 +365,30 @@ TEST_CASE("ParallelLedDriver: a timed-out wait never re-encodes into the live bu // control. So once given up, the driver periodically lets one frame through; if the bus is alive again, // output resumes on its own. This pins that retry-recovery. TEST_CASE("ParallelLedDriver: give-up self-recovers on a periodic retry, no reinit needed") { - MockParallelDriver d; + mm::ParallelLedDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 64, /*async=*/true); + wire(d, peripheral, src, corr, 64, /*async=*/true); // Wedge the bus and tick until it gives up: every wait times out, so each frame is a dead strike. - d.waitTimesOut = true; + peripheral.waitTimesOut = true; for (int i = 0; i < 40; i++) d.tick(); // well past kDeadFramesBeforeGiveUp CHECK(d.severity() == mm::DriverBase::Severity::Error); // reported "output stalled" // While given up, a tick must NOT transmit every frame (that would keep spending the render thread). - size_t mark = d.calls.size(); + size_t mark = peripheral.calls.size(); d.tick(); bool transmittedWhileGivenUp = false; - for (size_t i = mark; i < d.calls.size(); i++) - if (d.calls[i].kind == Call::Transmit) transmittedWhileGivenUp = true; + for (size_t i = mark; i < peripheral.calls.size(); i++) + if (peripheral.calls[i].kind == Call::Transmit) transmittedWhileGivenUp = true; CHECK_FALSE(transmittedWhileGivenUp); // this tick was inside the quiet window, not a retry // The bus comes back to life. Within one retry window the driver lets a frame through, it completes, // and output resumes β€” no config change, no reinit. Recovery means the driver actually LEFT the // give-up state (its Error status cleared), not merely that one retry Transmit happened: a retry that // transmits but whose wait still fails would keep the driver given-up, and that must NOT count. - d.waitTimesOut = false; + peripheral.waitTimesOut = false; bool recovered = false; for (int i = 0; i < 200 && !recovered; i++) { // several retry windows' worth of margin d.tick(); @@ -393,10 +397,10 @@ TEST_CASE("ParallelLedDriver: give-up self-recovers on a periodic retry, no rein CHECK(recovered); // the give-up Error state cleared β€” the driver is transmitting normally again // And it keeps transmitting on the following ticks (steady-state, not a one-off retry blip). - const size_t after = d.calls.size(); + const size_t after = peripheral.calls.size(); d.tick(); bool stillTransmitting = false; - for (size_t j = after; j < d.calls.size(); j++) - if (d.calls[j].kind == Call::Transmit) stillTransmitting = true; + for (size_t j = after; j < peripheral.calls.size(); j++) + if (peripheral.calls[j].kind == Call::Transmit) stillTransmitting = true; CHECK(stillTransmitting); } diff --git a/test/unit/light/unit_ParallelLedDriver_pinexpander.cpp b/test/unit/light/unit_ParallelLedDriver_pinexpander.cpp index f49fd987..7c0d4c31 100644 --- a/test/unit/light/unit_ParallelLedDriver_pinexpander.cpp +++ b/test/unit/light/unit_ParallelLedDriver_pinexpander.cpp @@ -22,64 +22,49 @@ namespace { using mm::nrOfLightsType; -// A mock parallel driver whose "bus" is plain memory (same shape as the double-buffer mock), -// so the lane/frame arithmetic is provable on the host with no peripheral. -class MockShiftDriver : public mm::ParallelLedDriver { +// A mock peripheral backend whose "bus" is plain memory (same shape as the double-buffer mock's +// MockPeripheral in unit_ParallelLedDriver_doublebuffer.cpp), so the lane/frame arithmetic is +// provable on the host with no real i80/Parlio/MoonI80 peripheral. Models the i80 SHAPE +// (powerOfTwoBus true β€” the expander only ever runs on an i80-shaped bus). +class MockPeripheral : public mm::LedPeripheral { public: - static constexpr uint8_t lanesAvailable() { return 8; } // 8 data lines, like an 8-bit bus - // The i80 shape: the BUS rounds to 8/16 whatever the pin count, so the driver pads the lane list. - // (Parlio, the other shape, sets this false β€” its bus width IS the pin count.) The expander only - // ever runs on an i80-shaped bus, so the mock models that one. - static constexpr bool kPowerOfTwoBus = true; - static constexpr bool kLoopbackFullWidth = false; - static constexpr bool kSupportsPinExpander = true; // memory bus: the expander is allowed - static constexpr const char* kInitFailMsg = "mock init failed"; - - void addBusControls() {} - bool busControlTriggersBuild(const char*) const { return false; } - void recordBusPins() {} - bool extraBusPinsCurrent() const { return true; } - const char* validateBusPins(const uint16_t*, uint8_t) const { return nullptr; } - const char* validateBusFatal() const { return nullptr; } - - bool busInit(size_t frameBytes, bool) { + uint8_t lanesAvailable() const override { return 8; } // 8 data lines, like an 8-bit bus + bool powerOfTwoBus() const override { return true; } // the BUS rounds to 8/16 whatever the pin count + bool loopbackFullWidth() const override { return false; } + bool supportsPinExpander() const override { return true; } // memory bus: the expander is allowed + const char* initFailMsg() const override { return "mock init failed"; } + mm::LedHwBlock hwBlock() const override { return mm::LedHwBlock::None; } // mock drives no real block + + void addBusControls(mm::ControlList&) override {} + bool busControlTriggersBuild(const char*) const override { return false; } + void recordBusPins() override {} + bool extraBusPinsCurrent() const override { return true; } + const char* validateBusPins(const uint16_t*, uint8_t) const override { return nullptr; } + const char* validateBusFatal() const override { return nullptr; } + uint16_t clockPinForBus() const override { return 99; } // a recognisable "parked here" sentinel + + bool busInit(size_t frameBytes, bool) override { cap_ = frameBytes; buf_.assign(frameBytes, 0); return true; } - - // The streaming ring encodes the frame one SLICE at a time, straight into the small internal - // buffer the DMA is about to read. That is only sound if a sliced encode produces byte-identical - // output to the whole-frame encode β€” so expose the encoder for the test that pins it. - template - void encodeSliceForTest(uint8_t outCh, uint8_t* dst, mm::nrOfLightsType first, - mm::nrOfLightsType count, bool closeFrame) { - this->template encodeRows(outCh, dst, first, count, closeFrame); - } - uint8_t* busBuffer(uint8_t i) { return (i == 0 && !buf_.empty()) ? buf_.data() : nullptr; } - size_t busCapacity() const { return cap_; } + uint8_t* busBuffer(uint8_t i) override { return (i == 0 && !buf_.empty()) ? buf_.data() : nullptr; } + size_t busCapacity() const override { return cap_; } // busTransmit reports success β€” as the real one does. This is the crux of the 2026-07-14 bug: // esp_lcd's tx_color returns ESP_OK because the ENQUEUE succeeded, while the GDMA mount fails // later inside the ISR. So "transmit returned true" does NOT mean the frame reached the wire. - bool busTransmit(uint8_t, size_t) { transmits_++; return true; } + bool busTransmit(uint8_t, size_t) override { transmits_++; return true; } // `waitTimesOut` simulates a transfer whose done-callback never fires β€” precisely what a failed // GDMA mount produces. The driver must degrade, not wedge, and must not reuse the buffer. - bool busWait(uint8_t, uint32_t) { return !waitTimesOut; } + bool busWait(uint8_t, uint32_t) override { return !waitTimesOut; } bool waitTimesOut = false; - uint32_t busLastTransmitUs() const { return 0; } - void busDeinit() { cap_ = 0; buf_.clear(); } - mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) { + uint32_t busLastTransmitUs() const override { return 0; } + void busDeinit() override { cap_ = 0; buf_.clear(); } + mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) override { return {}; } - // Test-only view of the derived lane math. - uint8_t physPinsForTest() const { return physPins_; } size_t transmitCount() const { return transmits_; } - // The GPIO list + length handed to the PERIPHERAL β€” the two must agree, or the platform reads off - // the end of the array. See the padding test below. - const uint16_t* busPinListForTest() { return this->busPinList(); } - uint8_t busPinCountForTest() const { return this->busPinCount(); } - uint16_t clockPinForBus() const { return 99; } // a recognisable "parked here" sentinel private: std::vector buf_; @@ -87,10 +72,36 @@ class MockShiftDriver : public mm::ParallelLedDriver { size_t transmits_ = 0; }; +// A tiny ParallelLedDriver subclass that exposes the protected lane-math internals a test needs +// (physPins_, encodeRows) without widening the production class's public surface β€” same pattern as +// unit_MultiPinLedDriver.cpp's `Expose : mm::ParallelLedDriver` for frameFitsDmaBudget. Everything +// else the tests use (laneCount, maxLaneLights, frameBytes, busPinList/busPinCount, pins, +// ledsPerPin, pinExpander, latchPin, defineControls, setSourceBuffer, correctionForTest, +// applyState, severity, status) is already public on ParallelLedDriver itself. +class MockShiftDriver : public mm::ParallelLedDriver { +public: + // The streaming ring encodes the frame one SLICE at a time, straight into the small internal + // buffer the DMA is about to read. That is only sound if a sliced encode produces byte-identical + // output to the whole-frame encode β€” so expose the encoder for the test that pins it. + template + void encodeSliceForTest(uint8_t outCh, uint8_t* dst, mm::nrOfLightsType first, + mm::nrOfLightsType count, bool closeFrame) { + this->template encodeRows(outCh, dst, first, count, closeFrame); + } + // Test-only view of the derived lane math. + uint8_t physPinsForTest() const { return physPins_; } + // The GPIO list + length handed to the PERIPHERAL β€” the two must agree, or the platform reads off + // the end of the array. See the padding test below. (busPinList/busPinCount are already public.) + const uint16_t* busPinListForTest() { return this->busPinList(); } + uint8_t busPinCountForTest() const { return this->busPinCount(); } +}; + // Bring a mock driver up on `lights` lights with the given pin list and expander setting. // shiftOn fits the 74HCT595 expander (8 strands per pin); latch is the latch GPIO. -void wire(MockShiftDriver& d, mm::Buffer& src, mm::Correction& corr, nrOfLightsType lights, - const char* pins, bool shiftOn, int8_t latch, const char* ledsPerPin = "") { +void wire(MockShiftDriver& d, MockPeripheral& peripheral, mm::Buffer& src, mm::Correction& corr, + nrOfLightsType lights, const char* pins, bool shiftOn, int8_t latch, + const char* ledsPerPin = "") { + d.setPeripheralForTest(&peripheral); std::strcpy(d.pins, pins); std::strcpy(d.ledsPerPin, ledsPerPin); d.pinExpander = shiftOn; @@ -109,10 +120,11 @@ void wire(MockShiftDriver& d, mm::Buffer& src, mm::Correction& corr, nrOfLightsT // the whole point of the expander (pins are the scarce resource, not strands). TEST_CASE("shift register: lanes = pins x 8") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; // 6 data pins + a latch β†’ 48 strands, the PO's 48x256 panel. - wire(d, src, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); + wire(d, peripheral, src, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); CHECK(d.physPinsForTest() == 6); CHECK(d.laneCount() == 48); // 6 pins x 8 outputs @@ -128,10 +140,11 @@ TEST_CASE("shift register: lanes = pins x 8") { // furthest read is < 1920. TEST_CASE("shift register: driver clamps to pins x ledsPerPin, ignoring a larger layout") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; // Source is 1920 lights (a 5x3 grid of 8x16 panels); the driver only drives 2 pins x 8 x 60 = 960. - wire(d, src, corr, /*lights=*/1920, "9,10", /*shiftOn=*/true, /*latch=*/11, /*ledsPerPin=*/"60"); + wire(d, peripheral, src, corr, /*lights=*/1920, "9,10", /*shiftOn=*/true, /*latch=*/11, /*ledsPerPin=*/"60"); CHECK(d.laneCount() == 16); // 2 pins x 8 outputs CHECK(d.maxLaneLights() == 60); // clamped to ledsPerPin, NOT the 1920/16 the source could feed @@ -155,9 +168,10 @@ TEST_CASE("shift register: driver clamps to pins x ledsPerPin, ignoring a larger // the expander must not have altered the existing behaviour. TEST_CASE("shift register: direct mode still drives one strand per pin") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 4 * 256, "1,2,3,4", /*shiftOn=*/false, /*latch=*/-1); + wire(d, peripheral, src, corr, 4 * 256, "1,2,3,4", /*shiftOn=*/false, /*latch=*/-1); CHECK(d.physPinsForTest() == 4); CHECK(d.laneCount() == 4); // no fan-out @@ -174,15 +188,17 @@ TEST_CASE("shift register: frame is set by strand LENGTH and the fan-out, not by // 2 pins x 8 = 16 strands, 256 lights each. MockShiftDriver small; + MockPeripheral peripheralSmall; mm::Buffer srcSmall; - wire(small, srcSmall, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(small, peripheralSmall, srcSmall, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); CHECK(small.laneCount() == 16); CHECK(small.maxLaneLights() == 256); // 6 pins x 8 = 48 strands, still 256 lights each β€” 3x the strands, 3x the lights. MockShiftDriver big; + MockPeripheral peripheralBig; mm::Buffer srcBig; - wire(big, srcBig, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); + wire(big, peripheralBig, srcBig, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); CHECK(big.laneCount() == 48); CHECK(big.maxLaneLights() == 256); @@ -197,15 +213,17 @@ TEST_CASE("shift register: the fan-out costs 8x the DMA frame") { // 8 strands, 256 lights each β€” direct (8 pins, one strand each). MockShiftDriver direct; + MockPeripheral peripheralDirect; mm::Buffer srcDirect; - wire(direct, srcDirect, corr, 8 * 256, "1,2,3,4,5,6,7,8", /*shiftOn=*/false, /*latch=*/-1); + wire(direct, peripheralDirect, srcDirect, corr, 8 * 256, "1,2,3,4,5,6,7,8", /*shiftOn=*/false, /*latch=*/-1); CHECK(direct.laneCount() == 8); CHECK(direct.maxLaneLights() == 256); // The same 8 strands at the same length, but through ONE pin's '595. MockShiftDriver shifted; + MockPeripheral peripheralShifted; mm::Buffer srcShifted; - wire(shifted, srcShifted, corr, 8 * 256, "1", /*shiftOn=*/true, /*latch=*/2); + wire(shifted, peripheralShifted, srcShifted, corr, 8 * 256, "1", /*shiftOn=*/true, /*latch=*/2); CHECK(shifted.laneCount() == 8); CHECK(shifted.maxLaneLights() == 256); @@ -224,9 +242,10 @@ TEST_CASE("shift register: the fan-out costs 8x the DMA frame") { // encode 16-bit slots into an 8-bit bus and emit a frame of pure garbage. TEST_CASE("shift register: 48 strands on 6 pins is still an 8-bit bus") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); + wire(d, peripheral, src, corr, 48 * 256, "1,2,3,4,5,6", /*shiftOn=*/true, /*latch=*/7); CHECK(d.laneCount() == 48); // ...strands, but // frameBytes = rows x channels x 24 slots x slotBytes x 8 (+ pad). With an 8-bit @@ -241,11 +260,12 @@ TEST_CASE("shift register: 48 strands on 6 pins is still an 8-bit bus") { // that lane would carry the latch waveform instead of pixel data. A config error, not a crash. TEST_CASE("shift register: latchPin colliding with a data pin is a config error") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/true, /*latch=*/3); // 3 is a data pin + wire(d, peripheral, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/true, /*latch=*/3); // 3 is a data pin - CHECK(d.severity() == MockShiftDriver::Severity::Error); + CHECK(d.severity() == mm::MoonModule::Severity::Error); CHECK(d.laneCount() == 0); // idles rather than driving a broken bus } @@ -253,27 +273,29 @@ TEST_CASE("shift register: latchPin colliding with a data pin is a config error" // config rather than run a bus that silently outputs nothing. TEST_CASE("shift register: the expander needs a latchPin") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/true, /*latch=*/-1); // unset + wire(d, peripheral, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/true, /*latch=*/-1); // unset - CHECK(d.severity() == MockShiftDriver::Severity::Error); + CHECK(d.severity() == mm::MoonModule::Severity::Error); CHECK(d.laneCount() == 0); } // The latch must not land on the peripheral's own WR/DC pins either β€” bench-found, because WR // defaults to GPIO 10 and that is the first free-looking pin a user reaches for. The i80 bus builds // fine, so the failure is silent garbage on the strands rather than an init error; that is what makes -// it worth an explicit guard. (The check itself lives in MultiPinLedDriver::validateBusFatal, which the +// it worth an explicit guard. (The check itself lives in I80Peripheral::validateBusFatal, which the // mock does not have β€” this pins the base's half: a data-pin collision is caught, so the mechanism -// is live. The WR/DC half is a compile-time-visible guard in the i80 driver.) +// is live. The WR/DC half is a compile-time-visible guard in the i80 backend.) TEST_CASE("shift register: driver refuses a latch that collides with a data lane") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; // Latch on data pin 2 β†’ the lane would carry the latch waveform instead of pixels. - wire(d, src, corr, 8 * 256, "1,2,3", /*shiftOn=*/true, /*latch=*/2); - CHECK(d.severity() == MockShiftDriver::Severity::Error); + wire(d, peripheral, src, corr, 8 * 256, "1,2,3", /*shiftOn=*/true, /*latch=*/2); + CHECK(d.severity() == mm::MoonModule::Severity::Error); CHECK(d.laneCount() == 0); } @@ -286,12 +308,14 @@ TEST_CASE("shift register: the loopback test frame is 8x the direct-mode frame") mm::Correction corr; MockShiftDriver direct; + MockPeripheral peripheralDirect; mm::Buffer srcDirect; - wire(direct, srcDirect, corr, 8 * 64, "1,2,3,4,5,6,7,8", /*shiftOn=*/false, /*latch=*/-1); + wire(direct, peripheralDirect, srcDirect, corr, 8 * 64, "1,2,3,4,5,6,7,8", /*shiftOn=*/false, /*latch=*/-1); MockShiftDriver shifted; + MockPeripheral peripheralShifted; mm::Buffer srcShifted; - wire(shifted, srcShifted, corr, 8 * 64, "1", /*shiftOn=*/true, /*latch=*/2); + wire(shifted, peripheralShifted, srcShifted, corr, 8 * 64, "1", /*shiftOn=*/true, /*latch=*/2); // Same strands, same length; the shift frame pays 8 bus words per slot instead of 1. frameBytes() // is the operational frame, which the loopback's per-light sizing mirrors (both scale by @@ -303,9 +327,10 @@ TEST_CASE("shift register: the loopback test frame is 8x the direct-mode frame") // reconfigure cleanly each time, never wedge or leave stale lane state behind. TEST_CASE("shift register: toggling the expander live reconfigures cleanly") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/false, /*latch=*/-1); + wire(d, peripheral, src, corr, 8 * 256, "1,2,3,4", /*shiftOn=*/false, /*latch=*/-1); CHECK(d.laneCount() == 4); const size_t directFrame = d.frameBytes(); @@ -321,7 +346,7 @@ TEST_CASE("shift register: toggling the expander live reconfigures cleanly") { d.applyState(); CHECK(d.laneCount() == 4); CHECK(d.frameBytes() == directFrame); - CHECK(d.severity() != MockShiftDriver::Severity::Error); + CHECK(d.severity() != mm::MoonModule::Severity::Error); } // =========================================================================== @@ -346,19 +371,20 @@ TEST_CASE("shift register: toggling the expander live reconfigures cleanly") { // inside a timing-out wait. It must stay responsive, and it must not corrupt the in-flight buffer. TEST_CASE("shift register: a transfer that never completes does not wedge the driver") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(d, peripheral, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); REQUIRE(d.laneCount() == 16); - d.waitTimesOut = true; // the DMA never signals done β€” exactly the bench failure + peripheral.waitTimesOut = true; // the DMA never signals done β€” exactly the bench failure // Tick repeatedly. The driver must keep running (no hang, no crash) and must NOT report success. for (int i = 0; i < 5; i++) d.tick(); // It must still be alive and configured β€” degraded, not dead. CHECK(d.laneCount() == 16); - CHECK(d.severity() != MockShiftDriver::Severity::Error); + CHECK(d.severity() != mm::MoonModule::Severity::Error); } // The buffer-safety invariant the timeout exists to protect: while a transfer may still be reading a @@ -366,18 +392,19 @@ TEST_CASE("shift register: a transfer that never completes does not wedge the dr // frame and half of the next on the wire β€” the "scattered random pixels" seen on the bench. TEST_CASE("shift register: a timed-out transfer never gets its buffer re-encoded") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(d, peripheral, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); - d.waitTimesOut = true; + peripheral.waitTimesOut = true; d.tick(); // starts a transfer that will never complete - const size_t transmitsAfterFirst = d.transmitCount(); + const size_t transmitsAfterFirst = peripheral.transmitCount(); d.tick(); // must NOT transmit again over the live buffer d.tick(); - CHECK(d.transmitCount() == transmitsAfterFirst); // no new transfer while the old one is stuck + CHECK(peripheral.transmitCount() == transmitsAfterFirst); // no new transfer while the old one is stuck } // **The robustness rule: a broken bus must not cost the user the DEVICE.** Every dead transfer is a @@ -390,42 +417,44 @@ TEST_CASE("shift register: a timed-out transfer never gets its buffer re-encoded // it. Output idle, device alive β€” never the other way round. TEST_CASE("a persistently dead bus is given up on, so it cannot starve the device") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(d, peripheral, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); - d.waitTimesOut = true; // the DMA never signals done, every frame, forever + peripheral.waitTimesOut = true; // the DMA never signals done, every frame, forever for (int i = 0; i < 40; i++) d.tick(); // It gave up: the failure is REPORTED (the user can see why the LEDs are dark)... - CHECK(d.severity() == MockShiftDriver::Severity::Error); + CHECK(d.severity() == mm::MoonModule::Severity::Error); // ...and it stopped spending the render thread on a bus that will never deliver. The exact count // doesn't matter; what matters is that it is BOUNDED β€” it did not keep trying for all 40 ticks. - CHECK(d.transmitCount() < 40u); + CHECK(peripheral.transmitCount() < 40u); } // Giving up must not be permanent: the user fixes the setting that broke the bus, the driver rebuilds, // and the LEDs come back β€” no reboot (the live-reconfiguration rule). TEST_CASE("a given-up driver recovers when the bus is fixed") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(d, peripheral, src, corr, 16 * 256, "1,2", /*shiftOn=*/true, /*latch=*/3); - d.waitTimesOut = true; + peripheral.waitTimesOut = true; for (int i = 0; i < 40; i++) d.tick(); - REQUIRE(d.severity() == MockShiftDriver::Severity::Error); // gave up - const size_t transmitsWhileDead = d.transmitCount(); + REQUIRE(d.severity() == mm::MoonModule::Severity::Error); // gave up + const size_t transmitsWhileDead = peripheral.transmitCount(); // The user fixes the config: the bus is rebuilt, and now transfers complete. - d.waitTimesOut = false; + peripheral.waitTimesOut = false; d.applyState(); // prepare -> reinit: a fresh bus deserves a clean slate for (int i = 0; i < 5; i++) d.tick(); - CHECK(d.transmitCount() > transmitsWhileDead); // transmitting again - CHECK(d.severity() != MockShiftDriver::Severity::Error); // and the error is cleared + CHECK(peripheral.transmitCount() > transmitsWhileDead); // transmitting again + CHECK(d.severity() != mm::MoonModule::Severity::Error); // and the error is cleared } // **THE INVARIANT THE STREAMING RING RESTS ON.** The ring never materialises the big encoded frame: @@ -440,8 +469,9 @@ TEST_CASE("a given-up driver recovers when the bus is fixed") { TEST_CASE("streaming ring: a sliced encode is byte-identical to the whole-frame encode") { mm::Correction corr; MockShiftDriver whole; + MockPeripheral peripheral; mm::Buffer srcWhole; - wire(whole, srcWhole, corr, 16 * 32, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(whole, peripheral, srcWhole, corr, 16 * 32, "1,2", /*shiftOn=*/true, /*latch=*/3); REQUIRE(whole.maxLaneLights() == 32); // Fill the source with a dense, varied pattern β€” a sparse/zero buffer would hide a slicing bug. @@ -489,7 +519,8 @@ TEST_CASE("bus pin list is padded to the full bus width, in both modes") { SUBCASE("direct mode: 3 pins β†’ 8 lanes, 5 parked on the clock pin") { MockShiftDriver d; - wire(d, src, corr, 64, "1,2,4", /*shiftOn=*/false, /*latch=*/-1); + MockPeripheral peripheral; + wire(d, peripheral, src, corr, 64, "1,2,4", /*shiftOn=*/false, /*latch=*/-1); REQUIRE(d.busPinCountForTest() == 8); // the BUS width, not the pin count const uint16_t* list = d.busPinListForTest(); @@ -501,7 +532,8 @@ TEST_CASE("bus pin list is padded to the full bus width, in both modes") { SUBCASE("shift mode: 2 pins + latch β†’ 8 lanes, the rest parked") { MockShiftDriver d; - wire(d, src, corr, 64, "1,2", /*shiftOn=*/true, /*latch=*/7); + MockPeripheral peripheral; + wire(d, peripheral, src, corr, 64, "1,2", /*shiftOn=*/true, /*latch=*/7); REQUIRE(d.busPinCountForTest() == 8); const uint16_t* list = d.busPinListForTest(); @@ -529,9 +561,10 @@ TEST_CASE("bus pin list is padded to the full bus width, in both modes") { // tripping the out-of-memory path. TEST_CASE("shift register: the loopback frame has room for its closing latch word") { MockShiftDriver d; + MockPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 16 * 8, "1,2", /*shiftOn=*/true, /*latch=*/3); + wire(d, peripheral, src, corr, 16 * 8, "1,2", /*shiftOn=*/true, /*latch=*/3); REQUIRE(d.laneCount() == 16); // 2 pins x 8 outputs d.loopbackTest = true; @@ -540,6 +573,30 @@ TEST_CASE("shift register: the loopback frame has room for its closing latch wor d.tick(); // builds + "transmits" the test frame (mock bus) // It must not have fallen into the out-of-memory branch, and must still be a live driver. - CHECK(d.severity() != MockShiftDriver::Severity::Error); + CHECK(d.severity() != mm::MoonModule::Severity::Error); CHECK(d.laneCount() == 16); } + +// A peripheral that CANNOT host the '595 (Parlio's transfer cap, or the classic i80 = I2S). Its +// pinExpander control is hidden, so a user can't turn a stray `pinExpander=true` back off β€” the driver +// must therefore auto-clear it and run direct, not wedge in an unfixable error status. +struct NoExpanderPeripheral : MockPeripheral { + bool supportsPinExpander() const override { return false; } +}; + +// The robustness case behind the 2026-07-23 consolidation bug: switching to (or loading a saved config +// on) a peripheral that can't host the expander must SILENTLY drop pinExpander to direct mode β€” because +// the pinExpander toggle is hidden there, an error status would be unfixable from the UI. Pins: the +// driver clears pinExpander, drives direct, and reports no error. +TEST_CASE("pinExpander auto-clears on a peripheral that can't host it (no unfixable error)") { + NoExpanderPeripheral peripheral; // declared before the driver β€” borrowed, must outlive it + MockShiftDriver d; + mm::Buffer src; + mm::Correction corr; + // Ask for the expander (as a stale saved config or a post-switch state would): 3 data pins, latch set. + wire(d, peripheral, src, corr, 3 * 8, "1,2,3", /*shiftOn=*/true, /*latch=*/7); + + CHECK_FALSE(d.pinExpander); // silently dropped to direct + CHECK(d.severity() != mm::MoonModule::Severity::Error); // NOT a dead-end error + CHECK(d.laneCount() == 3); // 3 pins β†’ 3 direct lanes (not Γ—8) +} diff --git a/test/unit/light/unit_ParallelLedDriver_ring.cpp b/test/unit/light/unit_ParallelLedDriver_ring.cpp index 22762120..8649b384 100644 --- a/test/unit/light/unit_ParallelLedDriver_ring.cpp +++ b/test/unit/light/unit_ParallelLedDriver_ring.cpp @@ -44,60 +44,55 @@ using mm::nrOfLightsType; constexpr uint8_t kMockRingBufs = 4; constexpr uint32_t kMockRingRows = 16; -class MockRingDriver : public mm::ParallelLedDriver { +class MockRingDriver; // forward decl β€” the peripheral's ring hooks call back into the owner's encode + +// The ring-capable backend: a memory-only LedPeripheral (same shape as unit_ParallelLedDriver_doublebuffer's +// MockPeripheral) PLUS the ring hooks (busInitRing/busTransmitRing/busIsRing/wantsRing), which is what +// MoonI80Peripheral is on real hardware. Holds the ring buffer pool and geometry; the actual per-slice +// encode is the OWNER's (ParallelLedDriver::encodeRows), reached through owner_ exactly as +// MoonI80Peripheral::ringEncodeTrampoline does. +class MockRingPeripheral : public mm::LedPeripheral { public: - static constexpr uint8_t lanesAvailable() { return 8; } // 8 data lines (an 8-bit bus) - static constexpr bool kPowerOfTwoBus = true; - static constexpr bool kLoopbackFullWidth = false; - static constexpr bool kSupportsPinExpander = true; - static constexpr const char* kInitFailMsg = "mock init failed"; - - void addBusControls() {} - // A ring-capable backend adds its ring cluster here (the base's default addRingControls is a no-op for + uint8_t lanesAvailable() const override { return 8; } // 8 data lines (an 8-bit bus) + bool powerOfTwoBus() const override { return true; } + bool loopbackFullWidth() const override { return false; } + bool supportsPinExpander() const override { return true; } + const char* initFailMsg() const override { return "mock init failed"; } + mm::LedHwBlock hwBlock() const override { return mm::LedHwBlock::None; } // mock drives no real block + + void addBusControls(mm::ControlList&) override {} + // A ring-capable backend adds its ring cluster here (the default addRingControls is a no-op for // whole-frame-only backends). Mirror the real driver: the source-snapshot knob under the path, gated // on wantsRing() β€” this mock's controllable wantRing_ drives the visibility the hide test checks. - void addRingControls() { - controls_.addBool("ringSnapshot", ringSnapshot); - controls_.setHidden(controls_.count() - 1, !wantsRing()); + void addRingControls(mm::ControlList& controls) override { + controls.addBool("ringSnapshot", owner_->ringSnapshotRef()); + controls.setHidden(controls.count() - 1, !wantsRing()); } - bool busControlTriggersBuild(const char*) const { return false; } - void recordBusPins() {} - bool extraBusPinsCurrent() const { return true; } - const char* validateBusPins(const uint16_t*, uint8_t) const { return nullptr; } - const char* validateBusFatal() const { return nullptr; } - uint16_t clockPinForBus() const { return 99; } + bool busControlTriggersBuild(const char*) const override { return false; } + void recordBusPins() override {} + bool extraBusPinsCurrent() const override { return true; } + const char* validateBusPins(const uint16_t*, uint8_t) const override { return nullptr; } + const char* validateBusFatal() const override { return nullptr; } + uint16_t clockPinForBus() const override { return 99; } // --- whole-frame bus (used to produce the reference frame the ring output is compared against) --- - bool busInit(size_t frameBytes, bool) { cap_ = frameBytes; buf_.assign(frameBytes, 0); return true; } - uint8_t* busBuffer(uint8_t i) { return (i == 0 && !buf_.empty()) ? buf_.data() : nullptr; } - size_t busCapacity() const { return cap_; } - bool busTransmit(uint8_t, size_t) { return true; } - bool busWait(uint8_t, uint32_t) { return true; } - uint32_t busLastTransmitUs() const { return 0; } - void busDeinit() { cap_ = 0; buf_.clear(); ringActive_ = false; } - mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) { return {}; } - - // The whole-frame reference: prefill constants + encode the entire frame in one call (what the ring - // must reproduce, slice by slice). - template - void encodeWholeForTest(uint8_t outCh, uint8_t* dst) { - this->template encodeRows(outCh, dst, 0, 0, /*closeFrame=*/true); - } - template - void prefillShiftFrameForTest(uint8_t outCh, uint8_t* dst) { - this->template prefillShiftFrame(outCh, dst); - } - // Which bus bit the '595's latch rides (the ragged darkness test masks it out of its bit check). - uint8_t latchBitForTest() const { return latchBit_; } - - // --- ring hooks (the seam the platform drives). The mock stores the trampoline + geometry and hands - // out plain-memory buffers; driveRingFrame() below replays the platform's prime+refill order. --- - bool wantsRing() const { return wantRing_; } + bool busInit(size_t frameBytes, bool) override { cap_ = frameBytes; buf_.assign(frameBytes, 0); return true; } + uint8_t* busBuffer(uint8_t i) override { return (i == 0 && !buf_.empty()) ? buf_.data() : nullptr; } + size_t busCapacity() const override { return cap_; } + bool busTransmit(uint8_t, size_t) override { return true; } + bool busWait(uint8_t, uint32_t) override { return true; } + uint32_t busLastTransmitUs() const override { return 0; } + void busDeinit() override { cap_ = 0; buf_.clear(); ringActive_ = false; } + mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) override { return {}; } + + // --- ring hooks (the seam the platform drives). The mock stores the geometry and hands out + // plain-memory buffers; driveRingFrame() below replays the platform's prime+refill order. --- + bool wantsRing() const override { return wantRing_; } void setWantRing(bool w) { wantRing_ = w; } // Buffers are ROWS-ONLY, exactly as the platform allocates them: the WS2812 reset comes from stopping // the peripheral, never from a pad inside a circulating buffer. Sizing these rows+pad here would let a // pad-writing bug pass the tests and overrun on hardware. - bool busInitRing(size_t rowBytes, uint32_t totalRows) { + bool busInitRing(size_t rowBytes, uint32_t totalRows) override { ringRowBytes_ = rowBytes; ringTotalRows_ = totalRows; ringActive_ = true; @@ -108,8 +103,8 @@ class MockRingDriver : public mm::ParallelLedDriver { for (auto& f : needsPrefill_) f = true; return true; } - bool busIsRing() const { return ringActive_; } - bool busTransmitRing() { return true; } // the wire itself is the platform's; the encode is what we test + bool busIsRing() const override { return ringActive_; } + bool busTransmitRing() override { return true; } // the wire itself is the platform's; the encode is what we test // Replay one frame through the ring exactly as the platform does: prime the first min(N, needed) // buffers, then refill in ring order until the slice that reaches totalRows. Returns the frame @@ -151,8 +146,7 @@ class MockRingDriver : public mm::ParallelLedDriver { // and re-flag the buffer after a tail memset (its constants are gone for the NEXT use). const bool needsPrefill = needsPrefill_[slot]; needsPrefill_[slot] = false; - MockRingDriver::ringEncodeTrampolineHost(this, ring_[slot].data(), row, count, last, - needsPrefill); + ringEncodeTrampolineHost(ring_[slot].data(), row, count, last, needsPrefill); if (shortSlice) needsPrefill_[slot] = true; // Reassemble the row region in DMA order. assembled.insert(assembled.end(), ring_[slot].begin(), @@ -204,29 +198,20 @@ class MockRingDriver : public mm::ParallelLedDriver { return (ringTotalRows_ + kMockRingRows - 1) / kMockRingRows; } - // The trampoline the real driver registers is MoonLedDriver::ringEncodeTrampoline; the mock - // reproduces its body (recover `this`, branch on bus width, call encodeRows) so the host drives the - // identical encode the seam does on device. `closeFrame` is ALWAYS false to the encoder: the platform - // (encodeRingSlice) never appends a latch pad to a rows-only ring buffer β€” the WS2812 reset comes from - // stopping the peripheral, not from a pad inside a circulating buffer. `needsPrefill` mirrors the real - // trampoline's prefill-skip: constants are laid only when the platform says the buffer's are gone (or - // the lanes are ragged), and the byte-compare tests prove a data-only refill of a recycled buffer is - // identical to a full one. - static void ringEncodeTrampolineHost(void* user, uint8_t* dst, uint32_t firstRow, - uint32_t count, bool /*last*/, bool needsPrefill) { - auto* self = static_cast(user); - const uint8_t outCh = self->correction_.outChannels; - const auto first = static_cast(firstRow); - const auto cnt = static_cast(count); - const bool prefill = self->pinExpanderMode() && (needsPrefill || !self->uniformLaneCounts()); - if (self->slotBytes() == 1) { - if (prefill) self->template prefillShiftRows(outCh, dst, first, cnt); - self->template encodeRows(outCh, dst, first, cnt, /*closeFrame=*/false); - } else { - if (prefill) self->template prefillShiftRows(outCh, dst, first, cnt); - self->template encodeRows(outCh, dst, first, cnt, /*closeFrame=*/false); - } - } + // The trampoline the real driver registers is MoonI80Peripheral::ringEncodeTrampoline; the mock + // reproduces its body (recover the OWNER β€” this backend's attach()'d ParallelLedDriver β€” branch on + // bus width, call encodeRows) so the host drives the identical encode the seam does on device. + // `closeFrame` is ALWAYS false to the encoder: the platform (encodeRingSlice) never appends a latch + // pad to a rows-only ring buffer β€” the WS2812 reset comes from stopping the peripheral, not from a + // pad inside a circulating buffer. `needsPrefill` mirrors the real trampoline's prefill-skip: + // constants are laid only when the platform says the buffer's are gone (or the lanes are ragged), + // and the byte-compare tests prove a data-only refill of a recycled buffer is identical to a full one. + // + // Needs the owner's PROTECTED encodeRows/prefillShiftRows, which only a ParallelLedDriver subclass + // can reach β€” MockRingDriver (below) exposes them via a couple of one-line forwarders, mirroring how + // MoonI80Peripheral's real trampoline calls back through `owner_`. + void ringEncodeTrampolineHost(uint8_t* dst, uint32_t firstRow, uint32_t count, bool /*last*/, + bool needsPrefill); size_t rowBytesForTest() const { return ringRowBytes_; } @@ -276,7 +261,7 @@ class MockRingDriver : public mm::ParallelLedDriver { const bool last = (firstRow + count >= ringTotalRows_); const bool needsPrefill = poolNeedsPrefill[slot]; poolNeedsPrefill[slot] = false; - ringEncodeTrampolineHost(this, pool[slot].data(), firstRow, count, last, needsPrefill); + ringEncodeTrampolineHost(pool[slot].data(), firstRow, count, last, needsPrefill); if (shortSlice) poolNeedsPrefill[slot] = true; // the tail memset erased those rows' constants }; uint32_t refilledRow = 0; @@ -326,6 +311,57 @@ class MockRingDriver : public mm::ParallelLedDriver { return out; } +private: + std::vector buf_; + size_t cap_ = 0; + std::vector ring_[kMockRingBufs]; + bool needsPrefill_[kMockRingBufs] = {}; // the platform's bufNeedsPrefill lifecycle, mirrored + size_t ringRowBytes_ = 0; + uint32_t ringTotalRows_ = 0; + bool ringActive_ = false; + bool wantRing_ = false; + int32_t lastSlot_ = -1; +}; + +// A tiny ParallelLedDriver subclass that exposes the protected lane/encode/snapshot internals the ring +// tests need (encodeRows, prefillShiftRows/Frame, latchBit_'s bit position, the ensureSnapshotCap / +// snapshotSourceForRing / copyRange snapshot machinery) without widening the production class's public +// surface β€” same pattern as unit_ParallelLedDriver_pinexpander.cpp's Expose-style mocks. Everything else +// the tests use (laneCount, maxLaneLights, frameBytes, pins, ledsPerPin, pinExpander, latchPin, +// defineControls, setSourceBuffer, correctionForTest, applyState, severity, outputsPerPin, +// setWindow, tick) is already public on ParallelLedDriver itself. +class MockRingDriver : public mm::ParallelLedDriver { +public: + // The whole-frame reference: prefill constants + encode the entire frame in one call (what the ring + // must reproduce, slice by slice). + template + void encodeWholeForTest(uint8_t outCh, uint8_t* dst) { + this->template encodeRows(outCh, dst, 0, 0, /*closeFrame=*/true); + } + template + void prefillShiftFrameForTest(uint8_t outCh, uint8_t* dst) { + this->template prefillShiftFrame(outCh, dst); + } + // Which bus bit the '595's latch rides (the ragged darkness test masks it out of its bit check). + uint8_t latchBitForTest() const { return this->latchBit(); } + + // The trampoline body itself (recover outCh/prefill-gate from this driver, branch on bus width, call + // encodeRows) β€” MockRingPeripheral::ringEncodeTrampolineHost forwards here, mirroring how + // MoonI80Peripheral's real trampoline recovers `owner_` and calls straight into it. + void encodeSliceForTest(uint8_t* dst, uint32_t firstRow, uint32_t count, bool needsPrefill) { + const uint8_t outCh = this->correction().outChannels; + const auto first = static_cast(firstRow); + const auto cnt = static_cast(count); + const bool prefill = this->pinExpanderMode() && (needsPrefill || !this->uniformLaneCounts()); + if (this->slotBytes() == 1) { + if (prefill) this->template prefillShiftRows(outCh, dst, first, cnt); + this->template encodeRows(outCh, dst, first, cnt, /*closeFrame=*/false); + } else { + if (prefill) this->template prefillShiftRows(outCh, dst, first, cnt); + this->template encodeRows(outCh, dst, first, cnt, /*closeFrame=*/false); + } + } + // Freeze the current source into the driver-owned snapshot and route the ring encode at it β€” the same // call tickRing makes before kicking a frame. After this, encodeRows reads the snapshot, so mutating // the live source (a resize / repaint on the render thread) can't tear or UAF the in-flight frame. @@ -350,19 +386,15 @@ class MockRingDriver : public mm::ParallelLedDriver { static mm::nrOfLightsType snapHalfForTest(mm::nrOfLightsType n, size_t chStride) { return snapLineAlignedHalf(n, chStride); } - -private: - std::vector buf_; - size_t cap_ = 0; - std::vector ring_[kMockRingBufs]; - bool needsPrefill_[kMockRingBufs] = {}; // the platform's bufNeedsPrefill lifecycle, mirrored - size_t ringRowBytes_ = 0; - uint32_t ringTotalRows_ = 0; - bool ringActive_ = false; - bool wantRing_ = false; - int32_t lastSlot_ = -1; }; +// Out-of-line: needs MockRingDriver's full definition (encodeSliceForTest), so it's defined after the +// class rather than inline in MockRingPeripheral. +inline void MockRingPeripheral::ringEncodeTrampolineHost(uint8_t* dst, uint32_t firstRow, uint32_t count, + bool /*last*/, bool needsPrefill) { + static_cast(owner_)->encodeSliceForTest(dst, firstRow, count, needsPrefill); +} + // Bring the mock up on `lights` lights, shift mode (8 pins Γ— 8 = 64 strands... capped; use fewer pins), // with a correction so outChannels is known. Mirrors the shiftregister test's setup. // @@ -370,8 +402,9 @@ class MockRingDriver : public mm::ParallelLedDriver { // "" leaves every strand equal at `lights`. Pass an explicit list for a RAGGED frame, where strands have // different lengths (an end user's mix of strips and panels), which is what makes the active mask change // mid-frame rather than being one constant. -void wireShift(MockRingDriver& d, mm::Buffer& src, mm::Correction& corr, nrOfLightsType lights, - const char* pins, const char* ledsPerPin = "") { +void wireShift(MockRingDriver& d, MockRingPeripheral& peripheral, mm::Buffer& src, mm::Correction& corr, + nrOfLightsType lights, const char* pins, const char* ledsPerPin = "") { + d.setPeripheralForTest(&peripheral); std::strcpy(d.pins, pins); std::strcpy(d.ledsPerPin, ledsPerPin); d.pinExpander = true; @@ -395,10 +428,11 @@ void wireShift(MockRingDriver& d, mm::Buffer& src, mm::Correction& corr, nrOfLig // writes to dst+0 for any firstRow, so if the tiling is right the reassembled buffer == the frame. TEST_CASE("MoonI80 ring: sliced encode tiles into a byte-identical whole frame") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; // 200 lights/strand > 16 rows/buffer Γ— 4 buffers = 64, so this needs real refills (not fits-in-ring). - wireShift(d, src, corr, 200, "1,2"); // 2 pins Γ— 8 = 16 strands, 200 lights each + wireShift(d, peripheral, src, corr, 200, "1,2"); // 2 pins Γ— 8 = 16 strands, 200 lights each // Paint the source so every row differs (a tiling bug that repeats a slice would then be visible). uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { @@ -413,16 +447,16 @@ TEST_CASE("MoonI80 ring: sliced encode tiles into a byte-identical whole frame") // Reference: one whole-frame encode (2 pins β†’ 8-bit bus β†’ uint8 slots). encodeRows in shift mode // writes only data words, so prefill the whole buffer's constants first β€” same as reinit does. - d.busInit(d.frameBytes(), false); - d.prefillShiftFrameForTest(outCh, d.busBuffer(0)); - d.encodeWholeForTest(outCh, d.busBuffer(0)); - std::vector whole(d.busBuffer(0), d.busBuffer(0) + rowRegion); - d.busDeinit(); + peripheral.busInit(d.frameBytes(), false); + d.prefillShiftFrameForTest(outCh, peripheral.busBuffer(0)); + d.encodeWholeForTest(outCh, peripheral.busBuffer(0)); + std::vector whole(peripheral.busBuffer(0), peripheral.busBuffer(0) + rowRegion); + peripheral.busDeinit(); // Ring: drive the frame slice by slice, reassemble the row region. - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - std::vector assembled = d.driveRingFrame(); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + std::vector assembled = peripheral.driveRingFrame(); REQUIRE(assembled.size() == whole.size()); CHECK(std::memcmp(assembled.data(), whole.data(), whole.size()) == 0); @@ -433,16 +467,17 @@ TEST_CASE("MoonI80 ring: sliced encode tiles into a byte-identical whole frame") // buffer), so a slice that wrote a latch word past its rows would overrun the allocation on hardware. TEST_CASE("MoonI80 ring: no slice writes past its rows (buffers are rows-only)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); + wireShift(d, peripheral, src, corr, 200, "1,2"); const uint8_t outCh = corr.outChannels; - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - d.driveRingFrame(); - CHECK(d.noSliceWritesPad()); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + peripheral.driveRingFrame(); + CHECK(peripheral.noSliceWritesPad()); } // 3. RECYCLED == FRESH β€” a second frame through the SAME (recycled, not zeroed) ring buffers produces @@ -450,9 +485,10 @@ TEST_CASE("MoonI80 ring: no slice writes past its rows (buffers are rows-only)") // single-frame test cannot see β€” the failure mode unique to a recycled ring. TEST_CASE("MoonI80 ring: a recycled buffer produces the same bytes as a fresh one") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); + wireShift(d, peripheral, src, corr, 200, "1,2"); uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { s[i * 3 + 0] = static_cast(i * 5 + 3); @@ -461,12 +497,12 @@ TEST_CASE("MoonI80 ring: a recycled buffer produces the same bytes as a fresh on } const uint8_t outCh = corr.outChannels; - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - std::vector first = d.driveRingFrame(); - std::vector second = d.driveRingFrame(); // same buffers, recycled β€” not re-init'd + std::vector first = peripheral.driveRingFrame(); + std::vector second = peripheral.driveRingFrame(); // same buffers, recycled β€” not re-init'd REQUIRE(first.size() == second.size()); CHECK(std::memcmp(first.data(), second.data(), first.size()) == 0); } @@ -477,9 +513,10 @@ TEST_CASE("MoonI80 ring: a recycled buffer produces the same bytes as a fresh on // 8 buffers (reuse) AND lastRows=8 (short) β€” exactly the case 128/192/256 (all Γ—16) never hit. TEST_CASE("MoonI80 ring: a short last slice in a reused buffer has a clean pad (no stale ghost rows)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); // 200 lights/strand: 13 slices, last slice = 8 rows + wireShift(d, peripheral, src, corr, 200, "1,2"); // 200 lights/strand: 13 slices, last slice = 8 rows uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { // dense non-zero source so a stale row WOULD show s[i * 3 + 0] = static_cast(i * 9 + 1); @@ -487,14 +524,14 @@ TEST_CASE("MoonI80 ring: a short last slice in a reused buffer has a clean pad ( s[i * 3 + 2] = static_cast(i * 19 + 2); } const uint8_t outCh = corr.outChannels; - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); // Drive TWICE so the last-slice buffer is genuinely recycled (held an earlier frame's full slice). - d.driveRingFrame(); - d.driveRingFrame(); - CHECK(d.lastSliceStalePadBytes() == 0); // tail past the short slice's rows is zero β€” no ghost rows + peripheral.driveRingFrame(); + peripheral.driveRingFrame(); + CHECK(peripheral.lastSliceStalePadBytes() == 0); // tail past the short slice's rows is zero β€” no ghost rows } // 5. SOURCE SNAPSHOT β€” the ring encodes off the render thread across the ~6 ms wire, so it must read a @@ -505,9 +542,10 @@ TEST_CASE("MoonI80 ring: a short last slice in a reused buffer has a clean pad ( // mid-wire from tearing or reading freed memory.) TEST_CASE("MoonI80 ring: the encode reads a per-frame snapshot, not the live source") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); + wireShift(d, peripheral, src, corr, 200, "1,2"); uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { s[i * 3 + 0] = static_cast(i * 5 + 3); @@ -515,16 +553,16 @@ TEST_CASE("MoonI80 ring: the encode reads a per-frame snapshot, not the live sou s[i * 3 + 2] = static_cast(i * 17 + 7); } const uint8_t outCh = corr.outChannels; - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); // Freeze the source, then SCRIBBLE all over the live buffer as the render thread would between kick // and wire-completion. The snapshot must shield the encode from it. REQUIRE(d.snapshotForTest()); - std::vector fromSnapshot = d.driveRingFrame(); + std::vector fromSnapshot = peripheral.driveRingFrame(); std::memset(src.data(), 0xA5, static_cast(src.count()) * src.channelsPerLight()); - std::vector afterMutation = d.driveRingFrame(); // still on the same snapshot + std::vector afterMutation = peripheral.driveRingFrame(); // still on the same snapshot REQUIRE(fromSnapshot.size() == afterMutation.size()); CHECK(std::memcmp(fromSnapshot.data(), afterMutation.data(), fromSnapshot.size()) == 0); @@ -533,7 +571,7 @@ TEST_CASE("MoonI80 ring: the encode reads a per-frame snapshot, not the live sou // scribbled buffer and confirm the encode follows it (a uniform 0xA5 source β†’ uniform encoded bytes, // clearly different from the structured pattern above). REQUIRE(d.snapshotForTest()); - std::vector fromMutated = d.driveRingFrame(); + std::vector fromMutated = peripheral.driveRingFrame(); REQUIRE(fromMutated.size() == fromSnapshot.size()); CHECK(std::memcmp(fromMutated.data(), fromSnapshot.data(), fromMutated.size()) != 0); } @@ -546,9 +584,10 @@ TEST_CASE("MoonI80 ring: the encode reads a per-frame snapshot, not the live sou TEST_CASE("MoonI80 ring: the windowed snapshot bias reads this driver's slice, not from light 0") { // Reference: a driver whose window starts at 0 over a buffer sized for exactly its strands. MockRingDriver ref; + MockRingPeripheral peripheralRef; mm::Buffer refSrc; mm::Correction corr; - wireShift(ref, refSrc, corr, 64, "1,2"); // 16 strands Γ— 64 lights = 1024-light window + wireShift(ref, peripheralRef, refSrc, corr, 64, "1,2"); // 16 strands Γ— 64 lights = 1024-light window const nrOfLightsType winLights = refSrc.count(); // the whole buffer IS the window here auto paint = [](uint8_t* p, nrOfLightsType n, nrOfLightsType base) { for (nrOfLightsType i = 0; i < n; i++) { @@ -558,27 +597,28 @@ TEST_CASE("MoonI80 ring: the windowed snapshot bias reads this driver's slice, n } }; paint(refSrc.data(), winLights, /*base=*/64); // same pixel VALUES the windowed driver will see - ref.setWantRing(true); + peripheralRef.setWantRing(true); const size_t rowBytes = static_cast(corr.outChannels) * 24 * 1 * ref.outputsPerPin(); - REQUIRE(ref.busInitRing(rowBytes, static_cast(ref.maxLaneLights()))); + REQUIRE(peripheralRef.busInitRing(rowBytes, static_cast(ref.maxLaneLights()))); REQUIRE(ref.snapshotForTest()); - std::vector refFrame = ref.driveRingFrame(); + std::vector refFrame = peripheralRef.driveRingFrame(); // Windowed: a bigger buffer, the driver's window offset to start=64, painted so window pixel k equals // reference pixel k. The bias must make the snapshot read [64, 64+winLights), i.e. the SAME values. MockRingDriver win; + MockRingPeripheral peripheralWin; mm::Buffer winSrc; mm::Correction corr2; - wireShift(win, winSrc, corr2, 64, "1,2"); // same geometry... + wireShift(win, peripheralWin, winSrc, corr2, 64, "1,2"); // same geometry... // ...but re-allocate the source with a 64-light lead-in the window skips, and re-apply the window. REQUIRE(winSrc.allocate(winLights + 64, 3) == true); paint(winSrc.data(), winLights + 64, /*base=*/0); // pixel 64.. == refSrc pixel 0.. (base 64) win.setWindow(64, winLights); win.applyState(); - win.setWantRing(true); - REQUIRE(win.busInitRing(rowBytes, static_cast(win.maxLaneLights()))); + peripheralWin.setWantRing(true); + REQUIRE(peripheralWin.busInitRing(rowBytes, static_cast(win.maxLaneLights()))); REQUIRE(win.snapshotForTest()); - std::vector winFrame = win.driveRingFrame(); + std::vector winFrame = peripheralWin.driveRingFrame(); REQUIRE(refFrame.size() == winFrame.size()); CHECK(std::memcmp(refFrame.data(), winFrame.data(), refFrame.size()) == 0); @@ -596,20 +636,21 @@ TEST_CASE("MoonI80 ring: the windowed snapshot bias reads this driver's slice, n // is the no-reuse stopgap's guarantee; it is what renders clean at ≀240 lights/strand (kRingBufs=16). TEST_CASE("MoonI80 ring: no-reuse frame clocks a clean LOW tail and stops deterministically") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 176, "1,2"); // 176 lights = 11 slices; model 16 buffers β†’ NO reuse + wireShift(d, peripheral, src, corr, 176, "1,2"); // 176 lights = 11 slices; model 16 buffers β†’ NO reuse uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { // dense non-zero so a dirty tail WOULD show s[i * 3 + 0] = static_cast(i * 7 + 1); s[i * 3 + 1] = static_cast(i * 13 + 5); s[i * 3 + 2] = static_cast(i * 29 + 2); } - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(corr.outChannels) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - auto f = d.driveRingFrameWithTermination(/*bufs=*/16, /*kTailBufs=*/1); + auto f = peripheral.driveRingFrameWithTermination(/*bufs=*/16, /*kTailBufs=*/1); const uint32_t nSlices = (176 + 15) / 16; // 11 CHECK(f.drainsToStop == nSlices + 1); // stops one buffer LATE (the tail), not early, not looping forever CHECK(f.tailIsLow); // the buffer(s) past the last real slice clock all-LOW @@ -631,27 +672,28 @@ TEST_CASE("MoonI80 ring: no-reuse frame clocks a clean LOW tail and stops determ // stop timing at the correct sizing is caught here; the equal-case stall is covered in the backlog. TEST_CASE("MoonI80 ring: the no-reuse stopgap clocks a clean tail and stops on the drain counter") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 176, "1,2"); // 11 slices + wireShift(d, peripheral, src, corr, 176, "1,2"); // 11 slices uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { s[i * 3 + 0] = static_cast(i * 7 + 1); s[i * 3 + 1] = static_cast(i * 13 + 5); s[i * 3 + 2] = static_cast(i * 29 + 2); } - d.setWantRing(true); + peripheral.setWantRing(true); const size_t rowBytes = static_cast(corr.outChannels) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); const uint32_t nSlices = (176 + 15) / 16; // 11 // bufs = nSlices + 1 (the correct stopgap sizing, kRingBufs > nSlices): clean LOW tail, stop on the // drain counter one buffer past the last real slice. This is the ≀240-lights/strand no-reuse guarantee. - auto ok = d.driveRingFrameWithTermination(/*bufs=*/static_cast(nSlices + 1), /*kTailBufs=*/1); + auto ok = peripheral.driveRingFrameWithTermination(/*bufs=*/static_cast(nSlices + 1), /*kTailBufs=*/1); CHECK(ok.tailIsLow); CHECK(ok.drainsToStop == nSlices + 1); // A deeper pool (kRingBufs=16 for 11 slices, the shipped stopgap) is equally clean and stops the same. - auto deep = d.driveRingFrameWithTermination(/*bufs=*/16, /*kTailBufs=*/1); + auto deep = peripheral.driveRingFrameWithTermination(/*bufs=*/16, /*kTailBufs=*/1); CHECK(deep.tailIsLow); CHECK(deep.drainsToStop == nSlices + 1); } @@ -673,12 +715,13 @@ TEST_CASE("MoonI80 ring: the no-reuse stopgap clocks a clean tail and stops on t // slice) nor the driver-level ring tests (which are never ragged) reach on their own. TEST_CASE("MoonI80 ring: a ragged frame tiles byte-identically (a strand ending mid-slice)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; // 16 strands (2 pins Γ— 8). Strand 0 runs the full 200; strands 3 and 9 end at 100 and 57 β€” both // INSIDE a 16-row slice (100 = slice 6 row 4; 57 = slice 3 row 9), and 57 is not a multiple of // anything convenient, which is the point. - wireShift(d, src, corr, 200, "1,2", + wireShift(d, peripheral, src, corr, 200, "1,2", "200,200,200,100,200,200,200,200,200,57,200,200,200,200,200,200"); uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { @@ -693,15 +736,15 @@ TEST_CASE("MoonI80 ring: a ragged frame tiles byte-identically (a strand ending // The frame is still as long as the LONGEST strand β€” the short ones just go dark early. REQUIRE(d.maxLaneLights() == 200); - d.busInit(d.frameBytes(), false); - d.prefillShiftFrameForTest(outCh, d.busBuffer(0)); - d.encodeWholeForTest(outCh, d.busBuffer(0)); - std::vector whole(d.busBuffer(0), d.busBuffer(0) + rowRegion); - d.busDeinit(); + peripheral.busInit(d.frameBytes(), false); + d.prefillShiftFrameForTest(outCh, peripheral.busBuffer(0)); + d.encodeWholeForTest(outCh, peripheral.busBuffer(0)); + std::vector whole(peripheral.busBuffer(0), peripheral.busBuffer(0) + rowRegion); + peripheral.busDeinit(); - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - std::vector assembled = d.driveRingFrame(); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + std::vector assembled = peripheral.driveRingFrame(); REQUIRE(assembled.size() == whole.size()); CHECK(std::memcmp(assembled.data(), whole.data(), whole.size()) == 0); @@ -715,9 +758,10 @@ TEST_CASE("MoonI80 ring: a ragged frame tiles byte-identically (a strand ending // cross the recycle boundary repeatedly. TEST_CASE("MoonI80 ring v2: coalesced EOFs (batched refill) are byte-identical to one-per-EOF") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2", ""); // 16 uniform strands, 200 rows: 13 slices over the mock pool + wireShift(d, peripheral, src, corr, 200, "1,2", ""); // 16 uniform strands, 200 rows: 13 slices over the mock pool uint8_t* s = src.data(); for (nrOfLightsType i = 0; i < src.count(); i++) { s[i * 3 + 0] = static_cast(i * 5 + 3); @@ -727,11 +771,11 @@ TEST_CASE("MoonI80 ring v2: coalesced EOFs (batched refill) are byte-identical t const uint8_t outCh = corr.outChannels; const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - std::vector onePerEof = d.driveRingFrame(); // the reference grouping - std::vector coalesced2 = d.driveRingFrameCoalesced(2); // every firing carries 2 drains - std::vector coalesced5 = d.driveRingFrameCoalesced(5); // deep coalescing (a long stall) + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + std::vector onePerEof = peripheral.driveRingFrame(); // the reference grouping + std::vector coalesced2 = peripheral.driveRingFrameCoalesced(2); // every firing carries 2 drains + std::vector coalesced5 = peripheral.driveRingFrameCoalesced(5); // deep coalescing (a long stall) REQUIRE(coalesced2.size() == onePerEof.size()); REQUIRE(coalesced5.size() == onePerEof.size()); @@ -746,10 +790,11 @@ TEST_CASE("MoonI80 ring v2: coalesced EOFs (batched refill) are byte-identical t // frames β€” which now skip the prefill β€” stay byte-identical to the whole-frame encode. TEST_CASE("MoonI80 ring: an EMPTY lane does not break uniformity (prefill-skip stays valid)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; // 15 strands at the full 200, the 16th empty β€” the 3840-lights-on-16-strands wall shape. - wireShift(d, src, corr, 200, "1,2", + wireShift(d, peripheral, src, corr, 200, "1,2", "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,0"); CHECK(d.uniformLaneCounts()); // the gate itself: empty lane ignored uint8_t* s = src.data(); @@ -762,15 +807,15 @@ TEST_CASE("MoonI80 ring: an EMPTY lane does not break uniformity (prefill-skip s const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); const size_t rowRegion = static_cast(d.maxLaneLights()) * rowBytes; - d.busInit(d.frameBytes(), false); - d.prefillShiftFrameForTest(outCh, d.busBuffer(0)); - d.encodeWholeForTest(outCh, d.busBuffer(0)); - std::vector whole(d.busBuffer(0), d.busBuffer(0) + rowRegion); - d.busDeinit(); + peripheral.busInit(d.frameBytes(), false); + d.prefillShiftFrameForTest(outCh, peripheral.busBuffer(0)); + d.encodeWholeForTest(outCh, peripheral.busBuffer(0)); + std::vector whole(peripheral.busBuffer(0), peripheral.busBuffer(0) + rowRegion); + peripheral.busDeinit(); - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - std::vector assembled = d.driveRingFrame(); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + std::vector assembled = peripheral.driveRingFrame(); REQUIRE(assembled.size() == whole.size()); CHECK(std::memcmp(assembled.data(), whole.data(), whole.size()) == 0); @@ -790,18 +835,19 @@ TEST_CASE("MoonI80 ring: an EMPTY lane does not break uniformity (prefill-skip s // buffers are reused, not zeroed), which is where a "lay it once at init" shortcut breaks on frame 2. TEST_CASE("MoonI80 ring: an exhausted RAGGED strand clocks zeros, on a fresh AND a recycled buffer") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; // Strand 0 alone runs the full 200; every other strand on both '595s ends at 8 β€” so from row 8 the // mask is a single bit, and 15 of 16 strands must be silent for the remaining 192 rows. - wireShift(d, src, corr, 200, "1,2", "200,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8"); + wireShift(d, peripheral, src, corr, 200, "1,2", "200,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8"); std::memset(src.data(), 0xFF, static_cast(src.count()) * 3); // a leak shows as full white const uint8_t outCh = corr.outChannels; const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); REQUIRE(d.maxLaneLights() == 200); - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); // Strand 0 is pin 0's shift position 0; the '595 shifts MSB-first, so that strand rides bit 0 of the // bus word at cycle outputsPerPin-1. Every OTHER bus bit must be 0 for rows >= 8: bit p is pin p's @@ -820,9 +866,9 @@ TEST_CASE("MoonI80 ring: an exhausted RAGGED strand clocks zeros, on a fresh AND INFO("exhausted strands leaked on " << which << ": " << leaked << " bytes"); CHECK(leaked == 0); }; - std::vector first = d.driveRingFrame(); + std::vector first = peripheral.driveRingFrame(); checkDark(first, "the first frame"); - std::vector second = d.driveRingFrame(); // same buffers, recycled + std::vector second = peripheral.driveRingFrame(); // same buffers, recycled checkDark(second, "a recycled buffer"); // And the two laps agree byte for byte β€” a recycled buffer is not a fresh one only by accident. REQUIRE(first.size() == second.size()); @@ -846,22 +892,23 @@ TEST_CASE("MoonI80 ring: an exhausted RAGGED strand clocks zeros, on a fresh AND // UNCONDITIONALLY. The mock's busDeinit clears ringActive_, so a surviving ring is visible here. TEST_CASE("MoonI80 ring: a failed ring build tears the bus down (no leaked ring)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); + wireShift(d, peripheral, src, corr, 200, "1,2"); const uint8_t outCh = corr.outChannels; const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); // A ring that built successfully β€” the exact state the failure path must not leave behind. - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); - REQUIRE(d.busIsRing()); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busIsRing()); // The fall-through's teardown, as reinit() performs it. It must not be gated on `inited_` β€” which is // false here, exactly as it is in production on this path. - d.busDeinit(); - CHECK_FALSE(d.busIsRing()); // the ring is gone, not merely unreferenced + peripheral.busDeinit(); + CHECK_FALSE(peripheral.busIsRing()); // the ring is gone, not merely unreferenced } TEST_CASE("MoonI80 ring: the PARALLEL snapshot's range-split is byte-identical to the whole-range serial") { @@ -870,9 +917,10 @@ TEST_CASE("MoonI80 ring: the PARALLEL snapshot's range-split is byte-identical t // ranges are disjoint and stateless: copyRange(0,half)+copyRange(half,N) == copyRange(0,N). The // snapshot is now a raw memcpy at SOURCE channel stride (correction fuses into encodeRows downstream). MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); // 16 strands Γ— 200, a real window + wireShift(d, peripheral, src, corr, 200, "1,2"); // 16 strands Γ— 200, a real window // Distinctive per-light source so a mis-split (gap/overlap/wrong stride) can't accidentally match. uint8_t* s = src.data(); for (mm::nrOfLightsType i = 0; i < src.count(); i++) { @@ -883,8 +931,8 @@ TEST_CASE("MoonI80 ring: the PARALLEL snapshot's range-split is byte-identical t const uint8_t outCh = corr.outChannels; const uint8_t srcCh = static_cast(src.channelsPerLight()); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - d.setWantRing(true); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + peripheral.setWantRing(true); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); // snapshotForTest sizes snapshotBuf_ (ensureSnapshotCap) and runs one full serial snapshot β€” after it, // the snapshot state (snapCopy*) is set and the buffer exists, so the manual re-runs below are safe. REQUIRE(d.snapshotForTest()); @@ -918,9 +966,10 @@ TEST_CASE("MoonI80 ring: the PARALLEL snapshot's range-split is byte-identical t // its tail reading stale bytes. This pins the full window survives. TEST_CASE("MoonI80 ring: snapshot keeps the whole window when outCh > srcCh (RGBW correction on RGB source)") { MockRingDriver d; + MockRingPeripheral peripheral; mm::Buffer src; mm::Correction corr; - wireShift(d, src, corr, 200, "1,2"); // 16 strands Γ— 200, RGB source (srcCh=3) + wireShift(d, peripheral, src, corr, 200, "1,2"); // 16 strands Γ— 200, RGB source (srcCh=3) // Swap in an RGBW correction (outCh=4) so outCh > the source's 3 channels β€” the failing condition. mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::RGBW); d.correctionForTest() = corr; @@ -928,11 +977,11 @@ TEST_CASE("MoonI80 ring: snapshot keeps the whole window when outCh > srcCh (RGB REQUIRE(corr.outChannels == 4); REQUIRE(src.channelsPerLight() == 3); - d.setWantRing(true); + peripheral.setWantRing(true); const uint8_t outCh = corr.outChannels; const uint8_t srcCh = static_cast(src.channelsPerLight()); const size_t rowBytes = static_cast(outCh) * 24 * 1 * d.outputsPerPin(); - REQUIRE(d.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); + REQUIRE(peripheral.busInitRing(rowBytes, static_cast(d.maxLaneLights()))); // Paint the source window's LAST light a distinct value; the snapshot must copy it. With the buggy // outCh clamp the window shrinks to winLen*3/4, so the last quarter (including this light) is never @@ -969,10 +1018,14 @@ TEST_CASE("MoonI80 ring: ringSnapshot control is hidden unless the ring is activ return false; }; MockRingDriver ringing; - ringing.setWantRing(true); + MockRingPeripheral peripheralRinging; + ringing.setPeripheralForTest(&peripheralRinging); + peripheralRinging.setWantRing(true); CHECK_FALSE(ringSnapshotHidden(ringing)); // ring active β†’ visible MockRingDriver whole; - whole.setWantRing(false); + MockRingPeripheral peripheralWhole; + whole.setPeripheralForTest(&peripheralWhole); + peripheralWhole.setWantRing(false); CHECK(ringSnapshotHidden(whole)); // no ring β†’ hidden } diff --git a/test/unit/light/unit_ParallelLedDriver_swap.cpp b/test/unit/light/unit_ParallelLedDriver_swap.cpp new file mode 100644 index 00000000..73d21d62 --- /dev/null +++ b/test/unit/light/unit_ParallelLedDriver_swap.cpp @@ -0,0 +1,191 @@ +// @module ParallelLedDriver +// @also MultiPinLedDriver, ParlioLedDriver + +#include "doctest.h" +#include "light/drivers/ParallelLedDriver.h" +#include "light/drivers/Correction.h" +#include "correction_presets.h" +#include "light/layers/Buffer.h" +#include "unit/core/conditional_controls.h" // controlIndex + +#include +#include + +// Host test of the runtime PERIPHERAL SWAP path β€” the `peripheral` Select changing on a live driver. +// The borrowed-mock tests (setPeripheralForTest) deliberately do NOT exercise this: a borrowed backend +// is !peripheralOwned_, so ensurePeripheralMatchesSelection() short-circuits and the registry swap +// never runs. To pin the swap we REGISTER two owned mock backends and drive the exact sequence +// Scheduler::setControl runs on a control change: +// +// applyControlValue writes peripheralSel_ β†’ rebuildControls() β†’ onControlChanged("peripheral") +// +// The bug this pins (found in the parallel-driver consolidation review): rebuildControls() already +// swaps the backend (ensurePeripheralMatchesSelection) and binds its members into the control list, +// so onControlChanged must NOT swap AGAIN β€” a second swap frees the just-bound backend and leaves +// every backend-owned control dangling into freed memory. Desktop's own registry is empty, so only a +// test that populates it can catch this. + +namespace { + +// A minimal owned backend (created by the registry, deleted by the driver). Reports a real hwBlock so +// the two labels model two distinct peripherals, and counts its own construction/destruction so the +// test can assert no leak and no double-free across a swap. +struct SwapMock : mm::LedPeripheral { + static inline int live = 0; // net live instances (ctor++ / dtor--) β€” 0 at rest, no leak/double-free + static inline int attachedDtors = 0; // destructions of a backend that was ATTACHED to a driver (i.e. + // a real selected backend, not a buildPeripheralOptions() probe β€” probes + // are make()/delete'd without attach()). A control change swaps to ONE + // backend, so across the whole swap sequence the only attached backend + // destroyed is the one being replaced. The double-swap bug destroys an + // EXTRA attached backend per change (it attaches B1 in the rebuild, then + // frees it in onControlChanged before attaching B2) β€” this counter is the + // discriminator that plain live/ctor counts can't be (probe churn). + mm::LedHwBlock block; + explicit SwapMock(mm::LedHwBlock b) : block(b) { live++; } + // owner_ (protected, set by attach()) is non-null only for a backend the driver actually selected; + // a buildPeripheralOptions() probe is make()/delete'd without attach(), so it destructs with a null + // owner_. Counting attached destructions isolates real backend churn from probe churn. + ~SwapMock() override { live--; if (owner_) attachedDtors++; } + + uint8_t lanesAvailable() const override { return 8; } + bool powerOfTwoBus() const override { return true; } + bool loopbackFullWidth() const override { return false; } + bool supportsPinExpander() const override { return false; } + const char* initFailMsg() const override { return "mock init failed"; } + mm::LedHwBlock hwBlock() const override { return block; } + + void addBusControls(mm::ControlList&) override {} + bool busControlTriggersBuild(const char*) const override { return false; } + void recordBusPins() override {} + bool extraBusPinsCurrent() const override { return true; } + const char* validateBusPins(const uint16_t*, uint8_t) const override { return nullptr; } + const char* validateBusFatal() const override { return nullptr; } + uint16_t clockPinForBus() const override { return 99; } + + bool busInit(size_t frameBytes, bool) override { cap_ = frameBytes; buf_.assign(frameBytes, 0); return true; } + uint8_t* busBuffer(uint8_t i) override { return (i == 0 && !buf_.empty()) ? buf_.data() : nullptr; } + size_t busCapacity() const override { return cap_; } + bool busTransmit(uint8_t, size_t) override { transmits_++; return true; } + bool busWait(uint8_t, uint32_t) override { return true; } + uint32_t busLastTransmitUs() const override { return 0; } + void busDeinit() override { cap_ = 0; buf_.clear(); } + mm::platform::RmtLoopbackResult busLoopback(const uint8_t*, size_t, size_t, uint8_t) override { return {}; } + + size_t transmits_ = 0; +private: + std::vector buf_; + size_t cap_ = 0; +}; + +// The peripheral registry is a static set built at static-init in production. On desktop the three +// real backends (i80/MoonI80/Parlio) DO register (their headers compile into this binary) but report +// 0 lanes, so they fill registry slots while being filtered out of the option list β€” leaving no room +// for two test mocks (kMaxPeripherals == 4). So a swap test SAVES the registry, installs exactly its +// two mocks, runs, and RESTORES it β€” scoped, and it can't perturb any other test's view of the set. +struct RegistryScope { + mm::ParallelLedDriver::PeripheralEntry saved[mm::ParallelLedDriver::kMaxPeripherals]; + uint8_t savedCount; + RegistryScope() { + savedCount = mm::ParallelLedDriver::peripheralRegistryCount_; + for (uint8_t i = 0; i < savedCount; i++) saved[i] = mm::ParallelLedDriver::peripheralRegistry_[i]; + mm::ParallelLedDriver::peripheralRegistryCount_ = 0; + // "swapA" (Parlio block) and "swapB" (LcdCam block) model two distinct peripherals. + mm::ParallelLedDriver::registerPeripheral("swapA", []() -> mm::LedPeripheral* { + return new SwapMock(mm::LedHwBlock::Parlio); + }); + mm::ParallelLedDriver::registerPeripheral("swapB", []() -> mm::LedPeripheral* { + return new SwapMock(mm::LedHwBlock::LcdCam); + }); + } + ~RegistryScope() { + mm::ParallelLedDriver::peripheralRegistryCount_ = savedCount; + for (uint8_t i = 0; i < savedCount; i++) mm::ParallelLedDriver::peripheralRegistry_[i] = saved[i]; + } +}; + +// Drive the Scheduler control-change sequence for the `peripheral` Select: write the new index through +// the bound control pointer (as applyControlValue does), rebuild controls (swap #1, binds new backend), +// then fire onControlChanged (must be a no-op swap, not a second free-and-rebuild). +void changePeripheralTo(mm::ParallelLedDriver& d, uint8_t index) { + int i = mm::test::controlIndex(d, "peripheral"); + REQUIRE(i >= 0); + *static_cast(d.controls()[static_cast(i)].ptr) = index; + d.rebuildControls(); + d.onControlChanged("peripheral"); +} + +} // namespace + +TEST_CASE("ParallelLedDriver: a peripheral swap does not double-free or dangle the control list") { + RegistryScope registry; // install swapA/swapB, restore the real set on scope exit + const int liveBefore = SwapMock::live; + + { + mm::ParallelLedDriver d; + mm::Buffer src; + mm::Correction corr; + // Fresh driver seeds the first registered backend (swapA). Wire a working config. + std::strcpy(d.pins, "1,2"); + REQUIRE(src.allocate(64, 3) == true); + mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); + d.defineControls(); + d.setSourceBuffer(&src); + d.correctionForTest() = corr; + d.applyState(); + + // Exactly ONE backend is live for a driver holding a single peripheral. + CHECK(SwapMock::live == liveBefore + 1); + + // Resolve labels β†’ board-filtered indices via the driver's own option list (order is registry + // order, which the test does not hardcode). A Select stores its options in aux and its option + // COUNT in max (hi = max-1), the shape defineDriverControls uses for the peripheral Select. + int aIdx = -1, bIdx = -1; + const auto& cs = d.controls(); + int selIdx = mm::test::controlIndex(d, "peripheral"); + REQUIRE(selIdx >= 0); + const char* const* opts = reinterpret_cast(cs[static_cast(selIdx)].aux); + const int optCount = cs[static_cast(selIdx)].max; // addSelect stores optionCount in max + for (int k = 0; k < optCount; k++) { + if (opts[k] && std::strcmp(opts[k], "swapA") == 0) aIdx = k; + if (opts[k] && std::strcmp(opts[k], "swapB") == 0) bIdx = k; + } + REQUIRE(aIdx >= 0); + REQUIRE(bIdx >= 0); + + // Swap A β†’ B. The bug: rebuildControls() swaps in B1 (binding its members into the control list), + // then onControlChanged swaps AGAIN β€” freeing B1 and building B2 β€” so the control list dangles into + // freed B1. The tell is the CONSTRUCTION count: the buggy path builds TWO backends for one change + // (B1 orphaned + B2), the fixed path builds exactly ONE (onControlChanged is a no-op swap). live + // count alone can't see it (both paths net one live backend); `built` delta is the discriminator. + int dtorsBefore = SwapMock::attachedDtors; + changePeripheralTo(d, static_cast(bIdx)); + // Aβ†’B destroys exactly ONE attached backend (the outgoing A). The double-swap bug destroys TWO + // (A replaced by B1 in the rebuild, then B1 replaced by B2 in onControlChanged) β€” so a delta > 1 + // is the bug's fingerprint. This is what live/ctor counts miss: probe churn hides the ctor delta, + // and net-live is 1 either way; only counting ATTACHED destructions isolates the extra free. + CHECK(SwapMock::attachedDtors - dtorsBefore == 1); + CHECK(SwapMock::live == liveBefore + 1); + // busInit succeeds (a memory buffer, not an inert desktop stub), so the bus comes up and the + // inited_-gated hwBlock() reports B's block (LcdCam) β€” proving the LIVE backend is B, not a + // dangling A: if the double-swap freed the rebuild-bound backend, hwBlock() would read freed memory. + CHECK(d.hwBlock() == mm::LedHwBlock::LcdCam); + + // The driver must still run: a tick after the swap encodes+transmits through the LIVE backend, + // not a freed one. If the control list dangled, this is a use-after-free (ASan/TSan would catch; + // the plain assert catches the "transmitted through a stale object" case). + d.tick20ms(); + d.tick(); // one render tick β€” reaches the live backend's busTransmit + + // Swap back B β†’ A, then A β†’ B again: repeated swaps must stay balanced (no accumulation), and + // hwBlock() tracks the live backend each time (A = Parlio, B = LcdCam). + changePeripheralTo(d, static_cast(aIdx)); + CHECK(SwapMock::live == liveBefore + 1); + CHECK(d.hwBlock() == mm::LedHwBlock::Parlio); + changePeripheralTo(d, static_cast(bIdx)); + CHECK(SwapMock::live == liveBefore + 1); + CHECK(d.hwBlock() == mm::LedHwBlock::LcdCam); + } + + // Driver destroyed β†’ its owned backend freed β†’ back to the starting live count (no leak). + CHECK(SwapMock::live == liveBefore); +} diff --git a/test/unit/light/unit_ParlioLedDriver.cpp b/test/unit/light/unit_ParlioLedDriver.cpp index 335734c0..c1e36f2d 100644 --- a/test/unit/light/unit_ParlioLedDriver.cpp +++ b/test/unit/light/unit_ParlioLedDriver.cpp @@ -20,11 +20,19 @@ // The one behavioural difference from the LCD driver pinned below: Parlio has // NO exactly-8-pins rule β€” 1..8 lanes are all valid (it takes the data GPIOs // directly, no all-lanes-required i80 bus). +// +// mm::ParallelLedDriver is the ONE registered driver; this file drives it with an +// injected mm::ParlioPeripheral backend, the backend this header defines and registers +// under the "Parlio" peripheral label. namespace { -void wire(mm::ParlioLedDriver& d, mm::Buffer& src, mm::Correction& corr, +// The peripheral is declared BEFORE the driver at every call site (see this helper's +// parameter order) so it outlives the driver β€” setPeripheralForTest borrows, it does +// not own (see unit_ParallelLedDriver_doublebuffer.cpp's wire()). +void wire(mm::ParallelLedDriver& d, mm::ParlioPeripheral& peripheral, mm::Buffer& src, mm::Correction& corr, mm::nrOfLightsType lights) { + d.setPeripheralForTest(&peripheral); // Pins default to UNSET now (the "default only when it cannot do harm" rule β€” // the user solders the strand to its own GPIOs), so a fresh driver idles until // configured. These slicing/frame tests exercise the lane logic, not the @@ -54,12 +62,13 @@ size_t expectFrame(mm::nrOfLightsType maxLights, uint8_t outCh, uint8_t slotByte // Three lanes (Parlio accepts any 1..8 count) slice the buffer consecutively; // the frame is sized by the LONGEST lane. TEST_CASE("ParlioLedDriver slices lanes and sizes the frame by the longest") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.pins, "36,37,38"); std::strcpy(d.ledsPerPin, "50,20,20"); - wire(d, src, corr, 90); + wire(d, peripheral, src, corr, 90); REQUIRE(d.laneCount() == 3); CHECK(d.laneLightCount(0) == 50); @@ -75,10 +84,11 @@ TEST_CASE("ParlioLedDriver slices lanes and sizes the frame by the longest") { // Empty ledsPerPin (the default) splits evenly over the 8 lanes β€” shared PinList // semantics, same as the RMT/LCD drivers. TEST_CASE("ParlioLedDriver even split over 8 lanes") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 256); // ledsPerPin empty (default) = even split + wire(d, peripheral, src, corr, 256); // ledsPerPin empty (default) = even split REQUIRE(d.laneCount() == 8); CHECK(d.laneLightCount(0) == 32); @@ -92,10 +102,11 @@ TEST_CASE("ParlioLedDriver accepts any lane count from 1 to 8") { mm::Correction corr; mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); for (const char* pinList : {"36", "36,37", "36,37,38,39,40", "36,37,38,39,40,41,42,43"}) { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; std::strcpy(d.pins, pinList); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); // count the commas+1 to know the expected lane count uint8_t expected = 1; for (const char* p = pinList; *p; p++) if (*p == ',') expected++; @@ -110,19 +121,21 @@ TEST_CASE("ParlioLedDriver accepts any lane count from 1 to 8") { // 9..16 pins are accepted (Parlio drives 1..16, the 16-bit bus); more than 16 is rejected. TEST_CASE("ParlioLedDriver accepts 9..16 pins, rejects more than 16") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; { // 12 pins β†’ 12 lanes, valid (the 16-bit bus) std::strcpy(d.pins, "1,2,3,4,5,6,7,8,9,10,11,12"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 12); CHECK(d.severity() != mm::MoonModule::Severity::Error); // valid β†’ info, not error } { // 17 pins β†’ rejected (over the 16-lane cap) - mm::ParlioLedDriver d2; + mm::ParlioPeripheral peripheral2; + mm::ParallelLedDriver d2; std::strcpy(d2.pins, "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"); - wire(d2, src, corr, 64); + wire(d2, peripheral2, src, corr, 64); CHECK(d2.laneCount() == 0); CHECK(d2.status() != nullptr); } @@ -135,19 +148,21 @@ TEST_CASE("ParlioLedDriver 16-lane frame doubles the byte size (16-bit bus)") { mm::Buffer src; mm::Correction corr; { // 8 lanes Γ— 50 lights β†’ 8-bit bus (slotBytes = 1) - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; std::strcpy(d.pins, "1,2,3,4,5,6,7,8"); std::strcpy(d.ledsPerPin, "50,50,50,50,50,50,50,50"); - wire(d, src, corr, 400); + wire(d, peripheral, src, corr, 400); REQUIRE(d.laneCount() == 8); CHECK(d.maxLaneLights() == 50); CHECK(d.frameBytes() == expectFrame(50, 3, 1)); } { // 16 lanes Γ— 50 lights β†’ 16-bit bus (slotBytes = 2), same per-lane lights, DOUBLE bytes - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; std::strcpy(d.pins, "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16"); std::strcpy(d.ledsPerPin, "50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50"); - wire(d, src, corr, 800); + wire(d, peripheral, src, corr, 800); REQUIRE(d.laneCount() == 16); CHECK(d.maxLaneLights() == 50); CHECK(d.frameBytes() == expectFrame(50, 3, 2)); // 16-bit slots β†’ 2 bytes/slot @@ -158,11 +173,12 @@ TEST_CASE("ParlioLedDriver 16-lane frame doubles the byte size (16-bit bus)") { // An RGBβ†’RGBW preset toggle grows the frame (32 vs 24 slot bytes per light). TEST_CASE("ParlioLedDriver frame grows on RGBW preset") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.ledsPerPin, "50,50"); - wire(d, src, corr, 100); + wire(d, peripheral, src, corr, 100); CHECK(d.frameBytes() == expectFrame(50, 3)); // The driver owns its Correction, so mutate that copy (not the external one). @@ -184,13 +200,14 @@ TEST_CASE("ParlioLedDriver frame grows on RGBW preset") { // changes. Mirrors the platform constant. TEST_CASE("ParlioLedDriver frame at the Parlio single-transfer ceiling (byte limit, channel-relative)") { constexpr size_t kParlioMaxTransferBytes = 0x7FFFF / 8; // 65535, matches platform_esp32_parlio.cpp - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; // 896 RGB lights/lane β€” the HW-tested config β€” FITS one transfer. std::strcpy(d.pins, "20,21,22,23,24,25,26,27"); std::strcpy(d.ledsPerPin, "896,896,896,896,896,896,896,896"); - wire(d, src, corr, 896 * 8); + wire(d, peripheral, src, corr, 896 * 8); CHECK(d.maxLaneLights() == 896); CHECK(d.frameBytes() == expectFrame(896, 3)); CHECK(d.frameBytes() <= kParlioMaxTransferBytes); // fits one Parlio transfer @@ -204,11 +221,12 @@ TEST_CASE("ParlioLedDriver frame at the Parlio single-transfer ceiling (byte lim // A bad pin list idles the driver with the parse literal in the status; fixing it recovers. TEST_CASE("ParlioLedDriver bad pins β†’ status error β†’ recovery") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; std::strcpy(d.pins, "36,nope"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); CHECK(d.laneCount() == 0); CHECK(d.frameBytes() == 0); @@ -227,9 +245,11 @@ TEST_CASE("ParlioLedDriver bad pins β†’ status error β†’ recovery") { // GPIO. (wire() back-fills empty pins for the slicing cases, so this one wires // the buffer directly to keep pins empty.) TEST_CASE("ParlioLedDriver with the empty default pins idles cleanly") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); REQUIRE(d.pins[0] == '\0'); // the empty default, not a bench guess REQUIRE(src.allocate(64, 3)); mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); @@ -246,10 +266,11 @@ TEST_CASE("ParlioLedDriver with the empty default pins idles cleanly") { // A 0Γ—0Γ—0 grid is a clean idle: zero counts, zero frame, no crash. TEST_CASE("ParlioLedDriver tolerates a zero-light buffer") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; - wire(d, src, corr, 0); + wire(d, peripheral, src, corr, 0); CHECK(d.laneCount() == 8); // the default 8 pins parse fine CHECK(d.maxLaneLights() == 0); @@ -265,20 +286,24 @@ TEST_CASE("ParlioLedDriver tick is crash-safe for every pin configuration") { mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); SUBCASE("single pin, populated grid") { - mm::ParlioLedDriver d; mm::Buffer src; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; std::strcpy(d.pins, "36"); - wire(d, src, corr, 64); + wire(d, peripheral, src, corr, 64); d.tick(); } SUBCASE("multi-pin even split") { - mm::ParlioLedDriver d; mm::Buffer src; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; std::strcpy(d.pins, "36,37,38"); - wire(d, src, corr, 90); + wire(d, peripheral, src, corr, 90); REQUIRE(d.laneCount() == 3); d.tick(); } SUBCASE("tick before any buffer is wired") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); d.tick(); } @@ -287,9 +312,11 @@ TEST_CASE("ParlioLedDriver tick is crash-safe for every pin configuration") { // setup/release cycles leave no residue (status clean, ASAN-checked heap). TEST_CASE("ParlioLedDriver setup/release is repeatable") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; mm::Buffer src; mm::Correction corr; + d.setPeripheralForTest(&peripheral); src.allocate(64, 3); mm::test::rebuildFromPreset(corr, 255, mm::test::PresetOrder::GRB); std::strcpy(d.pins, "20,21,22,23,24,25,26,27"); // pins now default UNSET @@ -307,7 +334,9 @@ TEST_CASE("ParlioLedDriver setup/release is repeatable") { // loopbackRxPin is bound always, visible only while loopbackTest is on. TEST_CASE("ParlioLedDriver loopbackRxPin tracks the loopbackTest toggle") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); bool found = false; for (uint8_t i = 0; i < d.controls().count(); i++) { @@ -325,7 +354,9 @@ TEST_CASE("ParlioLedDriver loopbackRxPin tracks the loopbackTest toggle") { // contract is host-testable here via the shared helper (toggles loopbackTest both // ways and asserts the control stays bound while flipping visibility). TEST_CASE("ParlioLedDriver loopbackTxPin tracks the loopbackTest toggle") { - mm::ParlioLedDriver d; + mm::ParlioPeripheral peripheral; + mm::ParallelLedDriver d; + d.setPeripheralForTest(&peripheral); d.defineControls(); auto setTest = [&](bool on) { mm::test::setControlValue(d, "loopbackTest", on); diff --git a/web-installer/deviceModels.json b/web-installer/deviceModels.json index b3df6f67..c693eeaf 100644 --- a/web-installer/deviceModels.json +++ b/web-installer/deviceModels.json @@ -715,10 +715,11 @@ } }, { - "type": "ParlioLedDriver", - "id": "ParlioLed", + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "Parlio", "pins": "21", "loopbackTxPin": 46, "loopbackRxPin": 47 @@ -867,10 +868,11 @@ } }, { - "type": "MultiPinLedDriver", - "id": "MultiPinLed", + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "i80", "pins": "47,21,14,9,8,16,15,7,1,2,42,41,40,39,38,48", "clockPin": 5, "dcPin": 6 @@ -925,10 +927,11 @@ } }, { - "type": "MultiPinLedDriver", - "id": "MultiPinLed", + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "i80", "pins": "47,48,21,38,14,39,13,40,12,41,11,42,10,2,3,1", "clockPin": 8, "dcPin": 9 @@ -984,10 +987,11 @@ } }, { - "type": "ParlioLedDriver", - "id": "ParlioLed", + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "Parlio", "pins": "20,21,22,23,24,25,26,27" } }, @@ -1054,10 +1058,11 @@ } }, { - "type": "ParlioLedDriver", - "id": "ParlioLed", + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "Parlio", "pins": "21,20,25,5,22,23,24,27" } }, @@ -1231,7 +1236,7 @@ ] }, { - "name": "hpwit shift-register board", + "name": "hpwit shift-register 48", "chip": "ESP32-S3", "firmwares": [ "esp32s3-n16r8" @@ -1246,14 +1251,27 @@ "type": "System", "id": "System", "controls": { - "deviceModel": "hpwit shift-register board" + "deviceModel": "hpwit shift-register 48" } }, { - "type": "MultiPinLedDriver", - "id": "MultiPinLed", + "type": "PanelsLayout", + "id": "Panels", + "parent_id": "Layouts", + "controls": { + "horizontalPanels": 8, + "verticalPanels": 6, + "panelWidth": 16, + "panelHeight": 16, + "snake": true + } + }, + { + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "i80", "pins": "9,10,12,8,18,17", "pinExpander": true, "latchPin": 46, @@ -1292,17 +1310,33 @@ } }, { - "type": "MultiPinLedDriver", - "id": "MultiPinLed", + "type": "PanelsLayout", + "id": "Panels", + "parent_id": "Layouts", + "controls": { + "horizontalPanels": 5, + "verticalPanels": 3, + "panelWidth": 16, + "panelHeight": 16, + "snake": true + } + }, + { + "type": "ParallelLedDriver", + "id": "ParallelLed", "parent_id": "Drivers", "controls": { + "peripheral": "i80", "pins": "9,10", "pinExpander": true, "latchPin": 46, "clockPin": 3, "ledsPerPin": "96", "dcPin": 21, - "doubleBuffer": false + "doubleBuffer": false, + "loopbackTest": true, + "loopbackStrand": 8, + "loopbackRxPin": 16 } }, { diff --git a/web-installer/index.html b/web-installer/index.html index db04513c..1d9d9b4d 100644 --- a/web-installer/index.html +++ b/web-installer/index.html @@ -230,10 +230,13 @@

    projectMM Installer

  1. 6%=kgb3gdnZS{fo?jilt~&VDo2prhoxc^#;Kp7 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

    SU`;Onab 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-transmit-schematic.png b/docs/assets/reference/mhc-wled-esp32-p4-shield-rs485-transmit-schematic.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7d6b388f764740e7d482162b94d767056ca110 GIT binary patch literal 46994 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

    +zny4;}0GnNn7X}U*)1= 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 Xuc9U7T`qb#BS= More on how the preview streams from the device: > [PreviewDriver](moonmodules/light/moxygen/PreviewDriver.md). -## The system modules +### The system modules The top of the list is your device's "about" section β€” read-outs and connection settings. You rarely need to touch these, but they're the first place to look if @@ -218,7 +218,41 @@ other. > is an example, driving its LEDs with [FastLED](https://github.com/FastLED/FastLED) (on > hold until projectMM ships as a reusable library). -## Building a light show: layouts β†’ layers β†’ drivers +### Control it from your phone with WLED Native + +The device's own web UI works on a phone, but for quick on/off and brightness from +your pocket there's a nicer option: **WLED Native**, the open-source mobile app for +the WLED ecosystem. projectMM speaks the WLED JSON API and announces itself over the +network the same way a WLED device does, so the app finds your projectMM controllers +automatically β€” no setup, no pairing. Each one shows up as a card with a power toggle +and a brightness slider, so a roomful of controllers is a scroll and a tap away. + +![projectMM devices discovered in WLED Native](assets/core/WLED%20Native%20discovers%20projectMM.jpeg){ width="300" } + +Get it free for your phone: + +- **iPhone / iPad:** [WLED Native on the App Store](https://apps.apple.com/us/app/wled-native/id6446207239) +- **Android:** [WLED Native on Google Play](https://play.google.com/store/apps/details?id=ca.cgagnier.wlednativeandroid) + +For the full picture and controls, the device's web interface is always there at +`http://.local` β€” WLED Native is the fast everyday remote alongside it. + +### Bring it into your smart home with Home Assistant + +Want your lights in the same dashboard as the rest of your house β€” and in +automations, voice assistants, and Apple Home? projectMM adopts into **Home +Assistant** like any other light: point the device at your HA setup and it appears +as a light entity with on/off and brightness, alongside a floor of other devices. + +![projectMM devices as lights in a Home Assistant dashboard](assets/core/ha-integration.png){ width="600" } + +There are two ways in β€” zeroconf (HA finds the device on its own) or MQTT +auto-discovery (for a broker-only or cross-subnet setup) β€” and from there you can +bridge the entity into Apple Home too. The step-by-step, including installing HA +and the MQTT broker if you don't have them, is in the +[home automation guide](usecases/home-automation.md). + +### Building a light show: layouts β†’ layers β†’ drivers The bottom three modules are where the fun is. They form a simple pipeline: a **layout** says where your lights are, **layers** decide what colours play on @@ -257,7 +291,7 @@ keep going. --- -## Where to go next +### Where to go next - **Understand the pipeline** β€” how layouts, layers, effects, modifiers and drivers fit together: [architecture overview](architecture.md#the-pipeline). diff --git a/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md b/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md new file mode 100644 index 00000000..fdd11d7f --- /dev/null +++ b/docs/history/plans/Plan-20260722 - Release 4 scope - effect breadth + rename runway.md @@ -0,0 +1,40 @@ +# Plan β€” Release 4 scope: effect breadth + the rename runway + +## Context + +Release 3 is being cut now. This plan captures the **Release 4** candidates β€” the next strategic thread after R3 β€” so the direction is recorded before the work starts. The product owner's steer: the items below are R4, not R3. + +The backlog has one dominant strategic thread that most other items orbit: the **projectMM β†’ MoonLight rename** ([backlog rename plan](../../backlog/rename-to-moonlight.md)). Its gate is *"the effect library must not feel thin next to the predecessor's 60+ effects."* Two in-flight plans feed that gate, and R4 is where they land. The shape of R4 is therefore **"the effects release + the rename runway"**: grow visible feature breadth while moving the single most important strategic gate (rename readiness), and leave the hardware-verification-bound driver work to its own dedicated push. + +This is a roadmap/scope plan, not a single-feature `/plan`. Each item below gets its own `/plan` + commit when reached; this document is the *map* and the *why*. + +## The spine β€” effect-breadth parity (headline) + +**MoonLight migration, Stage 1 + the next effect batch.** ([Plan-20260630 - MoonLight migration (multi-stage)](Plan-20260630%20-%20MoonLight%20migration%20(multi-stage).md).) + +This is the biggest lever and the explicit *"execution vehicle for the effect-breadth parity gate."* ~21 of the predecessor's 60+ effects are ported. Stage 1's prerequisites are the highest-value core work available, because every future effect leans on them: + +- **Shared palette** β€” hard prerequisite; many effects colour via `ColorFromPalette`. Generalise the pattern `PlasmaPaletteEffect` hard-codes today. +- **The shared primitive library** β€” FastLED-named, our own implementation, hot-path-tuned integer-only: `beatsin8`, `inoise8`, `qadd8`, `nscale8`, `random8`/`random16`, `ColorFromPalette`, and the dimension-agnostic draw set. Extends the existing `color.h` (`scale8`, `sin8`). +- **Tag/emoji legend** β€” settle before batch-migrating so every module is consistent from batch one. +- **Per-library doc model** β€” `effects_.md` compact table rows (per [ADR 0015](../../adr/0015-library-is-a-tag-not-a-folder.md)); changes the `check_specs.py` contract. + +Then the next migration batch on top. This is the R4 headline: it unblocks the rename *and* is pure user-visible feature growth. + +## Two quick wins β€” scoped and ready + +- **Active-instance election primitive.** ([Plan-20260710 - Active-instance election primitive](Plan-20260710%20-%20Active-instance%20election%20primitive.md).) A core `ActiveInstance` that removes duplicated singleton-election bookkeeping from `AudioService` + `DevicesModule` (both had real dangling-static bugs). Textbook *Complexity-lives-in-core* subtraction; small; in flight. +- **CodeRabbit #29 boundary findings (4).** ([backlog-core Β§ MoonLive core/platform layering](../../backlog/backlog-core.md#moonlive-coreplatform-layering--jit-sdkconfig-scoping-coderabbit-29-4-findings).) MoonLive core-includes-platform + compiled-into-`mm_core`, W^X disabled in the board default, a scenario riding timing + network. Real, already scoped; good hygiene to close before a named release. + +## The RS-485 / DMX-512 opportunity (candidate, larger) + +The [P4-shield RS-485/DMX hardware is now well documented](../../reference/mhc-wled-esp32-p4-shield.md) (the builder's schematics landed 2026-07-16). The **RS-485 / DMX-512 wired-output driver** + its **`platform::` UART-RS485 seam** ([backlog-light](../../backlog/backlog-light.md#rs-485-dmx-512-wired-output-future-the-physical-dmx-driver)) is demand-driven and self-contained. It is a meaty new capability β€” a flagship candidate if R4 wants a headline new-hardware feature alongside the effects work, but it is larger than the two quick wins and should be its own `/plan`. + +## Explicitly NOT in R4 + +- **P4 streaming ring / classic-shift-ring on raw I2S / P4-Parlio streaming** ([backlog-light "WANTED"](../../backlog/backlog-light.md#drivers)) β€” high value but hardware-verification-heavy; needs the expander wall. Better as its own focused effort than bundled into a release. +- **MoonI80 prime-only ring stall backstop** ([backlog-core](../../backlog/backlog-core.md#mooni80-prime-only-ring-no-stall-backstop-sibling-path-gap)) β€” needs the expander wall to verify; do not land blind. + +## Success shape + +R4 ships when: the migration Stage-1 primitives + the next effect batch have landed (moving the rename's breadth gate forward), the `ActiveInstance` primitive and the CodeRabbit #29 boundary fixes are in, and β€” if taken up β€” the RS-485/DMX driver reaches a verified first output. The rename itself is a *separate* cutover (its own plan); R4 is the runway that makes the name not a downgrade, not the switch. diff --git a/docs/moonmodules/core/system.md b/docs/moonmodules/core/system.md index 8c7ed30e..b566d5cd 100644 --- a/docs/moonmodules/core/system.md +++ b/docs/moonmodules/core/system.md @@ -15,6 +15,7 @@ The device's identity and vitals β€” name (behind mDNS `.local`, the SoftA - `deviceName` β€” the device identity behind mDNS `.local`, the SoftAP SSID, and the DHCP hostname. - `deviceModel` β€” the board model (drives the installer catalog entry). - `expertMode` β€” reveals advanced tuning/diagnostic controls (marked πŸ”§) across the UI; off by default. +- `logLevel` β€” serial verbosity (None/Error/Warn/Info/Debug/Verbose); default Warn silences the periodic tick line but keeps warnings/errors. First 60 s always logs at Info. - read-only vitals β€” `uptime`, `fps`, `heap`, `psram`, `flash`, `chip`, and per-module footprint. Detail: [technical](moxygen/SystemModule.md) diff --git a/docs/reference/mhc-wled-esp32-p4-shield.md b/docs/reference/mhc-wled-esp32-p4-shield.md index c3d46e89..8360feb3 100644 --- a/docs/reference/mhc-wled-esp32-p4-shield.md +++ b/docs/reference/mhc-wled-esp32-p4-shield.md @@ -1,15 +1,20 @@ # MHC-WLED ESP32-P4 shield β€” hardware reference -Terminal pinout and onboard features for the **MHC-WLED ESP32-P4 shield** (myhome-control), the P4-NANO carrier used on the bench (catalog `deviceModel: "MHC-WLED ESP32-P4 shield"`, `esp32p4-eth` firmware). Read from the board silkscreen so projectMM work reads this instead of the marketing render. The shield sits on a **Waveshare ESP32-P4-NANO**; GPIO numbers are the P4's. +Terminal pinout and onboard features for the **MHC-WLED ESP32-P4 shield** (myhome-control), the P4-NANO carrier used on the bench (catalog `deviceModel: "MHC-WLED ESP32-P4 shield"`, `esp32p4-eth` firmware). Read from the board silkscreen + the builder's schematics so projectMM work reads this instead of the marketing render. The shield sits on a **Waveshare ESP32-P4-NANO**; GPIO numbers are the P4's. **Sources** - Overview render (board V2): [`docs/assets/deviceModels/mhc-wled-esp32-p4-shield.jpg`](../assets/deviceModels/mhc-wled-esp32-p4-shield.jpg) -- Silkscreen (photographed, 2026-07-09): the terminal labels below are transcribed from the physical board, which supersedes the render where they differ (the render's RS-485 "GPIOs 3,4,6,53" is wrong β€” the board reads 4, 22, 24, 3). -- Builder: myhome-control (Wladi). +- Silkscreen (photographed) + the builder's schematics and terminal maps (myhome-control / Wladi, 2026-07-16); the transcriptions below come from those. The schematics supersede the marketing render where they differ. ## Pinout -![MHC-WLED ESP32-P4 shield terminal pinout](../assets/reference/mhc-wled-esp32-p4-shield-pinout.svg) +### GPIO ↔ screw-terminal map (V1 board) + +The output/RS-485 terminals, left to right, with the P4 GPIO each carries: + +![MHC-WLED ESP32-P4 shield GPIO terminal map](../assets/reference/mhc-wled-esp32-p4-shield-gpio-terminal-map.png) + +`O21 O20 O25 O5 O7 O23 O8 O27 O3 O22 O24 O4` β€” the level-shifted single-ended LED outputs, then the four RS-485 differential pairs. **Nothing on this shield is a bare GPIO.** Every terminal routes through protection or level-shifting β€” the reason a direct drive-and-read WS2812 loopback jumper fails on it (see below). Four terminal groups: @@ -27,20 +32,37 @@ The LED-data outputs. Each terminal is `O` on the silkscreen; a level shif > **GPIO 3, 4, 22, 24 each appear TWICE** β€” once here (level-shifted single-ended output, `O`) and once in the RS-485 block (`A--B`). It's the *same* P4 GPIO fanned out to two output forms: driving the pin lights up **both** its `O` terminal and its `A--B` transceiver at once. Wire to whichever form you need. GPIO 21/20/25/5/23/27 have **only** the level-shifted path (no RS-485), which is why the LED-driver default uses those + 22/24 for strips and leaves 3/4 free. -### 4x RS-485 β€” differential A/B pairs +### 4x RS-485 β€” differential A/B pairs (range extender + DMX) -Each channel is `A--B` on the silkscreen: an **RS-485 transceiver** (not a bare GPIO) driven by that GPIO. **Each channel occupies TWO screw terminals β€” an `A` and a `B`** (the differential pair), so the 4 channels are 8 terminals total. Channels on **GPIO 4, 22, 24, 3**. The render mentions "switch GPIO 3 as input/output," but there's **no physical switch on the board** β€” GPIO 3 is just a GPIO, and projectMM sets its direction in firmware (an output when driving, an input when `loopbackRxPin` reads it). +Each channel is `A--B` on the silkscreen: an **RS-485 transceiver** (an SP3485EN-L/TR, not a bare GPIO) driven by that GPIO, with 120 Ξ© termination, resettable fuses (nSMD010), and TVS protection (CDSOT23-SM712-ES) on the line. **Each channel occupies TWO screw terminals β€” an `A` and a `B`** (the differential pair), so the 4 channels are 8 terminals total. Channels on **GPIO 4, 22, 24, 3**. -| Channel | GPIO | Terminals | -|---|---|---| -| A-4-B | 4 | A4, B4 | -| A-22-B | 22 | A22, B22 | -| A-24-B | 24 | A24, B24 | -| A-3-B | 3 | A3, B3 | +RS-485 is here for two purposes: + +- **Range extender** β€” RS-485's differential pair carries LED data far past what a single-ended 5 V line manages. At the LED end you need an **RS-485 receiver with a 5 V data output** to convert the differential signal back to the WS2812 single-ended waveform. +- **DMX-512 output** β€” DMX's physical layer *is* RS-485, so these channels double as DMX outputs. Wire an XLR connector to `GND`, `A`, `B`; in DMX nomenclature **A is Dataβˆ’ (Signalβˆ’), B is Data+ (Signal+)**. + +**Three channels are transmit-only; one (GPIO 3) is switchable.** On the transmit-only channels (GPIO 4, 22, 24) the transceiver's `RE#`/`DE` direction pins are hard-wired to transmit (`DI` in, `RO` disconnected): + +![RS-485 transmit-only channel schematic (GPIO 4)](../assets/reference/mhc-wled-esp32-p4-shield-rs485-transmit-schematic.png) + +The **GPIO 3 channel adds a mechanical slide switch** (SW5, MSK12C02) that ties the transceiver's `RE#`/`DE` to 3V3 or GND β€” i.e. it selects **transmit mode** (`DI`, GPIO 3 drives the line) or **receive mode** (`RO`, GPIO 3 reads the line): + +![RS-485 GPIO 3 switchable channel schematic](../assets/reference/mhc-wled-esp32-p4-shield-rs485-gpio3-switchable-schematic.png) + +| Channel | GPIO | Terminals | Direction | +|---|---|---|---| +| A-4-B | 4 | A4, B4 | transmit only | +| A-22-B | 22 | A22, B22 | transmit only | +| A-24-B | 24 | A24, B24 | transmit only | +| A-3-B | 3 | A3, B3 | transmit **or** receive (board switch) | ### 4x in/out header -The `O46 O47 O2 O48` header plus power (`GND`, `In5V`, `Out3V3`). Inputs are **diode-protected with a ~16 kHz low-pass filter** β€” designed for robust button-style inputs, not high-speed signals. GPIO 2 and 46 are P4 **boot straps**. This header is *not* usable for a WS2812 loopback (the filter and protection destroy the ~800 kHz waveform β€” the `hi=0 lo=0` continuity result that pinned this). +The `O46 O47 O2 O48` header plus power (`GND`, `In5V`, `Out3V3`): + +![MHC-WLED ESP32-P4 shield in/out header](../assets/reference/mhc-wled-esp32-p4-shield-inout-header.png) + +Inputs are **diode-protected with a ~16 kHz low-pass filter** β€” designed for robust button-style inputs, not high-speed signals. GPIO 2 and 46 are P4 **boot straps**. This header is *not* usable for a WS2812 loopback (the filter and protection destroy the ~800 kHz waveform). ### Line-In audio (PCM1808 β†’ IΒ²S) @@ -52,12 +74,16 @@ The P4-NANO's RMII PHY: **MDC 31 Β· MDIO 52 Β· RST 51 Β· CLK 50 (external-in) Β· ## Loopback self-test on this shield -The loopback self-test drives a WS2812 frame out one pin and reads it back on a jumpered pin β€” so it needs a **bare GPIO pair**. This shield exposes none: every terminal is buffered (level shifter, RS-485 transceiver, or diode + low-pass). **The self-test therefore does not apply to this shield β€” that's by design, not a firmware gap.** +The loopback self-test drives a WS2812 frame out one pin and reads it back on a jumpered pin β€” so it needs a signal path from a Tx pin to an Rx pin. The bare-GPIO terminals can't provide it (every one is buffered), but the **GPIO 3 switchable RS-485 channel can**, because its board switch turns GPIO 3 into a data *input*: + +- **Set the GPIO 3 board switch to the receive (input) position**, then jumper the RS-485 differential pairs `A4β†’A3` and `B4β†’B3` (the wiring the builder shows): + + ![RS-485 loopback wiring: A4β†’A3, B4β†’B3, GPIO 3 switch in input position](../assets/reference/mhc-wled-esp32-p4-shield-rs485-loopback-wiring.png) -- The frame-size fix the test exercises is **already proven** on the bare P4-NANO (direct GPIO 32↔33, PASS at every grid size), so the shield doesn't need to re-prove it. -- To verify LED output *on the shield*, the honest test is to wire a real **WS2812 strip to an `O` output** and watch it light β€” that exercises the true path (GPIO β†’ level shifter β†’ strip), which is what the shield is built for. -- The RS-485 channels (the builder's suggested loopback path, Tx=GPIO 4 `A-4-B` β†’ Rx=GPIO 3 `A-3-B`, wired A4β†’A3 / B4β†’B3) are **unlikely to work as a loopback**: projectMM drives pins as plain GPIO with **no RS-485 direction control** (no DE/RE driver-enable / receiver-enable toggling), so the transceivers won't reliably switch Tx↔Rx, and the differential path is slew-limited for an ~800 kHz WS2812 waveform anyway. Half-duplex RS-485 (DE/RE) is a real feature, not something the loopback path gets for free β€” see the [RS-485 / DMX-512 wired-output future extension](../backlog/backlog-light.md#rs-485-dmx-512-wired-output-future-the-physical-dmx-driver). +- The signal path is: **GPIO 4 emits the WS2812 frame β†’ the first RS-485 transceiver drives it as a differential signal on `A4`/`B4` β†’ the second transceiver reads it back β†’ GPIO 3 receives it as a 3.3 V data input.** So the loopback runs **Tx = GPIO 4, Rx = GPIO 3** with the switch in the input position. +- The bare P4-NANO already proves the frame-size fix directly (GPIO 32↔33, PASS at every grid size), so the shield doesn't need to re-prove it β€” but this RS-485 path is the builder's intended on-shield loopback, distinct from the bare-GPIO jumper the self-test defaults to. +- To verify LED output *on the shield*, the other honest test is to wire a real **WS2812 strip to an `O` output** and watch it light β€” that exercises the true path (GPIO β†’ level shifter β†’ strip), which is what the shield is built for. ## Cross-reference -Chip-level GPIO constraints (straps, flash/PSRAM) for the P4 are in [gpio-usage.md Β§ ESP32-P4](gpio-usage.md#esp32-p4); this page is the *board* wiring. The catalog entry is [`web-installer/deviceModels.json`](../../web-installer/deviceModels.json) (`MHC-WLED ESP32-P4 shield`). +Chip-level GPIO constraints (straps, flash/PSRAM) for the P4 are in [gpio-usage.md Β§ ESP32-P4](gpio-usage.md#esp32-p4); this page is the *board* wiring. The catalog entry is [`web-installer/deviceModels.json`](../../web-installer/deviceModels.json) (`MHC-WLED ESP32-P4 shield`). RS-485 / DMX-512 as a first-class projectMM output is tracked in the [RS-485 / DMX-512 wired-output backlog item](../backlog/backlog-light.md#rs-485-dmx-512-wired-output-future-the-physical-dmx-driver). diff --git a/moondeck/_moondeck_config.py b/moondeck/_moondeck_config.py new file mode 100644 index 00000000..c969b875 --- /dev/null +++ b/moondeck/_moondeck_config.py @@ -0,0 +1,46 @@ +"""Shared moondeck.json helpers used across the check/ and run/ scripts. + +Kept dependency-free (stdlib only) so a PEP-723 script can import it after adding +moondeck/ to sys.path, without threading extra `--with` deps. Mirrors the shared +`_net_probe.py` pattern in scenario/, one level up so both check/ and run/ reach it. +""" + +import json +import urllib.request +from pathlib import Path + +_ROOT = Path(__file__).resolve().parent.parent +_STATE = _ROOT / "moondeck" / "moondeck.json" + +# logLevel option indices, matching SystemModule's addSelect order +# (None, Error, Warn, Info, Debug, Verbose). +LOG_NONE, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_VERBOSE = range(6) + + +def active_device_ips(): + """ESP32 device IPs in the active network (from moondeck.json). Skips the desktop + entry (its ip carries a :port) and anything without an ip. [] if unresolvable.""" + if not _STATE.exists(): + return [] + try: + state = json.loads(_STATE.read_text(encoding="utf-8")) + active = next((n for n in (state.get("networks") or []) + if n.get("name") == state.get("active_network")), None) + return [d["ip"] for d in (active or {}).get("devices", []) + if d.get("ip") and ":" not in d["ip"]] + except Exception: + return [] + + +def set_log_level(ips, index): + """POST System.logLevel= to each device IP. The value is a numeric JSON index + (a quoted value parses to 0). Best-effort per device: a stale/absent entry is skipped, + never raised, so it can't fail the caller's real work (a KPI capture, a monitor session).""" + body = json.dumps({"module": "System", "control": "logLevel", "value": index}).encode("utf-8") + for ip in ips: + req = urllib.request.Request(f"http://{ip}/api/control", data=body, + headers={"Content-Type": "application/json"}, method="POST") + try: + urllib.request.urlopen(req, timeout=3).read() + except Exception: + pass diff --git a/moondeck/check/collect_kpi.py b/moondeck/check/collect_kpi.py index bff011f4..f8a30cfd 100644 --- a/moondeck/check/collect_kpi.py +++ b/moondeck/check/collect_kpi.py @@ -20,6 +20,10 @@ ROOT = Path(__file__).resolve().parent.parent.parent ESP32_DIR = ROOT / "esp32" +# Shared moondeck.json + logLevel-toggle helpers (one level up, reachable from check/ and run/). +sys.path.insert(0, str(ROOT / "moondeck")) +from _moondeck_config import active_device_ips, set_log_level, LOG_INFO, LOG_WARN # noqa: E402 + # Per-host desktop build dir (matches build_desktop.py / package_desktop.py). # We pick the directory belonging to the OS this script runs on so KPI # numbers reflect the binary the developer actually has on disk. @@ -287,11 +291,17 @@ def _live_capture(log, seconds=15): import serial except ImportError: return False + # Raise the device to Info so the KPI tick line prints during the capture (it rests at Warn, + # which silences it). Restore Warn afterward so the LED stops flickering again. A freshly booted + # device already logs at Info for its first 60 s, so this is a no-op there but harmless. + ips = active_device_ips() + set_log_level(ips, LOG_INFO) print(f" ESP32 KPI: capturing {seconds}s from {port}...") try: ser = serial.Serial(port, 115200, timeout=1) except Exception as e: print(f" ESP32 KPI: cannot open {port}: {e}") + set_log_level(ips, LOG_WARN) return False end = time.time() + seconds try: @@ -303,6 +313,7 @@ def _live_capture(log, seconds=15): f.flush() finally: ser.close() + set_log_level(ips, LOG_WARN) return True def collect_code(): diff --git a/moondeck/run/monitor_esp32.py b/moondeck/run/monitor_esp32.py index 4b4de46a..d2857ebe 100644 --- a/moondeck/run/monitor_esp32.py +++ b/moondeck/run/monitor_esp32.py @@ -13,12 +13,22 @@ ROOT = Path(__file__).resolve().parent.parent.parent LOG_FILE = ROOT / "esp32" / "monitor.log" +# Shared moondeck.json + logLevel-toggle helpers (one level up, reachable from check/ and run/). +sys.path.insert(0, str(ROOT / "moondeck")) +from _moondeck_config import active_device_ips, set_log_level, LOG_INFO, LOG_WARN # noqa: E402 + def main(): parser = argparse.ArgumentParser() parser.add_argument("--port", required=True, help="Serial port") parser.add_argument("--baud", type=int, default=115200, help="Baud rate") args = parser.parse_args() + # Raise the device(s) to Info so the tick line shows while monitoring; restore Warn on exit so the + # status LED stops flickering on serial TX. Best-effort β€” an un-networked device is skipped (and + # already logs at Info for its first 60 s anyway). + ips = active_device_ips() + set_log_level(ips, LOG_INFO) + print(f"Monitoring {args.port} at {args.baud} baud...") print(f"Log saved to {LOG_FILE}") print("Press Ctrl+C (or Stop in MoonDeck) to stop.\n") @@ -28,6 +38,7 @@ def main(): ser = serial.Serial(args.port, args.baud, timeout=1) except serial.SerialException as e: print(f"Cannot open {args.port}: {e}") + set_log_level(ips, LOG_WARN) # couldn't monitor; leave the device quiet sys.exit(1) with open(LOG_FILE, "w") as log: @@ -43,6 +54,7 @@ def main(): pass finally: ser.close() + set_log_level(ips, LOG_WARN) # back to quiet so the LED stops flickering print(f"\nStopped. Full log: {LOG_FILE}") if __name__ == "__main__": diff --git a/moondeck/run/preview_installer.py b/moondeck/run/preview_installer.py index 237abec0..74ef09e5 100644 --- a/moondeck/run/preview_installer.py +++ b/moondeck/run/preview_installer.py @@ -76,13 +76,18 @@ def _stage_runtime_files(src_dir: Path, dst_dir: Path): - """Copy every browser-loadable file (.html/.js/.css/.json/.png/.ico) from - src_dir to dst_dir β€” mirrors release.yml's `cp -r docs//. pages//`. - README.md / other .md are docs, skipped.""" - dst_dir.mkdir(parents=True, exist_ok=True) - for src in src_dir.iterdir(): - if src.is_file() and src.suffix.lower() in (".html", ".js", ".css", ".json", ".png", ".ico"): - shutil.copy(src, dst_dir / src.name) + """Copy every browser-loadable file (.html/.js/.css/.json/.png/.ico/.svg) from + src_dir to dst_dir β€” mirrors release.yml's `cp -r web-installer/. pages/install/`. + README.md / other .md are docs, skipped. The deploy's `cp -r` is recursive, so a + subdirectory of static assets (web-installer/assets/, the app-store badges) is + staged too β€” walk the tree rather than just the top level, or those 404 in preview + while working in production.""" + exts = (".html", ".js", ".css", ".json", ".png", ".ico", ".svg") + for src in src_dir.rglob("*"): + if src.is_file() and src.suffix.lower() in exts: + out = dst_dir / src.relative_to(src_dir) + out.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(src, out) def _stage_referenced_board_images(dst_dir: Path): diff --git a/src/core/SystemModule.h b/src/core/SystemModule.h index 321b764a..af38aab5 100644 --- a/src/core/SystemModule.h +++ b/src/core/SystemModule.h @@ -115,12 +115,28 @@ class SystemModule : public MoonModule { static_cast(chipFlashVal_ / (1024 * 1024))); } + // Apply the persisted (or default) log level to the platform logger now, so a device that + // booted with a saved Warn/Error level is quiet from the first tick rather than only after + // the user touches the control. The main loop's first-60 s override keeps Info-level output + // (the installer's MM_IP read) alive regardless of this. + applyLogLevel(); + // Chain to base so children (the wired-by-code System modules β€” Tasks, I2cScan) // get their setup() β€” a child initialises its state here. Overriding // setup() shadows the base default that would otherwise propagate. MoonModule::setup(); } + /// The persisted serial log level. The main loop reads this to decide whether to emit the + /// once-a-second KPI tick line (Info or above), so a resting device at Warn stays off the wire. + platform::LogLevel logLevel() const { return static_cast(logLevel_); } + + /// A live log-level change applies immediately (no rebuild): push it to the platform logger. + /// Changing verbosity does not reshape any derived state, so this is onControlChanged, not prepare. + void onControlChanged(const char* controlName) override { + if (std::strcmp(controlName, "logLevel") == 0) applyLogLevel(); + } + void defineControls() override { // Platform-derived totals queried here (idempotent, no I/O) so the conditionals that // gate the Progress controls see real values rather than waiting on setup(). @@ -189,6 +205,12 @@ class SystemModule : public MoonModule { // Persisted so it survives a reboot; the UI honors it client-side (see the `advanced` flag on // Control) β€” nothing in the firmware reads it, so it needs no rebuild trigger. controls_.addBool("expertMode", expertMode_); + // Serial log level: how chatty the device is on the UART. Default Warn keeps the once-a-second + // KPI tick line off (a status LED that blinks on serial TX rests quiet) while real warnings and + // errors still print. Applied to the platform logger on change (see applyLogLevel); the KPI line + // is gated in the main loop. Advanced β€” a diagnostics knob, not a casual-user control. + controls_.addSelect("logLevel", logLevel_, logLevelOptions_, 6); + controls_.setAdvanced(controls_.count() - 1); // WiFi co-processor (P4 + on-board C6) firmware read-out. Gated at compile // time on hasWifiCoprocessor, so the whole control β€” and the snprintf/query // cost β€” vanishes on native-radio builds (classic/S3/desktop) and the @@ -304,6 +326,22 @@ class SystemModule : public MoonModule { // (dev/tuning readouts and knobs a casual user doesn't need β€” e.g. MoonLed's ring diagnostics and // manual geometry). One flag the whole system's UI composes against; no module reads System's state. bool expertMode_ = false; + // Push the current level to the platform logger. Clamps to the valid enum range so a corrupt + // persisted value can't index past Verbose. + void applyLogLevel() { + uint8_t lvl = logLevel_ > static_cast(platform::LogLevel::Verbose) + ? static_cast(platform::LogLevel::Verbose) : logLevel_; + platform::setLogLevel(static_cast(lvl)); + } + + // Serial log verbosity, persisted, default Warn. Controls how chatty the device is on the wire: + // at Warn the once-a-second KPI tick line is suppressed (no serial write, so a status LED that + // flickers on UART TX rests quiet) while ESP_LOGW/ESP_LOGE warnings and errors still print. The + // main loop reads logLevel() to gate the KPI line; affectsPrepare re-applies it to the platform + // logger on change. The first 60 s of uptime always logs at Info regardless (the web installer + // reads MM_IP off the tick line just after flash). Stored as the raw enum value for addSelect. + uint8_t logLevel_ = static_cast(platform::LogLevel::Warn); + static constexpr const char* logLevelOptions_[] = {"None", "Error", "Warn", "Info", "Debug", "Verbose"}; // Physical-hardware identity (catalog entry name). 32-byte buffer fits the longest // entry ("Olimex ESP32-Gateway Rev G" = 26) with headroom; the Improv RPC handler // caps str_len against this size dynamically. diff --git a/src/light/drivers/MultiPinLedDriver.h b/src/light/drivers/MultiPinLedDriver.h index b9fb349a..127e7a24 100644 --- a/src/light/drivers/MultiPinLedDriver.h +++ b/src/light/drivers/MultiPinLedDriver.h @@ -100,15 +100,18 @@ class MultiPinLedDriver : public ParallelLedDriver { /// INTERNAL-RAM only (no PSRAM) and it holds the whole frame (no streaming ring), so a frame larger /// than the free internal DMA block simply cannot allocate β€” and the failing esp_lcd path can busy- /// wait to a watchdog reset. reinit() pre-checks against this and idles with a clear status instead. - /// Budget = HALF the largest free internal block (doubleBuffer may need two frames) minus a fixed - /// reserve for the bus descriptors + other allocations that land between this query and the alloc. + /// Budget = the largest free internal block minus a fixed reserve for the bus descriptors + other + /// allocations that land between this query and the alloc; sized for ONE frame, since busInit() + /// downgrades the optional second (doubleBuffer) buffer on its own when only one fits. The classic + /// path is bounded by construction, so it never returns 0 (which means "no bound"): when the block + /// is at or under the reserve, it reports a small positive floor so the fit gate still rejects. /// On the LCD_CAM chips (S3/P4) the DMA reaches PSRAM β†’ 0 = no bound (the base default). COLD PATH. size_t dmaBudgetBytes() const { if constexpr (platform::i2sLanes > 0) { const size_t block = platform::maxInternalAllocBlock(); constexpr size_t kReserve = 16 * 1024; // descriptors + headroom for allocs after this query - const size_t usable = block > kReserve ? block - kReserve : 0; - return usable / 2; // halve: doubleBuffer allocates the frame twice + constexpr size_t kMinBudget = 1; // never 0 on the bounded path (0 == "no bound") + return block > kReserve ? block - kReserve : kMinBudget; } else { return 0; // LCD_CAM (S3/P4): PSRAM DMA, no whole-frame ceiling } diff --git a/src/light/drivers/ParallelLedDriver.h b/src/light/drivers/ParallelLedDriver.h index 2d9cd8d2..2648d65e 100644 --- a/src/light/drivers/ParallelLedDriver.h +++ b/src/light/drivers/ParallelLedDriver.h @@ -1271,8 +1271,8 @@ class ParallelLedDriver : public DriverBase { // Whether a whole-frame DMA buffer of `frameBytes` fits the internal-DMA budget of a driver whose // DMA can't reach PSRAM (the classic i80's I2S peripheral) and holds the whole frame (no ring). - // A driver that IS so bounded calls this in parseConfig; if false it idles with a clear status - // instead of choking the bus init on an allocation the peripheral can never satisfy. `budgetBytes` + // A driver that IS so bounded calls this in reinit() (before busInit); if false it idles with a clear + // status instead of choking the bus init on an allocation the peripheral can never satisfy. `budgetBytes` // 0 means "no bound" (PSRAM-capable / ring drivers) β†’ always fits. static bool frameFitsDmaBudget(size_t frameBytes, size_t budgetBytes) { return budgetBytes == 0 || frameBytes <= budgetBytes; diff --git a/src/light/drivers/PreviewDriver.h b/src/light/drivers/PreviewDriver.h index 4d44974b..8c192e4f 100644 --- a/src/light/drivers/PreviewDriver.h +++ b/src/light/drivers/PreviewDriver.h @@ -107,6 +107,7 @@ class PreviewDriver : public DriverBase { downscale_ = 1; slowStreak_ = 0; cleanStreak_ = 0; + framesWaiting_ = 0; // the old grid's drain count must not make the new grid's first frame read slow buildAndSendCoordTable(); refreshStatus(); // surface any resumable-path degradation (alloc miss) in the tab } @@ -188,7 +189,7 @@ class PreviewDriver : public DriverBase { // frames eventually send (the slow-but-complete case a pure all-sent signal misses β€” a // full-res 128Β² frame that delivers at ~2 fps). On a sustained run of slow frames, coarsen // the lattice (downscale_++) so frames shrink and the rate climbs; a sustained run of - // prompt, fully-sent frames refines back toward full res (downscale_--). The streaks only + // prompt, fully-sent frames refines back toward full res (downscale_ >>= 1, halving). The streaks only // advance on slots where a frame completed (sentThisSlot), so a long drain counts as ONE // slow frame, not many β€” making kDownscaleAfterSlow a count of slow frames, not ticks. // Hysteresis stops oscillation; the factor rides the wire stride field to the status line. @@ -606,7 +607,7 @@ class PreviewDriver : public DriverBase { // The streamed send is all-or-nothing per client, so a frame (color or coord table) that // doesn't reach every client means the link can't keep up at this resolution: coarsen // (downscale_++) after a short run of such frames so the rebuilt lattice sends fewer points. - // A sustained run of fully-sent frames refines back toward full resolution (downscale_--). + // A sustained run of fully-sent frames refines back toward full resolution (downscale_ >>= 1, halving). // downscale_ is an extra floor on the per-axis lattice stride, composing with the cap // downsample; it rides the wire stride field to the browser's "preview 1/N Β· link limited" // status. (β‰₯1; 1 = full resolution.) Hysteresis via the streak thresholds stops oscillation. diff --git a/src/main.cpp b/src/main.cpp index 78ee601b..2ff86dee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -548,6 +548,17 @@ void mm_main(volatile bool& keepRunning, uint16_t httpPort) { lastLog = now; if (scheduler.tickTimeUs() == 0) continue; // no measurement yet + // The KPI tick line is a plain stdout printf, not an ESP_LOG, so the platform log level + // doesn't suppress it β€” we gate it here on the same level. At Info or above it prints; at + // Warn/Error/None it's silenced so a device resting quietly makes no periodic serial write + // (a status LED that blinks on UART TX stops flickering). The first 60 s of uptime always + // prints regardless: the web installer reads MM_IP off this line just after flash, and the + // window latches the same way the MM_IP token below does (a plain `< 60000` re-opens every + // ~49.7 days at the millis() wrap). Real ESP_LOGW/ESP_LOGE warnings and errors are a + // separate stream that setLogLevel governs independently, so they still surface at Warn. + const bool inBootWindow = !mmIpWindowClosed && (now - bootMillis < 60000); + if (systemModule->logLevel() < mm::platform::LogLevel::Info && !inBootWindow) continue; + heap = mm::platform::freeHeap(); std::printf("tick: %uus (FPS: %u)", static_cast(scheduler.tickTimeUs()), static_cast(scheduler.fps())); diff --git a/src/platform/desktop/platform_desktop.cpp b/src/platform/desktop/platform_desktop.cpp index 35340d01..9c79cbc6 100644 --- a/src/platform/desktop/platform_desktop.cpp +++ b/src/platform/desktop/platform_desktop.cpp @@ -434,6 +434,11 @@ const char* resetReason() { return "OK"; } +void setLogLevel(LogLevel) { + // Desktop logs to the terminal unconditionally; the KPI-line gate reads the level directly, + // so there is nothing to apply to a platform logger here. +} + size_t firmwareSize() { return 0; } size_t firmwarePartition() { return 0; } size_t flashChipSize() { return 0; } diff --git a/src/platform/esp32/platform_esp32.cpp b/src/platform/esp32/platform_esp32.cpp index 74f038a0..5b1a7014 100644 --- a/src/platform/esp32/platform_esp32.cpp +++ b/src/platform/esp32/platform_esp32.cpp @@ -364,6 +364,12 @@ const char* resetReason() { } } +void setLogLevel(LogLevel level) { + // LogLevel's values are chosen to equal esp_log_level_t (None=0 … Verbose=5), so the + // mapping is a plain cast β€” the "*" tag sets the level for every component at once. + esp_log_level_set("*", static_cast(level)); +} + size_t firmwareSize() { // Get actual running image size from the image header const esp_partition_t* part = esp_ota_get_running_partition(); diff --git a/src/platform/platform.h b/src/platform/platform.h index a0c36a04..63cd5379 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -257,6 +257,16 @@ const char* hostIp(); // "BROWNOUT", "DEEPSLEEP", or "UNKNOWN". On desktop always returns "OK". UI uses // this to flag a "crashed" prior boot (PANIC / INT_WDT / TASK_WDT / BROWNOUT). const char* resetReason(); + +// Serial log verbosity, low to high. Mirrors the standard syslog/ESP-IDF ordering so the +// numeric value maps straight onto esp_log_level_set (None=0 … Verbose=5). The periodic KPI +// tick line (a plain stdout printf, not an ESP_LOG) is emitted only at Info or above, so a +// resting device at Warn stays quiet on the wire β€” no once-a-second serial write β€” while real +// ESP_LOGW/ESP_LOGE warnings and errors still print. setLogLevel applies it to the ESP-IDF +// logger; the KPI-line gate is read from the same value in the main loop. Desktop is a no-op. +enum class LogLevel : uint8_t { None = 0, Error, Warn, Info, Debug, Verbose }; +void setLogLevel(LogLevel level); + size_t firmwareSize(); // firmware image bytes size_t firmwarePartition(); // app partition size (firmware capacity) size_t flashChipSize(); // total flash chip capacity diff --git a/test/unit/light/unit_MultiPinLedDriver.cpp b/test/unit/light/unit_MultiPinLedDriver.cpp index f7dd8c43..3b584aaa 100644 --- a/test/unit/light/unit_MultiPinLedDriver.cpp +++ b/test/unit/light/unit_MultiPinLedDriver.cpp @@ -105,7 +105,7 @@ TEST_CASE("MultiPinLedDriver frame grows on RGBW preset") { // watchdog reset on hardware). On desktop / PSRAM chips the budget is 0 (no bound), so the frame-fit // gate NEVER triggers regardless of grid size: a large frame is never rejected for its size here (the // classic-i80 branch is compiled out). Pins the "budget 0 = no bound" contract β€” the gate is inert off -// the classic chip, so this refactor changes nothing on every non-classic target. The hardware behaviour +// the classic chip, so this refactor changes nothing on every non-classic target. The hardware behavior // (a too-big frame on the real classic i80 idles with the clear "over DMA" status) is proven on the Olimex. TEST_CASE("MultiPinLedDriver: the DMA-fit gate is inert off the classic i80 (budget 0)") { mm::MultiPinLedDriver d; @@ -122,6 +122,24 @@ TEST_CASE("MultiPinLedDriver: the DMA-fit gate is inert off the classic i80 (bud CHECK(std::strstr(d.status() ? d.status() : "", "over i80 DMA") == nullptr); } +// frameFitsDmaBudget() is the pure predicate the classic-i80 gate leans on; its logic is compiled out on +// desktop (budget always 0), so exercise it directly with synthetic budgets. A FINITE budget rejects an +// oversized frame and accepts one that fits; a ZERO budget ("no bound", the LCD_CAM/PSRAM/desktop case) +// never rejects, whatever the frame size. +TEST_CASE("MultiPinLedDriver::frameFitsDmaBudget rejects only over a finite budget") { + // frameFitsDmaBudget is a protected static on the CRTP base; a tiny subclass exposes it for the + // test without widening the production class surface. + struct Expose : mm::MultiPinLedDriver { + using mm::MultiPinLedDriver::frameFitsDmaBudget; + }; + // finite budget: reject strictly-larger, accept equal-or-smaller + CHECK_FALSE(Expose::frameFitsDmaBudget(1025, 1024)); + CHECK(Expose::frameFitsDmaBudget(1024, 1024)); + CHECK(Expose::frameFitsDmaBudget(512, 1024)); + // zero budget = no bound: never rejects, however large the frame + CHECK(Expose::frameFitsDmaBudget(1u << 30, 0)); +} + // A bad pin list idles the driver with the parse literal in the status; fixing it recovers. TEST_CASE("MultiPinLedDriver bad pins β†’ status error β†’ recovery") { mm::MultiPinLedDriver d; @@ -330,7 +348,9 @@ TEST_CASE("MultiPinLedDriver hides pinExpander where the chip can't host it") { for (uint8_t i = 0; i < d.controls().count(); i++) { if (std::strcmp(d.controls()[i].name, "pinExpander") == 0) { found = true; - CHECK(d.controls()[i].hidden == true); // hidden on a chip without expander support + // Hidden exactly when the chip can't host the expander β€” ties the assertion to the flag + // rather than to the desktop's happens-to-be-unsupported value, so it stays correct on any target. + CHECK(d.controls()[i].hidden == !mm::MultiPinLedDriver::kSupportsPinExpander); } } CHECK(found); // still BOUND (a saved value survives), just not shown diff --git a/web-installer/assets/app-store-badge.svg b/web-installer/assets/app-store-badge.svg new file mode 100644 index 00000000..072b425a --- /dev/null +++ b/web-installer/assets/app-store-badge.svg @@ -0,0 +1,46 @@ + + Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web-installer/assets/google-play-badge.png b/web-installer/assets/google-play-badge.png new file mode 100644 index 0000000000000000000000000000000000000000..131f3acaa252a863c3b694d0f522ea750aebd81c GIT binary patch literal 4904 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 literal 0 HcmV?d00001 diff --git a/web-installer/assets/home-assistant-icon.png b/web-installer/assets/home-assistant-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..39f0c14e1d4289206df4325257c08d4630f3f81f GIT binary patch literal 6142 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

    projectMM Installer - ?

    Plug in your ESP32. Pick a release + device. Flash. Get the device on your network. Open it in a browser.

    @@ -201,11 +201,44 @@

    projectMM Installer