kitesurfer1404 / WS2812FX

WS2812 FX Library for Arduino and ESP8266
MIT License
1.58k stars 343 forks source link

Aply a mask to segments #310

Closed romses closed 1 year ago

romses commented 2 years ago

Is there a way, to apply a bitmask to effects, so that masked pixels do not get turned on?

e.g.

Mask:   000011110000
Effect: EEEEEEEEEEEE
Out:    0000EEEE0000
moose4lord commented 2 years ago

I modified the ws2812fx_overlay example sketch to perform the masking function. It uses the same idea of using a virtual strip (to run the animation) and a physical strip (to drive the LED strip), and the custom show() function does the masking.

#include <WS2812FX.h>

#define LED_PIN    14
#define LED_COUNT 144

WS2812FX ws2812fx_v = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800,1,1);
WS2812FX ws2812fx_p = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800,1,1);

bool mask[LED_COUNT];

void setup() {
  // Initialize the virtual strip
  ws2812fx_v.init();
  ws2812fx_v.setBrightness(64);
  ws2812fx_v.setSegment(0, 0, LED_COUNT-1, FX_MODE_RAINBOW_CYCLE, BLACK, 1000);
  ws2812fx_v.start();

  // Config custom show() function for the virtual strip
  ws2812fx_v.setCustomShow(myCustomShow);

  /* Initialize the LED mask */
  for(int i=0; i<LED_COUNT; i++) {
    if(i & 1) {
      mask[i] = true; // mask even LEDs
    } else {
      mask[i] = false; // unmask odd LEDs
    }
  }

  // Initialize the physical strip last
  ws2812fx_p.init();
}

void loop() {
  // Run effects only on the virtual strip
  ws2812fx_v.service();
}

// The custom show() function masks the virtual strip data
// and copies it to the physical strip
void myCustomShow(void) {
  // get pointers to all the pixel data arrays
  uint8_t *pixels_v = ws2812fx_v.getPixels();
  uint8_t *pixels_p = ws2812fx_p.getPixels();

  // copy the masked virtual LED data to the physical strip
  for (uint16_t i=0; i < LED_COUNT; i++) {
    uint16_t pindex = i * 3; // index into the pixel arrays
    if(mask[i]) {
      memmove(&pixels_p[pindex], &pixels_v[pindex], 3); // copy 3 bytes
    } else {
      memset(&pixels_p[pindex], 0, 3); // set 3 bytes to zero (BLACK)
    }
  }

  // Call the physical strip's show() function.
  ws2812fx_p.Adafruit_NeoPixel::show();
}