Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,30 @@
# ------------------------------------------------------------------------------

# CI/release binaries
default_envs = nodemcuv2
Comment thread
softhack007 marked this conversation as resolved.
esp8266_2m
esp01_1m_full
nodemcuv2_160
esp8266_2m_160
esp01_1m_full_160
nodemcuv2_compat
esp8266_2m_compat
esp01_1m_full_compat
esp32dev
esp32dev_debug
esp32_eth
esp32_wrover
lolin_s2_mini
esp32c3dev
esp32c3dev_qio
esp32S3_wroom2
esp32s3dev_16MB_opi
esp32s3dev_8MB_opi
esp32s3dev_8MB_qspi
esp32s3_4M_qspi
usermods
;default_envs = nodemcuv2
; esp8266_2m
; esp01_1m_full
; nodemcuv2_160
; esp8266_2m_160
; esp01_1m_full_160
; nodemcuv2_compat
; esp8266_2m_compat
; esp01_1m_full_compat
; esp32dev
; esp32dev_debug
; esp32_eth
; esp32_wrover
; lolin_s2_mini
; esp32c3dev
; esp32c3dev_qio
; esp32S3_wroom2
; esp32s3dev_16MB_opi
; esp32s3dev_8MB_opi
; esp32s3dev_8MB_qspi
; esp32s3_4M_qspi
; usermods

default_envs = esp32dev
Comment thread
softhack007 marked this conversation as resolved.
Outdated

src_dir = ./wled00
data_dir = ./wled00/data
Expand Down Expand Up @@ -534,7 +536,7 @@ build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html
-D DATA_PINS=25
lib_deps = ${esp32_idf_V4.lib_deps}

[env:esp32c3dev]
extends = esp32c3
platform = ${esp32c3.platform}
Expand Down Expand Up @@ -658,7 +660,7 @@ monitor_filters = esp32_exception_decoder

[env:esp32s3_4M_qspi]
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
platform = ${esp32s3.platform}
platform_packages = ${esp32s3.platform_packages}
upload_speed = 921600
Expand Down
46 changes: 22 additions & 24 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1954,7 +1954,7 @@ void mode_colorwaves_pride_base(bool isPride2015) {
unsigned msmultiplier = beatsin88_t(147, 23, 60);

unsigned hue16 = sHue16;
unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) :
unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) :
beatsin88_t(113, 60, 300) * SEGMENT.intensity * 10 / 255;

sPseudotime += duration * msmultiplier;
Expand Down Expand Up @@ -3763,7 +3763,7 @@ void mode_exploding_fireworks(void)
if (SEGENV.aux0 == 0) { //init flare
flare->pos = 0;
flare->posX = SEGMENT.is2D() ? hw_random16(2,cols-3) : (SEGMENT.intensity > hw_random8()); // will enable random firing side on 1D
unsigned peakHeight = 75 + hw_random8(180); //0-255
unsigned peakHeight = 84 + hw_random8(146); // 33% to 90% of 256
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the firework goes to the very top, it only explodes down, rather than in both directions. If it is too low, it mostly explodes up.

peakHeight = (peakHeight * (rows -1)) >> 8;
flare->vel = sqrtf(-2.0f * gravity * peakHeight);
flare->velX = SEGMENT.is2D() ? (hw_random8(9)-4)/64.0f : 0; // no X velocity on 1D
Expand Down Expand Up @@ -3800,6 +3800,7 @@ void mode_exploding_fireworks(void)

// initialize sparks
if (SEGENV.aux0 == 2) {
int colIndex = hw_random8();
for (unsigned i = 1; i < nSparks; i++) {
sparks[i].pos = flare->pos;
sparks[i].posX = flare->posX;
Expand All @@ -3808,7 +3809,7 @@ void mode_exploding_fireworks(void)
sparks[i].velX = SEGMENT.is2D() ? (float(hw_random16(20001)) / 10000.0f) - 1.0f : 0; // from -1 to 1
sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright
//sparks[i].col = constrain(sparks[i].col, 0, 345);
sparks[i].colIndex = hw_random8();
sparks[i].colIndex = colIndex;
sparks[i].vel *= flare->pos/rows; // proportional to height
sparks[i].velX *= SEGMENT.is2D() ? flare->posX/cols : 0; // proportional to width
sparks[i].vel *= -gravity *50;
Expand All @@ -3835,9 +3836,6 @@ void mode_exploding_fireworks(void)
c = color_blend(spColor, WHITE, uint8_t((prog - 300)*5));
} else if (prog > 45) { //fade from spark color to black
c = color_blend(BLACK, spColor, uint8_t(prog - 45));
unsigned cooling = (300 - prog) >> 5;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai is removing this block a user-visible change, or just refactoring?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@softhack007 It’s a user-visible change. That block previously biased the fade-to-black phase by reducing green/blue (a “cooling”/warming shift), so spark tails skewed a bit warmer as they dimmed. With it removed, sparks now fade linearly using the palette color (no extra channel bias), which keeps the per‑explosion color more faithful. You’ll notice it most with blue/white explosions; both 1D and 2D paths are affected. If we want the warmer tail back, we could reintroduce it (or gate it behind a flag) without touching the rest of the logic.


🧠 Learnings used
Learnt from: DedeHai
Repo: wled/WLED PR: 5379
File: wled00/FX.cpp:10865-10865
Timestamp: 2026-03-27T18:33:33.813Z
Learning: Repo: wled/WLED
File: wled00/FX.cpp
Context: Slow Transition effect (mode_slow_transition) UI metadata string _data_FX_MODE_SLOW_TRANSITION
Learning: The “Time (min)” control intentionally does not advertise the special case “0 = 10s” in the label; this shortcut is meant to be discovered by users. Do not suggest adding “0=10s” (or similar) to the label in future reviews.

Learnt from: DedeHai
Repo: wled/WLED PR: 4615
File: wled00/FX.cpp:1814-1817
Timestamp: 2026-03-29T07:49:28.820Z
Learning: WLED wled00/FX.cpp::mode_random_chase(): Advancing the shared PRNG before capturing prevSeed on the first call is intentional to decorrelate initial seeds across effects. Do not suggest moving the snapshot earlier; if needed, add a comment to document this behavior.

Learnt from: BobLoeffler68
Repo: wled/WLED PR: 5293
File: usermods/user_fx/user_fx.cpp:149-151
Timestamp: 2026-01-24T18:51:09.740Z
Learning: In WLED's Spinning Wheel effect (usermods/user_fx/user_fx.cpp), the color scale calculation (SEGENV.aux1) must match the position modulo range. When position uses `pos = (pos_fixed >> 16) % SEGLEN`, the color scale must be `aux1 = (255 << 8) / SEGLEN` to distribute the palette evenly across the full position range. Using vstripLen for color scaling while position uses SEGLEN causes palette colors to cycle too quickly and appear incomplete.

Learnt from: DedeHai
Repo: wled/WLED PR: 5434
File: wled00/colors.cpp:79-83
Timestamp: 2026-03-21T11:43:36.767Z
Learning: In WLED's `color_fade()` (wled00/colors.cpp), the `video=true` path computes `maxc = (maxc>>2) + 1` and only preserves a channel if its value strictly exceeds that threshold (`r > maxc`, etc.). This means very dark non-zero channels (e.g., r==1 or r==2) can be dropped to zero in video mode. This is intentional: it prevents flickering in corner regions of gradients and is an accepted design compromise. Do not flag this as a bug in future reviews.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR `#4798`, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: DedeHai
Repo: wled/WLED PR: 4615
File: wled00/FX.cpp:10824-10824
Timestamp: 2026-03-29T06:08:02.547Z
Learning: WLED: In wled00/FX.cpp::mode_slow_transition(), the change-detection logic intentionally compares data->currentCCT to SEGMENT.cct (not data->endCCT). SEGMENT.cct is set to currentCCT at the end of each call; comparing to endCCT would re-initialize the transition on each frame and stall CCT blending. Do not propose changing this.

Learnt from: freakintoddles2
Repo: wled/WLED PR: 4904
File: wled00/FX.cpp:3915-3930
Timestamp: 2025-09-02T19:42:57.475Z
Learning: WLED wled00/FX.cpp::mode_percent — For time-based options (% of Minute/Hour/Day), behavior is clock-like: at rollover (elapsed==0) intentionally show SEGLEN lit for one tick to represent completion, then move to 1 LED at the next second. This is by design (not a progress bar) and should not be “fixed”.

Learnt from: BobLoeffler68
Repo: wled/WLED PR: 5109
File: wled00/FX.cpp:3174-3343
Timestamp: 2025-11-27T06:33:11.436Z
Learning: WLED Ants effect (wled00/FX.cpp): The author prefers the current velocity initialization using hw_random16(1000, 5000)/5000.0f, resulting in an effective range of ~3.6–10.0 (with VELOCITY_MIN=2.0, VELOCITY_MAX=10.0), and wants the code kept as-is with comments updated to document this behavior. Avoid suggesting changes to span the full 2.0–10.0 range in future reviews.

Learnt from: netmindz
Repo: wled/WLED PR: 4728
File: wled00/FX.h:378-378
Timestamp: 2025-06-15T09:59:52.720Z
Learning: In WLED's FX.h, MODE_COUNT represents the highest FX_MODE_ ID + 1, not the total count of FX_MODE_ definitions. This is because some effects may have been removed but their IDs are not reused, creating gaps in the numbering sequence. MODE_COUNT is used for array bounds and range checking.

Learnt from: netmindz
Repo: wled/WLED PR: 4728
File: wled00/FX.h:378-378
Timestamp: 2025-06-15T09:59:52.720Z
Learning: In WLED's FX.h, MODE_COUNT represents the highest FX_MODE_ ID + 1, not the total count of FX_MODE_ definitions. This is because some effects may have been removed but their IDs are not reused, creating gaps in the numbering sequence. MODE_COUNT is used for array bounds and range checking.

Learnt from: softhack007
Repo: wled/WLED PR: 5443
File: wled00/FX_fcn.cpp:1277-1277
Timestamp: 2026-03-24T12:10:32.630Z
Learning: In WLED's `WS2812FX::service()` (wled00/FX_fcn.cpp), the old condition `|| (doShow && seg.mode == FX_MODE_STATIC)` was an **inclusion** guard — it caused FX_MODE_STATIC to render only when another segment had already set doShow=true. It did NOT skip or protect FX_MODE_STATIC from rendering. The PR `#5443` simplification removes this condition, meaning FX_MODE_STATIC now renders on every `timeToShow` tick uniformly. This is intentional and not a regression. Do not flag FX_MODE_STATIC special-casing as missing in future reviews of this function.

Learnt from: willmmiles
Repo: wled/WLED PR: 5462
File: wled00/json.cpp:1189-1198
Timestamp: 2026-03-30T15:32:08.847Z
Learning: In WLED's `respondModeData()` (wled00/json.cpp), the 256-character `lineBuffer` limit for effect descriptor strings (getModeData) is an intentional constraint that matches the same 256-char limit used ~6 other places in the codebase. It is not new to this PR and should not be flagged as a regression. Lifting it requires a future refactor (better type system or dynamic buffer).

Learnt from: BobLoeffler68
Repo: wled/WLED PR: 5440
File: usermods/user_fx/user_fx.cpp:1304-1313
Timestamp: 2026-03-25T07:03:35.475Z
Learning: In WLED `mode_dissolveplus` (usermods/user_fx/user_fx.cpp), using `hw_random16(SEGLEN)` to select the survivor pixel index is correct and safe for this 1D-only effect. The 0xFFFF unmapped-entry concern from the physical bus mapping does not apply to 1D segments because virtual indices 0..SEGLEN-1 always map to valid physical LEDs without gaps. Do not flag this as a bug in future reviews of 1D effects.

Learnt from: DedeHai
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2026-02-22T20:40:46.281Z
Learning: At low brightness (<30), color_blend() suffers from integer rounding that destroys RGB channel ratios, causing visible hue shifts during transitions (e.g., greenish tints). This can be fixed by applying hue preservation logic similar to color_fade()'s video mode: add 1 to channels that are non-zero and > 13% of max channel `(channel << 5) > maxc`. This preserves color ratios and prevents premature channel zeroing at low brightness without affecting performance at normal brightness levels.

Learnt from: DedeHai
Repo: wled/WLED PR: 4889
File: wled00/json.cpp:310-310
Timestamp: 2026-03-21T18:12:09.437Z
Learning: In WLED's `deserializeSegment()` (wled00/json.cpp), the blend mode field `seg.blendMode` is intentionally written without a post-read clamp (`getVal(elem["bm"], seg.blendMode)`). Out-of-range or unsupported blend mode values are handled safely in `WS2812FX::blendSegment()` (wled00/FX_fcn.cpp), which defaults to mode 0 for any unsupported value via a bounds check against the `BLENDMODES` constant. Do not flag the missing clamp in deserializeSegment as a bug in future reviews.

Learnt from: DedeHai
Repo: wled/WLED PR: 4615
File: wled00/FXparticleSystem.cpp:598-606
Timestamp: 2026-03-09T19:16:30.985Z
Learning: In WLED's FXparticleSystem.cpp, the particle system (both 1D and 2D) is intentionally RGB-only and does not process or output the white channel. The `fast_color_scaleAdd()` function discards the W byte by design. Even though `CRGBW` is used internally for color representation (e.g., `baseRGB`, palette lookups via `ColorFromPalette`), the W channel is never rendered. Do not flag the missing W channel handling in particle system rendering paths as a bug.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-12-28T14:06:48.772Z
Learning: In WLED post-commit ee9ac947, the rendering pipeline uses per-segment buffers and per-pixel bus updates. Unmapped (0xFFFF) mapping entries are now skipped in WS2812FX::show() (no “clear to black”), which can leave physical gap LEDs with stale/random colors unless they are explicitly cleared. This is a behavior change from pre-0.16 where a full physical buffer was effectively refreshed each frame.

Learnt from: BobLoeffler68
Repo: wled/WLED PR: 5251
File: usermods/user_fx/user_fx.cpp:146-148
Timestamp: 2026-01-01T07:19:40.244Z
Learning: In the WLED Ants effect (usermods/user_fx/user_fx.cpp), the color alternation logic `antIndex % 3 == 1` is intentional and creates a 1/3 vs 2/3 distribution between SEGCOLOR(0) and SEGCOLOR(2). This unbalanced alternation is by design and should not be changed to a balanced mod 2 alternation.

Learnt from: softhack007
Repo: wled/WLED PR: 5355
File: wled00/util.cpp:635-638
Timestamp: 2026-02-07T16:06:08.677Z
Learning: PSRAM-related compilation guards should enable PSRAM code only for ESP32 variants that actually include PSRAM: ESP32-C61, ESP32-C5, and ESP32-P4. Exclude ESP32-C3, ESP32-C6, and ESP8266 from these guards. Apply this rule across the codebase (not just wled00/util.cpp) by reviewing and updating PSRAM guards/macros in all relevant files (C/C++ headers and sources).

Learnt from: softhack007
Repo: wled/WLED PR: 4893
File: wled00/set.cpp:95-95
Timestamp: 2026-03-14T20:56:46.543Z
Learning: Guideline: Ensure WiFi hostname is set after WiFi.mode() but before WiFi.begin() to avoid default esp-XXXXXX hostname being used in DHCP. This ordering only takes effect after the STA interface exists (so avoid placing hostname setting before initConnection). In WLED, place the hostname configuration inside initConnection() (after WiFi.disconnect(true) and before WiFi.begin()) rather than in earlier boot code like deserializeConfig(). This rule should be applied in code reviews for WLED’s network initialization paths in wled00/*.cpp, and note that on ESP8266 the ordering is less strict but still desirable for consistency.

Learnt from: softhack007
Repo: wled/WLED PR: 4838
File: lib/NeoESP32RmtHI/src/NeoEsp32RmtHIMethod.cpp:30-35
Timestamp: 2026-03-27T12:33:48.499Z
Learning: In C/C++ preprocessor conditionals (`#if`, `#elif`) GCC/Clang treat `&&` as short-circuit evaluated during preprocessing. This means guards like `#if defined(ARDUINO_ARCH_ESP32) && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)` are safe even if the macro/function-like macro on the RHS (e.g., `ESP_IDF_VERSION_VAL`) is not defined on some targets, because the RHS will not be expanded when the LHS is false (e.g., `defined(...)` evaluates to 0). During code review, avoid flagging such cases as “undefined function-like macro invocation” if they are protected by short-circuiting `defined(...) && ...`/`||` logic; some tools like cppcheck may not model this and can produce false positives. Also, don’t suggest refactoring that moves ESP32-specific includes/headers (e.g., `esp_idf_version.h`) outside of these guarded preprocessor blocks, since that will break targets (e.g., ESP8266) where the headers don’t exist.

Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: wled00/cfg.cpp:673-673
Timestamp: 2026-03-27T21:17:45.980Z
Learning: When calling raw lwIP APIs (e.g., around `ntpUdp.begin()` or any `lwIP`/`tcpip`-layer call) in this codebase on ESP32 Arduino-ESP32 platforms where core locking/checking is enabled, wrap the lwIP call with `LOCK_TCPIP_CORE()` / `UNLOCK_TCPIP_CORE()` from `lwip/tcpip.h`. This prevents thread-safety/core-violation crashes without requiring `sdkconfig` changes.

Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: wled00/cfg.cpp:673-673
Timestamp: 2026-03-27T21:17:45.980Z
Learning: When using lwIP “raw” APIs in WLED on ESP32 (Arduino-ESP32 / IDF 5.5+), don’t rely on LOCK_TCPIP_CORE()/UNLOCK_TCPIP_CORE() unless CONFIG_LWIP_TCPIP_CORE_LOCKING=y is guaranteed. CONFIG_LWIP_CHECK_THREAD_SAFETY=y can trigger the assertion “Required to lock TCPIP core functionality!” when raw lwIP calls occur off the TCPIP thread. If the locking mode isn’t enabled (or can’t be changed via sdkconfig), schedule lwIP work (e.g., ntpUdp.begin() and similar raw lwIP calls) via tcpip_callback() so it runs on the TCPIP thread; this should work regardless of the locking-mode setting. Review any similar raw lwIP usage for correct thread/context handling.

Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: wled00/wled.cpp:698-700
Timestamp: 2026-03-28T01:37:15.541Z
Learning: In this WLED codebase, when using `DEBUG_PRINTLN(F("..."))`, an explicit trailing `\n` inside the `F("...")` string (e.g., `DEBUG_PRINTLN(F("Warning!\n"))`) may be intentional to create a blank line in debug output as a visual separator. During code review, do not automatically flag these as “double newline” or recommend removing the `\n`—first verify with the author/context that the extra newline is deliberate.

Learnt from: willmmiles
Repo: wled/WLED PR: 5462
File: wled00/json.cpp:1189-1198
Timestamp: 2026-03-30T15:32:02.808Z
Learning: When working with WLED strings stored in PROGMEM on ESP8266/ESP32, assume you can’t use `strchr_P` for character scanning. If you need to scan a PROGMEM string for a character (e.g., searching for '@' within effect data), review changes to ensure they perform an explicit RAM copy first (e.g., via `strncpy_P` into a buffer) and then scan in RAM. Avoid proposing incremental/streaming PROGMEM character-by-character scans without a RAM buffer on these targets, since it’s impractical with the available APIs.

Learnt from: DedeHai
Repo: wled/WLED PR: 5464
File: wled00/FX_fcn.cpp:1699-1701
Timestamp: 2026-04-09T07:26:09.816Z
Learning: In WLED’s WLED code, if a pixel/buffer allocation uses `BFRALLOC_NOBYTEACCESS` (and especially on classic ESP32 where byte-level access to IRAM-resident buffers is unsafe), avoid using byte-wise operations like `memset`/`memcpy` on that buffer. Specifically, do not combine `BFRALLOC_CLEAR | BFRALLOC_NOBYTEACCESS` and do not perform `memcpy`/`memset` over `Segment::pixels` (e.g., in `setGeometry()`/`finalizeInit()` or copy ctor/assignment). Instead, use element-wise 32-bit access (loop over `uint32_t*` and assign/copy per element) to ensure 32-bit access only.

Learnt from: DedeHai
Repo: wled/WLED PR: 5464
File: wled00/FX_fcn.cpp:1699-1701
Timestamp: 2026-04-09T09:14:29.218Z
Learning: In WLED, when reviewing ESP32 code that uses pixel buffers allocated with `BFRALLOC_NOBYTEACCESS` (e.g., `WS2812FX::_pixels` and `Segment::pixels`), treat `memset`/`memcpy` on those buffers as an intentionally low-risk, accepted pattern. These buffers are designed to be IRAM-safe for 32-bit-only access, and the Xtensa newlib assembly implementations perform 32-bit word stores for word-aligned, word-multiple-sized buffers (so the IRAM constraint is satisfied in practice). Do not flag `memset`/`memcpy` on `BFRALLOC_NOBYTEACCESS` pixel buffers as a critical bug; if any concern arises, downgrade severity to low and focus on potential future regressions rather than an immediate correctness violation.

c.g = qsub8(c.g, cooling);
c.b = qsub8(c.b, cooling * 2);
Copy link
Copy Markdown
Author

@RussStringham RussStringham Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code comes from the original algorithm code. In that code the firework always explodes as white, then fades to yellow, before fading to black. Where the firework here can be any color. If it is already yellow it doesn't fade at all. If it is blue or green it fades completely before the fade to black even starts.

}
if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(int(sparks[i].posX), rows - int(sparks[i].pos) - 1, c);
else SEGMENT.setPixelColor(int(sparks[i].posX) ? rows - int(sparks[i].pos) - 1 : int(sparks[i].pos), c);
Expand Down Expand Up @@ -4285,7 +4283,7 @@ void mode_sunrise() {

for (unsigned i = 0; i <= SEGLEN/2; i++)
{
//default palette is Fire
//default palette is Fire
unsigned wave = triwave16((i * stage) / SEGLEN);
wave = (wave >> 8) + ((wave * SEGMENT.intensity) >> 15);
uint32_t c;
Expand Down Expand Up @@ -4976,13 +4974,13 @@ void mode_ColorClouds()

// Higher values make the clouds move faster.
const uint32_t volSpeed = 1 + SEGMENT.speed;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RussStringham please revert all "whitespace only" changes. They are not necessary, and will cause problems in case we want to cherry-pick your PR from one branch to another.


// Higher values make the color change faster.
const uint32_t hueSpeed = 1 + SEGMENT.intensity;

// Higher values make more clouds (but smaller ones).
const uint32_t volSqueeze = 8 + SEGMENT.custom1;

// Higher values make the clouds more colorful.
const uint32_t hueSqueeze = SEGMENT.custom2;

Expand Down Expand Up @@ -5352,7 +5350,7 @@ void mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Ye
for (int j=0; j < cols; j++) {
for (int i=0; i < rows; i++) {
indexx = perlin8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map.
SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
} // for i
} // for j
} // mode_2Dfirenoise()
Expand Down Expand Up @@ -5386,7 +5384,7 @@ typedef struct Cell {
uint8_t alive : 1, faded : 1, toggleStatus : 1, edgeCell: 1, oscillatorCheck : 1, spaceshipCheck : 1, unused : 2;
} Cell;

void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/
void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/
// and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler
if (!strip.isMatrix || !SEGMENT.is2D()) FX_FALLBACK_STATIC; // not a 2D set-up
const int cols = SEG_W, rows = SEG_H;
Expand Down Expand Up @@ -6606,7 +6604,7 @@ void mode_2Dplasmarotozoom() {
float *a = reinterpret_cast<float*>(SEGENV.data);
byte *plasma = reinterpret_cast<byte*>(SEGENV.data+sizeof(float));

unsigned ms = strip.now/15;
unsigned ms = strip.now/15;

// plasma
for (int j = 0; j < rows; j++) {
Expand Down Expand Up @@ -6836,7 +6834,7 @@ void mode_gravcenter_base(unsigned mode) {
if(mode == 2) offset = 0; // Gravimeter
if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset;
else if (gravcen->gravityCounter % gravity == 0) gravcen->topLED--;

if(mode == 1) { //Gravcentric
for (int i=0; i<tempsamp; i++) {
uint8_t index = segmentSampleAvg*24+strip.now/200;
Expand Down Expand Up @@ -6880,7 +6878,7 @@ void mode_gravcenter_base(unsigned mode) {
SEGMENT.setPixelColor(gravcen->topLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
}
}
gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity;
}

Expand Down Expand Up @@ -7142,26 +7140,26 @@ void mode_puddles_base(bool peakdetect) {
if (pos+size>= SEGLEN) size = SEGLEN - pos;
}
}
else { // puddles
else { // puddles
if (volumeRaw > 1) {
size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume.
if (pos+size >= SEGLEN) size = SEGLEN - pos;
}
}
}

for (unsigned i=0; i<size; i++) { // Flash the LED's.
SEGMENT.setPixelColor(pos+i, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0));
}
}

void mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
mode_puddles_base(true);
}
}
static const char _data_FX_MODE_PUDDLEPEAK[] PROGMEM = "Puddlepeak@Fade rate,Puddle size,Select bin,Volume (min);!,!;!;1v;c2=0,m12=0,si=0"; // Pixels, Beatsin

void mode_puddles(void) { // Puddles. By Andrew Tuline.
mode_puddles_base(false);
}
}
static const char _data_FX_MODE_PUDDLES[] PROGMEM = "Puddles@Fade rate,Puddle size;!,!;!;1v;m12=0,si=0"; // Pixels, Beatsin


Expand Down Expand Up @@ -9860,7 +9858,7 @@ void mode_particleFireworks1D(void) {
PartSys->applyFriction(1); // apply friction to all particles

PartSys->update(); // update and render

for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
if (PartSys->particles[i].ttl > 20) PartSys->particles[i].ttl -= 20; //ttl is linked to brightness, this allows to use higher brightness but still a short spark lifespan
else PartSys->particles[i].ttl = 0;
Expand Down Expand Up @@ -11052,7 +11050,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_COLORTWINKLE, &mode_colortwinkle, _data_FX_MODE_COLORTWINKLE);
addEffect(FX_MODE_LAKE, &mode_lake, _data_FX_MODE_LAKE);
addEffect(FX_MODE_METEOR, &mode_meteor, _data_FX_MODE_METEOR);
//addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor
//addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor
addEffect(FX_MODE_RAILWAY, &mode_railway, _data_FX_MODE_RAILWAY);
addEffect(FX_MODE_RIPPLE, &mode_ripple, _data_FX_MODE_RIPPLE);
addEffect(FX_MODE_TWINKLEFOX, &mode_twinklefox, _data_FX_MODE_TWINKLEFOX);
Expand All @@ -11070,7 +11068,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_SPARKLE, &mode_sparkle, _data_FX_MODE_SPARKLE);
addEffect(FX_MODE_GLITTER, &mode_glitter, _data_FX_MODE_GLITTER);
addEffect(FX_MODE_SOLID_GLITTER, &mode_solid_glitter, _data_FX_MODE_SOLID_GLITTER);
addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET);
addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET);
#ifdef WLED_PS_DONT_REPLACE_1D_FX
addEffect(FX_MODE_ROLLINGBALLS, &mode_rolling_balls, _data_FX_MODE_ROLLINGBALLS);
addEffect(FX_MODE_STARBURST, &mode_starburst, _data_FX_MODE_STARBURST);
Expand All @@ -11096,7 +11094,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_SINEWAVE, &mode_sinewave, _data_FX_MODE_SINEWAVE);
addEffect(FX_MODE_PHASEDNOISE, &mode_phased_noise, _data_FX_MODE_PHASEDNOISE);
addEffect(FX_MODE_FLOW, &mode_flow, _data_FX_MODE_FLOW);
addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN);
addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN);
addEffect(FX_MODE_WASHING_MACHINE, &mode_washing_machine, _data_FX_MODE_WASHING_MACHINE);
addEffect(FX_MODE_BLENDS, &mode_blends, _data_FX_MODE_BLENDS);
addEffect(FX_MODE_TV_SIMULATOR, &mode_tv_simulator, _data_FX_MODE_TV_SIMULATOR);
Expand Down
2 changes: 1 addition & 1 deletion wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2099,5 +2099,5 @@ const char JSON_palette_names[] PROGMEM = R"=====([
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura",
"Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2","Retro Clown","Candy","Toxy Reaf","Fairy Reaf",
"Semi Blue","Pink Candy","Red Reaf","Aqua Flash","Yelblu Hot","Lite Light","Red Flash","Blink Red","Red Shift","Red Tide",
"Candy2","Traffic Light"
"Candy2","Traffic Light","Fireworks"
])=====";
2 changes: 1 addition & 1 deletion wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

constexpr size_t FASTLED_PALETTE_COUNT = 7; // 6-12 = sizeof(fastledPalettes) / sizeof(fastledPalettes[0]);
constexpr size_t GRADIENT_PALETTE_COUNT = 59; // 13-72 = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]);
constexpr size_t GRADIENT_PALETTE_COUNT = 60; // 13-73 = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]);
constexpr size_t DYNAMIC_PALETTE_COUNT = 6; // 0- 5 = dynamic palettes (0=default(virtual),1=random,2=primary,3=primary+secondary,4=primary+secondary+tertiary,5=primary+secondary(+tertiary if not black)
constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT + GRADIENT_PALETTE_COUNT; // total number of fixed palettes
#ifndef ESP8266
Expand Down
5 changes: 3 additions & 2 deletions wled00/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,7 @@ function loadPalettesData() {
if (lsPalData) {
try {
var d = JSON.parse(lsPalData);
if (d && d.vid == lastinfo.vid) {
if (d && d.vid == lastinfo.vid && d.pcount == lJson.length) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RussStringham what is the purpose of this change? is it a bugfix?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Fireworks palette didn't display the palette at the bottom of the selector, because the cache wasn't regenerated since the vid didn't change. This forced a cache update for the new palette.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually a fix for a long standing bug.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fix is actually incomplete. I will add the correct version in a seperate PR

palettesData = d.p;
redrawPalPrev();
return resolve();
Expand All @@ -2824,7 +2824,8 @@ function loadPalettesData() {
getPalettesData(0, () => {
localStorage.setItem("wledPalx", JSON.stringify({
p: palettesData,
vid: lastinfo.vid
vid: lastinfo.vid,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RussStringham please explain

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the comment for line 2815

pcount: lJson.length
}));
redrawPalPrev();
setTimeout(resolve, 99); // delay optional
Expand Down
21 changes: 20 additions & 1 deletion wled00/palettes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,24 @@ const byte trafficlight_gp[] PROGMEM = {
170, 255, 255, 0, //yellow
255, 255, 0, 0}; //red

// Fireworks palette: colors sized by real-world frequency
// red/blue ~22%, green ~18%, violet ~15%, orange ~11%, white ~7%, yellow ~5%
const byte fireworks_gp[] PROGMEM = {
0, 255, 0, 0, // red (start)
55, 255, 0, 0, // red (end)
56, 0, 0, 220, // blue (start)
112, 0, 0, 220, // blue (end)
113, 0, 210, 0, // green (start)
158, 0, 210, 0, // green (end)
159, 148, 0, 211, // violet (start)
197, 148, 0, 211, // violet (end)
198, 255, 80, 0, // orange (start)
224, 255, 80, 0, // orange (end)
225, 255, 255, 255, // white (start)
243, 255, 255, 255, // white (end)
244, 255, 210, 0, // yellow (start)
255, 255, 210, 0}; // yellow (end)

const byte Aurora2_gp[] PROGMEM = {
0, 17, 177, 13, //Greenish
64, 121, 242, 5, //Greenish
Expand Down Expand Up @@ -863,5 +881,6 @@ const uint8_t* const gGradientPalettes[] PROGMEM = {
red_shift_gp, //68-55 Red Shift
red_tide_gp, //69-56 Red Tide
candy2_gp, //70-57 Candy2
trafficlight_gp //71-58 Traffic Light
trafficlight_gp, //71-58 Traffic Light
fireworks_gp //72-59 Fireworks
};
Loading