-
Notifications
You must be signed in to change notification settings - Fork 2
Add 10 stateless and stateful effects #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| # Objective Assessment of the Project | ||
|
|
||
| Based on the code, specs (`docs/moonmodules/`), architecture docs, and `docs/plan.md`. | ||
|
|
||
| --- | ||
|
|
||
| ## Short Conclusion | ||
|
|
||
| This is **no longer a "specs-only" project**. There is a **real end-to-end pipeline** running (layout → layer → effects/modifier → blend/LUT → drivers → HTTP/WebSocket UI), with **serious testing** and **working ESP32 hardware**. The structure aligns well with the v3 philosophy (simple, data-driven, minimal magic). | ||
|
|
||
| At the same time, it is still **far from the complete vision** described in the README/architecture (many effects, LED drivers, WiFi, persistence, multi-layer support, parallelism). The README status ("architecture phase, implementation starting") is **outdated**. | ||
|
|
||
| **Overall:** strong **technical foundation + process** (~7/10), but the end-user product is still **about halfway there** (~4–5/10 compared to Release 1.0 in `plan.md`). | ||
|
|
||
| --- | ||
|
|
||
| # How Far Along Is It? | ||
|
|
||
| ## What *is* already done (core system) | ||
|
|
||
| | Area | Status | | ||
| |------|--------| | ||
| | **MoonModule + controls + scheduler** | Complete, consistently used | | ||
| | **Pipeline** | LayoutGroup → GridLayout → Layer → effects → modifier → DriverGroup → ArtNet + Preview | | ||
| | **Mapping** | MappingLUT, MirrorModifier, BlendMap, 1:1 optimization without extra buffer | | ||
| | **Effects** | Rainbow, Noise | | ||
| | **Drivers** | ArtNet send, Preview (WebSocket binary frames) | | ||
| | **HTTP API** | `/api/state`, `/api/control`, `/api/system`, module CRUD (`POST/DELETE /api/modules`) | | ||
| | **Web UI** | Vanilla JS, WebSocket, sliders/toggles/text, **WebGL 3D preview** | | ||
| | **Desktop** | Builds and runs (`mmv3`, port 8080) | | ||
| | **ESP32** | Ethernet (Olimex Gateway), same pipeline, live scenarios on hardware | | ||
| | **Tooling** | MoonDeck, platform-boundary check, scenario runners (in-process + live) | | ||
| | **Tests** | 10 unit test files + 5 JSON scenarios + live scenarios (desktop + ESP32) | | ||
|
|
||
| The promoted specs in `docs/moonmodules/` (18 total) mostly match the implementation in `src/`, which is unusually good for an agent-driven project. | ||
|
|
||
| --- | ||
|
|
||
| ## What is still missing (or intentionally postponed) | ||
|
|
||
| From `docs/plan.md` (items 9–13) and draft specs: | ||
|
|
||
| - **System MoonModule** as an actual module (diagnostics partially exist in `/api/system`, but not as a MoonModule in the tree) | ||
| - **WiFi**, **config persistence**, **UI type picker** + dynamic effect switching from the browser | ||
| - **README quick-start** (you already got it working; the repo docs have not caught up) | ||
| - **WS2812 / APA102 / direct DMX output** — currently only ArtNet network output | ||
| - **Many effects/layouts** from `moonmodules_draft/` (Wheel, GameOfLife, Ripples, Rotate, ...) | ||
| - **Multi-layer support** (architecture docs describe Layer A/B/C; code currently uses a single `Layer` in `main.cpp`, and `DriverGroup` comments reference "multi-layer later") | ||
| - **Parallelism / core affinity** — documented, not implemented in the scheduler | ||
| - **Teensy / Raspberry Pi support** — only mentioned in docs, no `src/platform/teensy` etc. | ||
|
|
||
| ### Rough completion estimates | ||
|
|
||
| - **Vertical slice (single installation, ArtNet + browser):** ~**65–70%** | ||
| - **Full architectural vision** (all platforms, all protocols, rich effects library): ~**25–30%** | ||
| - **Release 1.0** ("flash, WiFi, browser, settings persistence"): item 8 seems complete; 9–13 still open → ~**50%** toward that milestone | ||
|
|
||
| --- | ||
|
|
||
| # How Well Is It Built? | ||
|
|
||
| ## Strong Points | ||
|
|
||
| ### 1. Architecture and discipline | ||
|
|
||
| `CLAUDE.md`, `architecture.md`, promoted specs, and `check_platform_boundary.py` create a **real engineering framework**. Platform-specific code is isolated in `src/platform/`; the rest compiles everywhere. That prevents the typical drift seen in v1/v2. | ||
|
|
||
| ### 2. The MoonModule pattern actually works | ||
|
|
||
| One lifecycle (`setup` → `onBuildControls` → `onAllocateMemory` → `loop` / `loop20ms`), generic children, `ModuleRole`, and a runtime CRUD factory. Learnable and extensible without requiring UI rewrites for every effect. | ||
|
|
||
| ### 3. Memory-conscious design | ||
|
|
||
| The `memory-1to1` and `memory-lut` scenarios prove intentional memory decisions (no LUT buffer for 1:1 mappings, but one for mirror mappings). `performance.md` measures both desktop and ESP32 performance — unusually useful this early. | ||
|
|
||
| ### 4. Test strategy | ||
|
|
||
| Unit → scenario → live HTTP tests is **mature** for embedded/C++. Hardware verification on 128×128 without PSRAM is explicitly documented in `testing.md`. | ||
|
|
||
| ### 5. UI philosophy | ||
|
|
||
| No npm/runtime dependency chain in the UI; controls are rendered from module state. WebSocket + debounce + in-place updates follow the original UI spec from v1 — much of it is already implemented in `app.js`. | ||
|
|
||
| ### 6. Code style | ||
|
|
||
| Header-only modules, `constexpr`, `std::span`, `-Werror`, and no TODOs in `src/`. Fits the "understandable in 30 seconds" philosophy per file (except perhaps `HttpServerModule.h`). | ||
|
|
||
| --- | ||
|
|
||
| ## Weak Points / Technical Debt | ||
|
|
||
| ### 1. `HttpServerModule.h` is a monolith | ||
|
|
||
| HTTP, WebSocket, JSON parsing, static files, CRUD — everything lives in one large header. Functional, but the opposite of "single-file simplicity" from a maintenance perspective. | ||
|
|
||
| ### 2. Rebuild propagation is coarse | ||
|
|
||
| Every control change calls `scheduler_->rebuild()` → triggering `onAllocateMemory()` on **all** top-level modules. The architecture docs describe fine-grained propagation; this is not there yet. | ||
|
|
||
| ### 3. The layer pipeline is intentionally limited | ||
|
|
||
| One modifier during LUT build; multiple sequential effects are supported, but the default stack in `main.cpp` is fixed. Runtime CRUD exists via the API, but the **UI** lacks a type picker (`/api/types` does not exist yet). | ||
|
|
||
| ### 4. ESP32 performance | ||
|
|
||
| According to `performance.md`, at 128×128, roughly **51% of the tick time is ArtNet UDP** — no pacing/limiting yet as recommended in `decisions.md`. Functionally fine (~17 FPS), but not scalable to "10,000+ LEDs" on this chip without optimization. | ||
|
|
||
| ### 5. Documentation vs reality | ||
|
|
||
| The README still says "implementation starting"; `plan.md` describes live scenarios as "next steps" while `testing.md` states they already pass on hardware. This is confusing for new developers. | ||
|
|
||
| ### 6. Platform breadth | ||
|
|
||
| Vision = ESP32 + desktop + Teensy + Raspberry Pi. | ||
| Implementation = desktop + ESP32 (Ethernet). The rest remains roadmap material. | ||
|
|
||
| --- | ||
|
|
||
| # Evaluation by Dimension | ||
|
|
||
| | Dimension | Score | Notes | | ||
| |-----------|------|------| | ||
| | **Architecture (design)** | 8/10 | Clear core/domain separation, MoonModule everywhere, strong docs | | ||
| | **Core implementation** | 7/10 | Pipeline works, tested, hardware-proven | | ||
| | **Extensibility** | 7/10 | Factory + specs; HttpServer/UI not yet fully generic for "everything from browser" | | ||
| | **Testing & quality** | 8/10 | Strong for project size; includes live + memory scenarios | | ||
| | **Product/UX (end-user)** | 5/10 | Works locally; no WiFi flash flow, persistence, or type picker | | ||
| | **Performance (ESP32)** | 6/10 | 128×128 works; ArtNet dominates; no LED DMA path | | ||
| | **Documentation** | 7/10 | Excellent internally; README/plan are out of sync | | ||
|
|
||
| --- | ||
|
|
||
| # Comparison to Earlier Iterations (`docs/history/`) | ||
|
|
||
| This feels like a **deliberate response to v1/v2 bloat**: | ||
|
|
||
| - Less "framework for the framework" | ||
| - Specs before code | ||
| - Strict platform boundaries and checklists | ||
| - One working pipeline instead of 60 effects without tests | ||
|
|
||
| The project is beyond the "prototype" stage, but not yet at MoonLight/WLED-level breadth in terms of effects and drivers. | ||
|
|
||
| --- | ||
|
|
||
| # What I Would Prioritize (for reference only) | ||
|
|
||
| As a product owner, aligned with `plan.md`: | ||
|
|
||
| 1. Update README + quick-start | ||
| 2. System MoonModule + WiFi (for Release 1.0) | ||
| 3. Config persistence | ||
| 4. UI type picker + module switching (API is partially there already) | ||
| 5. ArtNet pacing/batching on ESP32 | ||
|
|
||
| --- | ||
|
|
||
| # One-Sentence Summary | ||
|
|
||
| The project is **technically solid and well-controlled** for an early v3 cycle, with a **working LED pipeline and serious testing**; however, it is **not yet a complete end-user product** where "a customer flashes an ESP32 and starts playing with effects," and the **README significantly understates** how far the implementation already is. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Checkerboard 2D Effect | ||
|
|
||
| Animated checker pattern with two configurable hues. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool) — from `EffectBase` | ||
| - `cell_size` (uint8_t, default 4, range 1-32) — cell width/height in grid units | ||
| - `bpm` (uint8_t, default 60, range 1-255) — phase shift speed (cells appear to move) | ||
| - `hue_a` (uint8_t, default 0) — colour of even cells | ||
| - `hue_b` (uint8_t, default 128) — colour of odd cells | ||
|
|
||
| ## Rendering | ||
|
|
||
| Checker bit from `(x/cell + y/cell + phase) & 1`. `dynamicBytes()` = 0. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test](../../../testing.md#stateless-effects) — non-zero output, spatial variation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Fire 2D Effect | ||
|
|
||
| Classic demoscene fire simulation on the XY plane. Maintains a `width x height` heat field; sparks spawn at the bottom row, drift upward with cooling, and are mapped to a black-red-yellow-white palette. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool, default true) — inherited from `EffectBase` | ||
| - `cooling` (uint8_t, default 55, range 10-200) — heat loss per frame (higher = shorter flames) | ||
| - `sparking` (uint8_t, default 120, range 50-255) — probability of new sparks at the bottom row | ||
| - `hue_shift` (uint8_t, default 0, range 0-255) — rotate the fire palette around the colour wheel (0 = classic fire, 96 = green ghost-fire, 160 = blue plasma-fire) | ||
|
|
||
| ## Rendering | ||
|
|
||
| Per frame (in this order): | ||
|
|
||
| 1. **Cool** every cell by a small random amount. | ||
| 2. **Rise** — each row averages from the row below (4-tap neighbourhood), heat propagates from `y = h-1` up toward `y = 0`. | ||
| 3. **Sparks** — up to 4 random sparks at the bottom row each frame, gated by `sparking`. | ||
| 4. **Render** the heat field to RGB via the fire palette (or hue-rotated HSV when `hue_shift != 0`). | ||
|
|
||
| Integer-only, no floats. Internal PRNG (LCG) avoids `rand()`. | ||
|
|
||
| ## Memory | ||
|
|
||
| Allocates `width * height` bytes for the heat buffer in `onAllocateMemory()` when `enabled` is true. Freed in `teardown()` and when disabled. Toggling `enabled` triggers a scheduler rebuild that (re)allocates. | ||
|
|
||
| | Logical size | Heat buffer | | ||
| |--------------|-------------| | ||
| | 64x64 | 4 KB | | ||
| | 128x128 | 16 KB | | ||
|
|
||
| `dynamicBytes()` reports the live size. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test: FireEffect](../../../testing.md#fire) — buffer becomes non-zero after several frames of sparking. | ||
|
|
||
| ## Prior art | ||
|
|
||
| Standard demoscene fire (Lode's tutorials, FastLED's `Fire2012`). Adapted to the integer-only, no-Arduino style of this codebase. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Glow Particles 2D Effect | ||
|
|
||
| Soft-glowing particles rendered as a metaball field. Particles move with independent velocities and bounce off the edges; the per-pixel field summation produces chaotic organic blobs — like `MetaballsEffect` with more freedom of movement. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool) — from `EffectBase` | ||
| - `count` (uint8_t, default 5, range 1-8) — number of glow sources | ||
| - `speed` (uint8_t, default 60, range 1-255) — movement speed | ||
| - `radius` (uint8_t, default 24, range 4-64) — influence radius (larger = more merging) | ||
| - `hue_shift` (uint8_t, default 0, range 0-255) — global hue rotation | ||
|
|
||
| ## Rendering | ||
|
|
||
| Position update uses 12.4 fixed-point arithmetic. Per pixel: `field += (radius² × 64) / (dx² + dy² + 1)` across all active particles. Brightness clamps to 255; hue derives from the field magnitude. | ||
|
|
||
| No heap allocations. Per-particle state: 8 bytes × 8 = 64 bytes. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test](../../../testing.md#stateless-effects) — non-zero output, spatial variation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Lava Lamp 2D Effect | ||
|
|
||
| Three slow blobs whose summed field is mapped through a black → red → orange → yellow → white palette. Atmospheric, fluid look — like a real lava lamp rather than the bright HSV of `MetaballsEffect`. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool) — from `EffectBase` | ||
| - `bpm` (uint8_t, default 8, range 1-64) — orbit speed in beats per minute | ||
| - `radius` (uint8_t, default 36, range 8-80) — blob influence radius | ||
| - `intensity` (uint8_t, default 200, range 64-255) — how strongly the field maps into the palette | ||
|
|
||
| ## Rendering | ||
|
|
||
| Three integer-orbited blobs (`sin8` for x/y at independent phases and speeds). Per pixel: `field += (radius² × 64) / (dx² + dy² + 1)` summed over the blobs, then `palette_[(field × intensity) >> 8]`. Palette is a 256-entry constexpr table in flash (768 bytes). No heap allocations. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test](../../../testing.md#stateless-effects) — non-zero output, spatial variation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Metaballs 2D Effect | ||
|
|
||
| Four "blobs" moving on the XY plane via integer sin/cos, with a metaball field summation per pixel. Visually similar to a lava lamp — blobs fluidly merge and separate. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool, default true) — inherited from `EffectBase` | ||
| - `bpm` (uint8_t, default 30, range 1-255) — orbit speed in beats per minute | ||
| - `radius` (uint8_t, default 28, range 4-64) — ball influence radius (larger = more merging) | ||
| - `hue_shift` (uint8_t, default 0, range 0-255) — rotate the resulting hue | ||
|
|
||
| ## Rendering | ||
|
|
||
| Per frame: | ||
| - Compute 4 ball positions `(bx, by)` using `sin8()` at different phases and orbit speeds. Stateless apart from a phase accumulator (BPM-stable). | ||
|
|
||
| Per pixel: | ||
| - For each ball: `field += (radius^2 * 64) / (dx^2 + dy^2 + 1)` | ||
| - Brightness = clamped `field`; hue = `(field >> 1) + hue_shift` | ||
| - Output via `hsvToRgb(hue, 240, brightness)` | ||
|
|
||
| Four divisions per pixel — acceptable for desktop and ESP32 LX7. No floats, no heap (`dynamicBytes()` = 0). | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test: MetaballsEffect](../../../testing.md#metaballs) — non-zero output, spatial variation. | ||
|
|
||
| ## Prior art | ||
|
|
||
| Classic demoscene effect (1980s). Same integer field-summation technique as countless WLED ports. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Particles 2D Effect | ||
|
|
||
| A swarm of particles drifting on the XY plane with persistent trails. Each particle has fixed-point position, velocity, and hue. A private RGB trail buffer is faded each frame, particles are drawn on top, and the trail buffer is copied to the layer buffer (which the Layer clears every frame). | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool, default true) — inherited from `EffectBase` | ||
| - `count` (uint8_t, default 32, range 1-64) — number of active particles | ||
| - `speed` (uint8_t, default 80, range 1-255) — velocity multiplier | ||
| - `fade` (uint8_t, default 240, range 200-255) — trail persistence (255 = no fade, 200 = quick fade) | ||
| - `hue_shift` (uint8_t, default 0, range 0-255) — rotate all particle hues | ||
|
|
||
| ## Rendering | ||
|
|
||
| Per frame: | ||
|
|
||
| 1. **Fade** every byte in the trail buffer via `scale8(byte, fade)` (integer multiply, no float). | ||
| 2. **Update + draw** — for each active particle: advance position using 12.4 fixed-point math, bounce off edges, draw RGB into the trail buffer. | ||
| 3. **Copy** the trail buffer into the layer buffer. | ||
|
|
||
| Maximum particles is `MAX_PARTICLES = 64` (a compile-time constant). Particle state is a fixed array — no heap allocation for the particle list itself. | ||
|
|
||
| ## Memory | ||
|
|
||
| Allocates `width * height * channelsPerLight` bytes for the persistent trail buffer in `onAllocateMemory()` when `enabled` is true. Freed in `teardown()` and when disabled. | ||
|
|
||
| | Logical size | Trail buffer (RGB) | | ||
| |--------------|--------------------| | ||
| | 64x64 | 12 KB | | ||
| | 128x128 | 48 KB | | ||
|
|
||
| Particle list (`64 * 8` bytes) is part of `sizeof(ParticlesEffect)`, not `dynamicBytes()`. `dynamicBytes()` reports only the trail buffer. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test: ParticlesEffect](../../../testing.md#particles) — buffer becomes non-zero after one frame (particles draw immediately). | ||
|
|
||
| ## Prior art | ||
|
|
||
| Classic "snow"/"stars"/"fireflies" effect from many LED firmwares. The fade-and-draw approach (a.k.a. *afterimage*) matches FastLED's `fadeToBlackBy` idiom. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Plasma 2D Effect | ||
|
|
||
| Animated plasma pattern from four summed sine waves on orthogonal and diagonal axes. Default effect in the desktop and ESP32 pipeline. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `bpm` (uint8_t, default 30, range 1-255) — animation speed in beats per minute | ||
| - `scale_x` (uint8_t, default 16, range 1-64) — horizontal wave length in grid cells (`step = 256 / scale_x`) | ||
| - `scale_y` (uint8_t, default 16, range 1-64) — vertical wave length in grid cells | ||
| - `hue_shift` (uint8_t, default 0, range 0-255) — rotates the entire color wheel | ||
|
|
||
| ## Rendering | ||
|
|
||
| Four `sin8` lookups per pixel (256-byte constexpr LUT in flash, no float, no heap). Waves: | ||
|
|
||
| - Horizontal: `sin8(x * step_x + t1)` | ||
| - Vertical: `sin8(y * step_y + t2)` — hoisted per row | ||
| - Diagonal: `sin8(x * step_x + y * step_x - t3)` | ||
| - Anti-diagonal: `sin8(x * step_y + 128 - y * step_y + t1)` | ||
|
|
||
| Sum averaged (`>> 2`), add `hue_shift`, map via `hsvToRgb(hue, 255, 255)`. | ||
|
|
||
| ### Performance | ||
|
|
||
| - No division or modulo in the inner loop — `step_x`/`step_y` computed once per frame | ||
| - Nested `for (y) for (x)` with row pointer — no `i % w` per pixel | ||
| - Y-dependent terms hoisted outside the x-loop | ||
| - `dynamicBytes()` = 0 — no `onAllocateMemory` override | ||
|
|
||
| Phase accumulator matches NoiseEffect pattern — BPM changes do not jump the animation. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test: PlasmaEffect](../../../testing.md#plasma) — non-zero output, spatial variation, differs from NoiseEffect. | ||
|
|
||
| Default pipeline uses Plasma + MirrorModifier (see `src/main.cpp`). | ||
|
|
||
| ## Prior art | ||
|
|
||
| Classic demoscene plasma effect (sum of sines). Integer sin8 LUT approach matches FastLED-style tables. No direct v1/v2 module port — simpler than NoiseEffect (no hash/bilinear). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Plasma Palette 2D Effect | ||
|
|
||
| Same four-sine plasma field as `PlasmaEffect`, but colours come from a 256-entry fire-ocean RGB palette in flash instead of `hsvToRgb`. | ||
|
|
||
| ## Controls | ||
|
|
||
| - `enabled` (bool) — from `EffectBase` | ||
| - `bpm` (uint8_t, default 30, range 1-255) | ||
| - `scale_x` (uint8_t, default 16, range 1-64) | ||
| - `scale_y` (uint8_t, default 16, range 1-64) | ||
|
|
||
| ## Rendering | ||
|
|
||
| Plasma index `((s1+s2+s3+s4)>>2)` maps through `palette_[256]` (768 bytes flash). `dynamicBytes()` = 0. | ||
|
|
||
| ## Tests | ||
|
|
||
| [Module test](../../../testing.md#stateless-effects) — non-zero output, spatial variation. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assessment is inconsistent with this PR's changes.
This assessment document describes features as missing that are actually being delivered in this PR:
/api/types, adds picker card, wire add/delete/move actions).RipplesEffectis added in layer 5./api/typesdoes not exist yet," but layer 6 addsGET /api/typesinHttpServerModule.Since this document is part of the PR and dated the same month, readers will assume it reflects the post-merge state, making these claims misleading.
Recommendation: Either update the assessment to reflect the state after this PR, or clearly label it as a "pre-PR baseline" snapshot for historical reference.
Also applies to: 44-44, 47-47, 102-102
🤖 Prompt for AI Agents