Skip to content

Add moving gap to Chase 2 version 2#5507

Open
RussStringham wants to merge 9 commits intowled:mainfrom
RussStringham:running-skip
Open

Add moving gap to Chase 2 version 2#5507
RussStringham wants to merge 9 commits intowled:mainfrom
RussStringham:running-skip

Conversation

@RussStringham
Copy link
Copy Markdown

@RussStringham RussStringham commented Apr 15, 2026

This PR is an alternate implementation for PR-5504. Only one or the other should be merged. Here is the description:

I have added a new slider to Chase 2 that generates values between 0 and 15. When this slider is at its default value of 0, it behaves exactly like the current version of Chase 2. When the slider is greater than 0, it is treated as a gap value. At any instance in time, the result looks the same as when a gap is specified in the segment definition. However, when the stripe moves by one LED, it moves to the next physical LED, rather than the next lit LED. This results is the gaps rotating as well.

In this PR, the gap color is controled by Cs (color 3) instead of always being black. I have also simplified the running() function so that the theater modes only differ from Chase 2 by the parameters that are passed. There is no special logic in the function to handle theater differently than chase. In this case, the theater BG color is the gap color and the theater width is the gap width.

In the previous PR the gap is called the skip value.

Summary by CodeRabbit

  • New Features

    • Added a Gap parameter to control stripe spacing.
    • Added a third color for off/filled regions to expand visual options.
    • Exposed Gap and Width in the Running Color effect metadata.
  • Refactor

    • Reworked chase/running effects to a stripe-based model for finer control of width, spacing, motion, and color handling.
    • Safer parameter clamping and smoother, more predictable motion.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The internal running effect was refactored to stripe-based rendering with a new signature (color1, color2, color3, skip, width); per-LED placement, clamped parameters, stripe geometry and phase/progression were changed. Three public mode callers and the FX_MODE_RUNNING_COLOR metadata string were updated accordingly.

Changes

Cohort / File(s) Summary
Running Effect Implementation
wled00/FX.cpp
Replaced theatre/window renderer with stripe-segment logic. running() signature changed to running(uint32_t color1, uint32_t color2, uint32_t color3, int skip, int width). Clamps width/skip, computes pitch, stripe_len, period, phase from SEGENV.aux0, uses modular arithmetic to assign color1 (foreground), color2 (background) or color3 (elsewhere), and advances motion by updating SEGENV.aux0 based on phase/period.
Public Mode Callers
wled00/FX.cpp
Updated mode_theater_chase(), mode_theater_chase_rainbow(), and mode_running_color() to call the new running() signature. Theater-chase modes pass width=1, compute skip = 2 + (SEGMENT.intensity >> 4) and use the same chase color for color1/color2; mode_running_color() computes skip = SEGMENT.custom1 >> 4, width = 1 + (SEGMENT.intensity >> 4), and passes SEGCOLOR(2) as color3.
Effect Metadata
wled00/FX.cpp
Updated _data_FX_MODE_RUNNING_COLOR metadata string to include Skip and set c1=0 (changed from "Chase 2@!,Width;!,!;!" to "Chase 2@!,Width,Skip;!,!,!;!;;c1=0").

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

enhancement, effect

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Add moving gap to Chase 2 version 2' is partially related to the changeset. The PR summary refers to 'Add moving skip' but the title says 'moving gap', which are related but not identical concepts. The title correctly identifies this as a Chase 2 enhancement, but uses slightly imprecise terminology compared to the actual implementation (skip vs. gap).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@wled00/FX.cpp`:
- Around line 554-576: SEGENV.aux0 can be out-of-range if period shrinks; after
computing period (based on width/skip/pitch) but before rendering the loop that
uses pos, normalize SEGENV.aux0 to the new period (guarding against period being
zero) by doing something like: if (period > 0 && SEGENV.aux0 >= period)
SEGENV.aux0 %= period; this ensures pos calculations in the for-loop (which
reference SEGENV.aux0) stay correct until the next movement tick updates aux0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 590a12ed-2b11-4c01-b48f-d27485df7032

📥 Commits

Reviewing files that changed from the base of the PR and between ba377d7 and 865e231.

📒 Files selected for processing (1)
  • wled00/FX.cpp

Comment thread wled00/FX.cpp Outdated
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
wled00/FX.cpp (1)

554-579: ⚠️ Potential issue | 🟡 Minor

Clamp the saved phase to the new period before rendering.

If Width/Skip is reduced while the effect is already running, SEGENV.aux0 can still be larger than the new period. On Line 562 that makes the dividend negative, so % can stay negative and the next frame renders the wrong stripe pattern until Line 578 advances again.

Suggested fix
   int pitch = skip + 1;
   int stripe_len = width * pitch - skip;
   int period = 2 * width * pitch;
+  int phase = SEGENV.aux0 % period;
 
   for (unsigned i = 0; i < SEGLEN; i++) {
     int col = color3;
-    int pos = ((int)(i % period) - (int)SEGENV.aux0 + period) % period;
+    int pos = ((int)(i % period) - phase + period) % period;
     if (pos < stripe_len && (pos % pitch == 0)) {
       if (usePalette) color1 = SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 0);
       col = color1;                       // foreground stripe
@@
   }
 
   if (it != SEGENV.step) {
-    SEGENV.aux0 = (SEGENV.aux0 + 1) % period;
+    SEGENV.aux0 = (phase + 1) % period;
     SEGENV.step = it;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wled00/FX.cpp` around lines 554 - 579, SEGENV.aux0 can remain >= the new
period when width/skip shrink, causing the modulus math for pos to produce
negative values and misrender; clamp SEGENV.aux0 to the new period range before
rendering by reducing SEGENV.aux0 modulo period (or set to min(SEGENV.aux0,
period-1)) right after computing int period and before the for-loop that
computes pos, so subsequent uses of SEGENV.aux0 produce valid non-negative
positions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@wled00/FX.cpp`:
- Around line 554-579: SEGENV.aux0 can remain >= the new period when width/skip
shrink, causing the modulus math for pos to produce negative values and
misrender; clamp SEGENV.aux0 to the new period range before rendering by
reducing SEGENV.aux0 modulo period (or set to min(SEGENV.aux0, period-1)) right
after computing int period and before the for-loop that computes pos, so
subsequent uses of SEGENV.aux0 produce valid non-negative positions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b9b82ab2-b472-41b0-a62a-b92fa4c39e67

📥 Commits

Reviewing files that changed from the base of the PR and between 865e231 and 0969948.

📒 Files selected for processing (1)
  • wled00/FX.cpp

RussStringham and others added 2 commits April 14, 2026 23:10
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
wled00/FX.cpp (1)

556-563: ⚠️ Potential issue | 🟡 Minor

Normalize phase before modulo position math.

Line 562 can produce negative pos when SEGENV.aux0 is larger than a newly reduced period (C++ % keeps dividend sign), causing transient wrong rendering until the next tick.

🔧 Proposed fix
   int pitch = skip + 1;
-  int stripe_len = width * pitch - skip;
+  int stripe_len = width * pitch - skip;
   int period = 2 * width * pitch;
+  int phase = SEGENV.aux0 % period;
 
   for (unsigned i = 0; i < SEGLEN; i++) {
     uint32_t col = color3;
-    int pos = ((int)(i % period) - (int)SEGENV.aux0 + period) % period;
+    int pos = ((int)(i % period) - phase + period) % period;
@@
   if (it != SEGENV.step) {
-    SEGENV.aux0 = (SEGENV.aux0 + 1) % period;
+    SEGENV.aux0 = (phase + 1) % period;
     SEGENV.step = it;
   }

Also applies to: 578-578

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wled00/FX.cpp` around lines 556 - 563, Normalize the phase before doing the
modulo position math: compute a reducedPhase = (int)SEGENV.aux0 % period (ensure
period>0) and then use pos = ((int)(i % period) - reducedPhase + period) %
period so the subtraction cannot produce values outside the -period..period
range; update the same logic used at the second occurrence around the later pos
calculation (the one at line ~578) to use reducedPhase as well. Ensure casts to
int are applied consistently.
🧹 Nitpick comments (1)
wled00/FX.cpp (1)

557-557: Use camelCase for new local variable names.

stripe_len is newly introduced snake_case; stripeLen would match project C++ naming rules.

As per coding guidelines: "Use camelCase for C++ function and variable names".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wled00/FX.cpp` at line 557, The new local variable stripe_len should be
renamed to camelCase to match project conventions; update the declaration and
all its uses to stripeLen (e.g., in FX.cpp where stripe_len is computed as
"width * pitch - skip") so references in the surrounding function (the FX
rendering/stripe calculation block) use stripeLen consistently and rebuild to
ensure no remaining snake_case occurrences.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@wled00/FX.cpp`:
- Around line 556-563: Normalize the phase before doing the modulo position
math: compute a reducedPhase = (int)SEGENV.aux0 % period (ensure period>0) and
then use pos = ((int)(i % period) - reducedPhase + period) % period so the
subtraction cannot produce values outside the -period..period range; update the
same logic used at the second occurrence around the later pos calculation (the
one at line ~578) to use reducedPhase as well. Ensure casts to int are applied
consistently.

---

Nitpick comments:
In `@wled00/FX.cpp`:
- Line 557: The new local variable stripe_len should be renamed to camelCase to
match project conventions; update the declaration and all its uses to stripeLen
(e.g., in FX.cpp where stripe_len is computed as "width * pitch - skip") so
references in the surrounding function (the FX rendering/stripe calculation
block) use stripeLen consistently and rebuild to ensure no remaining snake_case
occurrences.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8b5ec2ee-7f59-4970-b501-d34c72ceaa85

📥 Commits

Reviewing files that changed from the base of the PR and between 0969948 and 3781475.

📒 Files selected for processing (1)
  • wled00/FX.cpp

Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@wled00/FX.cpp`:
- Around line 546-573: The function running() references undeclared symbols
usePalette, usePalette2, and it; add explicit parameters or local declarations
to fix this: update running(...) signature to include bool usePalette and bool
usePalette2 (matching the do_palette pattern used by chase()), and declare a
local uint32_t it computed the same way other mode functions do (e.g., uint32_t
it = strip.now / cycleTime or the equivalent timing expression used elsewhere),
then use those variables in the existing logic (leave calls to
SEGMENT.color_from_palette and SEGENV.aux0/step updates as-is).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 29022d7e-7091-4185-95f0-1a56f5cc9bc8

📥 Commits

Reviewing files that changed from the base of the PR and between 3781475 and e69efe7.

📒 Files selected for processing (1)
  • wled00/FX.cpp

Comment thread wled00/FX.cpp Outdated
@DedeHai
Copy link
Copy Markdown
Collaborator

DedeHai commented Apr 15, 2026

I think version2 is better as it has the additional color.
To me "skip" is not the right term, it better be called "gap". also you need to add a checkmark as it breaks existing presets otherwise: to test, create a preset in the current version, then update to the PR and see if it changes.

@RussStringham
Copy link
Copy Markdown
Author

@DedeHai I have renamed "skip" to "gap" in the code and the UI.

There is no need for a checkmark. The theater modes work exactly as before. Chase 2 defaults to a gap value of zero. When it is zero, it behaves exactly as the previous version, so previously saved presets will be unchanged.

@RussStringham RussStringham changed the title Add moving skip to Chase 2 version 2 Add moving gap to Chase 2 version 2 Apr 16, 2026
@DedeHai
Copy link
Copy Markdown
Collaborator

DedeHai commented Apr 16, 2026

There is no need for a checkmark.

there is. an existing preset does not use the defaults. please test it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants