Skip to content

On Lossy Colours

Andrew Tuline edited this page May 24, 2020 · 22 revisions

Issue

The following code moves the pixels down the line, but as it gets to the end it the intensity decreases significantly:

setPixelColor(i,getPixelColor(i-1));

Explanation

getPixelColor() is lossy, whereas setPixelColor() perfectly sets the intended color. However unfortunately the raw pixel memory buffer is also lossy, since it has to save the values scaled by master brightness. And unfortunately, if you do s = xb /255, later doing x = s255/b won't yield exactly the same result (thanks integer division). To solve this problem we would need a secondary pixel data buffer.

See: https://github.com/Aircoookie/WLED/issues/820

Workarounds

As a workaround, you could allocate memory for each function on the fly as a double buffer and use that, or you could hard code an array. Either way, you need to double up on the memory requirements and that is extremely limited with the

Allocate memory

if (!SEGENV.allocateData(SEGLEN)) return mode_static(); // Allocation failed
byte* myVal = SEGENV.data;                              // Could also be an int or long or whatever.

You could then refer to myVal[0] up through myVal[SEGLEN-1]

One problem with dynamic memory allocation at the firmware level is that it can become segmented and fail.

Hard coded array

First off, I would encapsulate ALL of this with #ifndef statements because you can't guarantee memory available on an ESP8266. In FX.cpp, you would define globally:

#ifndef ESP8266
uint32_t ledData[1500];            // Or whatever value, but I would reserve this for ESP82 only.
#endif

Similarly, you would encapsulate all functions and definitions that support that array. In the (encapsulated) animation, you would do the following:

uint16_t WS2812FX::mode_myMode(void) {

#ifndef ESP8266

  uint32_t* leds = ledData;

// PERFORM ANIMATION MAGIC HERE!!


  for (int i = SEGLEN; i > 0; i--) {    // You can shift LED's the FastLED way.
    leds[i] = leds[i-1];
  }


  for (int i= 0; i < SEGLEN; i++) {   // Now send to the NeoPixelBus array
    c.h = (leds[i] >> 16) & 0xFF;
    c.s = (leds[i] >> 8) &0xFF;
    c.v = leds[i] & 0xFF;
    color = c;                       // Implicit conversion to RGB supplied by FastLED
    setPixelColor(i, color.red, color.green, color.blue);
  }

#endif

  return FRAMETIME;
} // mode_myMode()
Clone this wiki locally