Skip to content

Conversation

@DedeHai
Copy link
Collaborator

@DedeHai DedeHai commented Jan 3, 2026

reopening as #5215 was closed.

Summary by CodeRabbit

  • New Features

    • Added support for an additional dynamic palette option.
  • Bug Fixes

    • Improved palette boundary validation and selection logic.
    • Fixed palette indexing calculations to ensure correct palette rendering across different palette sources.
    • Enhanced custom palette mapping to prevent out-of-bounds access.

✏️ Tip: You can customize this high-level summary in your review settings.

- use constants instead of magic numbers
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

Walkthrough

The changes refactor palette handling logic across multiple files to use a fixed palette count constant (FIXED_PALETTE_COUNT) instead of dynamic counting. DYNAMIC_PALETTE_COUNT is increased from 5 to 6, affecting palette boundaries, sorting, indexing, and rendering throughout the codebase.

Changes

Cohort / File(s) Summary
Palette Constants
wled00/const.h
Updated DYNAMIC_PALETTE_COUNT from 5 to 6, which modifies FIXED_PALETTE_COUNT and WLED_MAX_CUSTOM_PALETTES calculations. Range documentation now reflects 0–5 for dynamic palettes.
Core Palette Loading
wled00/FX_fcn.cpp
Adjusted boundary checks for out-of-bounds palette detection (pal >= FIXED_PALETTE_COUNT now triggers out-of-bounds path). Refined progmem palette lookup conditions and replaced hardcoded 72-byte memcpy with sizeof-aware copy. Updated index calculations for fastled palette selection.
Palette Serialization & Rendering
wled00/json.cpp
Replaced dynamic palette counting with FIXED_PALETTE_COUNT constant. Refactored palette index mapping logic and loop bounds (inclusive to exclusive). Updated palette source selection for custom, fastled, and gradient palettes with corrected offset calculations.
UI Palette Handling
usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp
Modified sortModesAndPalettes to allocate based on FIXED_PALETTE_COUNT instead of getPaletteCount(). Sorting now targets only fixed palettes, skipping custom palettes. Custom palette mapping adjusted to use FIXED_PALETTE_COUNT+i indexing.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • #4932 — Directly related palette boundary and constant refactoring (FIXED_PALETTE_COUNT, DYNAMIC_PALETTE_COUNT) that establishes the foundation for these index and sorting changes.

Suggested reviewers

  • blazoncek
  • willmmiles
  • Aircoookie

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Palettes fix' is vague and generic, using a broad non-descriptive term that doesn't convey meaningful information about the specific palette-related changes. Provide a more specific title that describes the particular palette issue being fixed, such as 'Fix palette boundary and indexing logic' or 'Refactor palette handling with fixed counts'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp (1)

414-416: Consider replacing magic number 1 with a constant or clarifying the comment.

The comment suggests DYNAMIC_PALETTE_COUNT could be used, but that equals 6 (skipping all dynamic palettes), whereas skipPaletteCount = 1 only skips "Default" before the while loop increments it past the *-prefixed palettes.

If the intent is to always skip dynamic palettes from sorting, consider:

-  int skipPaletteCount = 1; // could use DYNAMIC_PALETTE_COUNT instead
-  while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++; // legacy code
+  int skipPaletteCount = DYNAMIC_PALETTE_COUNT; // skip dynamic palettes (0-5) from sorting

Otherwise, clarify the comment to explain why 1 is used (to include "Default" in sorting while still skipping *-prefixed entries via the while loop).

Based on learnings, magic numbers should be replaced with constants when meaningful.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60e1698 and acfb8b2.

📒 Files selected for processing (4)
  • usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp
  • wled00/FX_fcn.cpp
  • wled00/const.h
  • wled00/json.cpp
🧰 Additional context used
📓 Path-based instructions (2)
wled00/**/!(html_*)*.h

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 2-space indentation for non-generated C++ header files (.h)

Files:

  • wled00/const.h
wled00/**/*.cpp

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 2-space indentation for C++ source files (.cpp)

Files:

  • wled00/json.cpp
  • wled00/FX_fcn.cpp
🧠 Learnings (18)
📓 Common learnings
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: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.
Learnt from: blazoncek
Repo: wled/WLED PR: 5140
File: wled00/data/settings_time.htm:66-76
Timestamp: 2025-12-01T07:01:16.949Z
Learning: In WLED PR #5134, the fix for macros being initialized with the enable bit set only handles new configurations, not existing ones. If there is a bug in timer/macro handling code (e.g., in settings_time.htm), it must be fixed to work correctly for existing configurations as well.
Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.
📚 Learning: 2025-04-26T19:19:07.600Z
Learnt from: blazoncek
Repo: wled/WLED PR: 4658
File: wled00/const.h:140-141
Timestamp: 2025-04-26T19:19:07.600Z
Learning: In WLED, the WLED_MAX_PANELS macro is intentionally defined as a fixed constant value (18) with no redefinition mechanism, making it "unoverridable" - there's no need for a static assertion to check its maximum value.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
📚 Learning: 2025-08-28T08:09:20.630Z
Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-11-14T13:37:30.955Z
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-11-14T13:37:11.994Z
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-08-31T03:38:14.114Z
Learnt from: BobLoeffler68
Repo: wled/WLED PR: 4891
File: wled00/FX.cpp:3333-3349
Timestamp: 2025-08-31T03:38:14.114Z
Learning: WLED PacMan effect (wled00/FX.cpp): Keep pacmancharacters_t position fields as signed int (not int16_t). Maintainer preference (blazoncek) prioritizes avoiding potential overhead/regressions over minor RAM savings. Avoid type shrinking here unless memory pressure is demonstrated.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-08-26T11:51:21.817Z
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.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-11-16T19:40:46.260Z
Learnt from: DedeHai
Repo: wled/WLED PR: 4926
File: wled00/FX.cpp:4727-4730
Timestamp: 2025-11-16T19:40:46.260Z
Learning: WLED AuroraWave (wled00/FX.cpp): wave_start and wave_end intentionally use int16_t; segments longer than 32k LEDs are not supported (bounded by MAX_LEDS), so widening to 32-bit is unnecessary.

Applied to files:

  • wled00/const.h
  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-11-27T06:33:11.436Z
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.

Applied to files:

  • wled00/const.h
📚 Learning: 2025-06-15T09:59:52.720Z
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.

Applied to files:

  • wled00/const.h
📚 Learning: 2025-10-20T09:38:51.997Z
Learnt from: blazoncek
Repo: wled/WLED PR: 4995
File: wled00/FX.cpp:5223-5226
Timestamp: 2025-10-20T09:38:51.997Z
Learning: WLED matrices: each dimension (SEG_W, SEG_H) is limited to ≤255; 256 or larger per side is not supported/feasible on ESP32, so effects should assume per-dimension max 255.

Applied to files:

  • wled00/const.h
📚 Learning: 2025-11-22T12:12:53.486Z
Learnt from: DedeHai
Repo: wled/WLED PR: 5105
File: wled00/FX.h:968-968
Timestamp: 2025-11-22T12:12:53.486Z
Learning: In WLED's WS2812FX class (wled00/FX.h), the _pixels array stores LED colors indexed by unmapped (logical) LED positions, not physical positions. The getPixelColor(n) function intentionally checks if the logical LED at index n maps to a valid physical position via getMappedPixelIndex(n), then accesses _pixels[n] with the unmapped index. If the mapping is invalid (e.g., -1 for gaps in LED maps, or out of bounds), it returns 0 (black). This allows peek preview to correctly show gaps in LED mappings as black pixels. The mapping from logical to physical positions is only applied when writing to the hardware bus, not when reading from the pixel buffer.
<!-- [add_learning]

Applied to files:

  • wled00/const.h
📚 Learning: 2025-05-09T18:43:15.355Z
Learnt from: DedeHai
Repo: wled/WLED PR: 4682
File: wled00/FX.cpp:8997-9005
Timestamp: 2025-05-09T18:43:15.355Z
Learning: In the WLED codebase, SEGMENT.custom3 is always constrained to the range 0-31 and will not exceed this range.

Applied to files:

  • wled00/const.h
📚 Learning: 2025-10-10T18:34:06.550Z
Learnt from: DedeHai
Repo: wled/WLED PR: 4997
File: wled00/e131.cpp:33-44
Timestamp: 2025-10-10T18:34:06.550Z
Learning: In WLED's DDP packet handling (ws.cpp and e131.cpp), only prevent out-of-bounds memory access rather than enforcing DDP spec compliance. Don't check the 1440-byte spec limit—accept out-of-spec packets assuming correct encoding. The bounds check `maxDataIndex = c + numLeds * ddpChannelsPerLed; if (maxDataIndex > dataLen) reject` is sufficient and already covers the timecode flag case (when c=4) without needing separate validation.

Applied to files:

  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-12-28T14:06:48.764Z
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-12-28T14:06:48.764Z
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.

Applied to files:

  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-10-05T15:24:05.545Z
Learnt from: CR
Repo: wled/WLED PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-05T15:24:05.545Z
Learning: Applies to wled00/html_*.h : DO NOT edit generated embedded web header files (wled00/html_*.h)

Applied to files:

  • wled00/json.cpp
📚 Learning: 2025-12-15T20:25:25.815Z
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-12-15T20:25:25.815Z
Learning: The CSS palette preview in wled00/data/index.js genPalPrevCss() function uses raw RGB values in CSS linear-gradient() without applying WLED's gamma correction, while actual LED output goes through NeoGammaWLEDMethod gamma correction. This causes inherent discrepancies between the web UI palette preview and actual LED colors, especially noticeable with different gamma settings.

Applied to files:

  • wled00/json.cpp
  • wled00/FX_fcn.cpp
📚 Learning: 2025-11-14T05:48:44.673Z
Learnt from: DedeHai
Repo: wled/WLED PR: 5040
File: wled00/image_loader.cpp:84-96
Timestamp: 2025-11-14T05:48:44.673Z
Learning: In WLED (wled00/FX_2Dfcn.cpp), the Segment::setPixelColorXY() function performs internal bounds checking against vWidth() and vHeight(), returning early if coordinates are out of bounds. No additional guards are needed when calling this function, even in upscaling loops where coordinates might exceed segment dimensions.

Applied to files:

  • wled00/FX_fcn.cpp
🧬 Code graph analysis (1)
usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp (1)
wled00/colors.h (1)
  • getPaletteCount (127-127)
🪛 Clang (14.0.6)
wled00/const.h

[error] 9-9: unknown type name 'constexpr'

(clang-diagnostic-error)


[error] 9-9: expected ';' after top level declarator

(clang-diagnostic-error)


[error] 10-10: unknown type name 'constexpr'

(clang-diagnostic-error)


[error] 10-10: expected ';' after top level declarator

(clang-diagnostic-error)


[error] 11-11: unknown type name 'constexpr'

(clang-diagnostic-error)


[error] 11-11: expected ';' after top level declarator

(clang-diagnostic-error)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_8MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32s3_4M_qspi)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_16MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32c3dev)
  • GitHub Check: wled_build / Build Environments (esp32_eth)
  • GitHub Check: wled_build / Build Environments (esp32dev)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full)
  • GitHub Check: wled_build / Build Environments (esp32c3dev_qio)
  • GitHub Check: wled_build / Build Environments (nodemcuv2_compat)
  • GitHub Check: wled_build / Build Environments (esp32S3_wroom2)
  • GitHub Check: wled_build / Build Environments (usermods)
  • GitHub Check: wled_build / Build Environments (esp32_wrover)
  • GitHub Check: wled_build / Build Environments (lolin_s2_mini)
  • GitHub Check: wled_build / Build Environments (esp32dev_debug)
  • GitHub Check: wled_build / Build Environments (esp8266_2m)
  • GitHub Check: wled_build / Build Environments (esp8266_2m_160)
  • GitHub Check: wled_build / Build Environments (nodemcuv2)
  • GitHub Check: Analyze (c-cpp)
🔇 Additional comments (7)
wled00/const.h (1)

9-12: LGTM! Good use of constexpr constants for palette counts.

The introduction of FIXED_PALETTE_COUNT and the documented index ranges (0-5 dynamic, 6-12 FastLED, 13-71 gradient) clearly replaces previous magic numbers with maintainable constants. The comments accurately reflect the computed values: 6 + 7 + 59 = 72 fixed palettes.

Note: The static analysis "unknown type name 'constexpr'" errors are false positives—Clang is likely parsing as C rather than C++11+.

Based on learnings, replacing magic numbers with named constants improves maintainability.

wled00/FX_fcn.cpp (2)

233-233: LGTM! Correct out-of-bounds palette handling.

The condition pal >= FIXED_PALETTE_COUNT && pal <= 255-customPalettes.size() correctly identifies palette indices that fall in the gap between fixed palettes (0-71) and custom palettes (255 downwards), resetting them to the default palette.


271-276: LGTM! Palette index calculations are correct and use proper constants.

The logic correctly handles:

  • FastLED palettes (indices 6-12): pal - DYNAMIC_PALETTE_COUNT yields array indices 0-6
  • Gradient palettes (indices 13-71): pal - (DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT) yields array indices 0-58

Using sizeof(tcp) instead of hardcoded 72 for the memcpy_P is a good practice for maintainability. Based on learnings, this aligns with the goal of replacing magic numbers with size-aware constructs.

usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.cpp (1)

404-409: LGTM! Correct allocation and custom palette mapping.

The allocation uses getPaletteCount() (= FIXED_PALETTE_COUNT + customPalettes.size()), and custom palettes are correctly mapped to indices FIXED_PALETTE_COUNT + i with values 255 - i, matching WLED's custom palette ID scheme.

wled00/json.cpp (3)

948-960: LGTM! Clean pagination logic with proper constant usage.

The use of constexpr for itemPerPage and FIXED_PALETTE_COUNT for palettesCount improves maintainability. The pagination bounds are correctly calculated with min() preventing overflow.


965-966: LGTM! Correct palette index mapping for JSON keys.

The index calculation i >= palettesCount ? 255 - i + palettesCount : i correctly maps:

  • Fixed palettes (0-71) → use index directly
  • Custom palettes (array index 72+) → map to palette IDs 255, 254, 253...

995-1001: LGTM! Palette source selection uses correct offsets.

The cascading conditions correctly identify:

  • Custom palettes: i >= palettesCount → index into customPalettes[i - palettesCount]
  • FastLED palettes (6-12): i < DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNTfastledPalettes[i - DYNAMIC_PALETTE_COUNT]
  • Gradient palettes (13-71): gGradientPalettes[i - (DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT)]

Using sizeof(tcp) for the memcpy_P size is consistent with the changes in FX_fcn.cpp.

@DedeHai DedeHai merged commit 5cfb6f9 into main Jan 3, 2026
83 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants