WLED pattern porting?

So I hooked up a few of the new Hex panels I got to a new Atom lite (in the same shipment), and flashed it with the latest WLED. And I was reminded of a few things:

  1. WLED has almost no matrix/2D support… there is some in the WLED reactive fork, but not yet in the main. PB blows it away if you have anything but a string of lights. Mapping in PB, especially as we make it easier to map for newbies, is far and away the killer feature nobody else is close to… if someone codes in FastLED, they can use a map generator but they still have to write the code by hand, and it’s not nearly as easy to do so as in PB.

  2. WLED builds in dozens of ‘effects’, combined with dozens of ‘palettes’. Mixing and matching (most but not all effects use the palette selected) means it’s got a large number of built-ins, but really, many of the effects are variants, so it’s not as diverse as it seems. I suspect if you counted the number of patterns in the PB library, we probably have more actual different ‘effects’, by far.

That said, I’d like to propose a group effort, open to anyone who wants to help:

5cnz1k
Port ALL the things!

The “re-org” of the pattern library into more of a github style is coming (soon?)
WLED bundles all of it’s built-in effects into just a file or two. Split that into concrete and fairly small tasks, we could build PB equivs (or better) for each one.

This could be a good way to folks learning to code in PB to feel really accomplished and contribute back. Some of those patterns are pretty easy to do in PB, perhaps easier than in WLED.

Who’s interested?

1 Like

That’s a great idea, and as a starting point can I suggest that it would be an idea to put together a compatibility library? IIRC, WLED stuff is written for FastLED so some concepts are completely orthogonal to the PB way and other things can be fairly easily ported as library-able functions.

What I’m thinking is that we’d probably want a skeleton program that defines a FastLED-like environment with pixel framebuffers and a standard render() function to output them, and as as many compatibility functions as we can provide to make the process of “porting” mostly a copy-and-paste into the preRender() function and some minor syntax fixups.

I’ve already started playing with a couple of FastLED patterns so I made my own FastLED-like skeleton:

//  Framebuffers
var pixelReds = array(pixelCount);
var pixelGreens = array(pixelCount);
var pixelBlues = array(pixelCount);
// standard renderer
export function render(index) { RGB(pixelReds[index], pixelGreens[index], pixelBlues[index]); }

and a PB function to mimic the “EVERY_N_MILLISECONDS” macro:

////////////////////////////////////////////////
//  FASTLED emulation functions (mine)
var maxTimers = 10;
var elapsedTime = array(maxTimers);
function EVERY_N_MILLISECONDS(delta, accumulator, target, func) {
  elapsedTime[accumulator] += delta;
  if (elapsedTime[accumulator] > target) {
    elapsedTime[accumulator] = 0;
    func();
  }
}

Then to use it:

// Just an example; a real pattern ought to do something more interesting!
export var hue = 0;
function changeHue() {
  hue = (hue + 1/6) % 1;
    for (index=0; index<numPixels; index++) {
        pixelReds[index] = hue;
        pixelGreens[index] = hue;
        pixelBlues[index] = hue;
    }
}
export var brightness = 0;
function changeBrightness() {
  brightness = (brightness + 1/10) % 1;
}
export function beforeRender(delta) {
  EVERY_N_MILLISECONDS(delta, 0, 500, changeHue);
  EVERY_N_MILLISECONDS(delta, 1, 50, changeBrightness);
}

Easy patterns like chasers will be simple enough to port, but a lot of the nicest patterns depend on things like palettes, blending, blurring and fading functions that we don’t have yet.

And at the moment I’m struggling with the difference in floating point representations and what FastLED functions do internally with them; for instance, the pattern code may calculate a 16.16 number which it then passes to “beatsin88” which expects an 8.8 number, so the C compiler silently does a downcast and/or a truncation, and then the parameters to beatsin88 are treated as an integer if less than 256 but as a 16.16 fixed-point number if greater. With all the side-effects it can be very difficult to tell by eye what some numbers used as parameters to FastLED functions are really doing; sometimes it’s necessary to single-step through in a debugger to see how it winds up.

Still, I think it would be a very worthwhile exercise, and when we’ve squeezed all the goodness we can out of the WLED pattern library we can move on to the other FastLED-based engines (I’ve seen quite a few patterns I like in the SoulMate library).

Embrace and extend!

while the idea of a FastLED compatibility library is a good idea, it’s such a radically different method of programming LEDs, that doing simple tasks (like most of the patterns in WLED) becomes more about emulating WLED than actually doing the pattern.

So let’s divide this in two pieces:

  1. Duplicate the pattern, using as close to the ‘PB way’ of doing it.

For example, look at WLED/FX.cpp at master · Aircoookie/WLED · GitHub

and take a simple case: blink() is used for a few patterns.

blink(color1, color2, bool strobe, bool do_palette)
alternate between color 1+2, maybe strobe, maybe use a palette of colors.

Porting this exactly, including segmenting code (which is used a lot in the patterns) seems pointless IF we can port the functionality.

We have ‘segmenting’ code now, the Multisegment pattern and Multimap multi-pattern will do this in either 1d or 2d, and just need a code fragment of a pattern to be installed into them.

Palette aside, doing a blink() is pretty easy.

  1. Build a FastLED library for porting things where it’s just easier to emulate than to do it the PB way.

I’m all in favor of doing this, but don’t want it in the way of the much simpler task of just ensuring that Pattern X from WLED has a PB equiv. In fact, having a PB equiv rather than a pure port can help teach people the PB way to write things.

I hear what you’re saying, but a quick look through the PB pattern library shows that a lot of the non-chaser patterns – most of the Cylon/KITT variants, Snake, Doom Fire and others – calculate into pixel buffers and then output them at render time. If we port most of the FastLED helper functions for dealing with buffers, then those WLED patterns can work on PB with a minimum of fuss (which is one consideration as a training exercise). Those who want to code golf can continue rewriting the patterns to try to eliminate the pixel buffers, but in many cases it won’t be possible.

Don’t get me wrong, I love the PB way of doing things and I’ve never seen better for getting something amazing up and running with a minimum of code, but there are times when you need a little more access to the render pipeline…

I don’t have a problem with a pixel buffer, in fact, I’m working on code for one now…

but the KITT variants are a good example of why I don’t want to just port it. We have not only an array method of doing it (Classic KITT by Ben), but we have new variants that do it on matrixes, using waves, with no array required.

Doing it again seems pointless, especially if we’re just faking doing via FastLED ‘emulation’.

I think we agree, making it easier to do FastLED style patterns is a good thing. I’m just saying, don’t port it wholesale, pick and choose.