OctoWS2811 - Teensy4.1 - Use RGB and RGBW

Possible, yes. Easy, not really, unless you modify the library with your own setPixel() function.

If you use Teensy 4.0 or 4.1, the good news is setPixel() is fairly simple. Make sure you read the file OctoWS2811_imxrt.cpp.

For Teensy 3.2, 3.5, 3.6, the pixel data is stored in a transposed format which allows the code to run faster but it makes the setPixel() code quite complicated. Long ago the library had somewhat simpler (but nowhere near as easy as Teensy 4.x) code that wasn't quite as fast, so you might look on github history for the very old code. But even then, it's not easy. I'd recommend just getting a Teensy 4.0 or 4.1 if you want to do this, since the code will be so much easier.

On how the Teensy 4 code works, hopefully you can see most of it is just dealing with the different color orders, and then it just writes 3 bytes for RGB and 4 bytes for RGBW into the buffer. The key piece you'll need to modify is this:

Code:
		uint8_t *dest = (uint8_t *)drawBuffer + num * 4;

This simple code just multiplies "num" (the 0-based pixel index) by 4, since the entire buffer is known to be 4 byte RGBW data.

Let's say you were to connect 800 LEDs, 100 to each pin, and the first half are RGB and the 2nd half are RGBW. Every pin must transmit the same number of data bits. So those pins with RGB need only 2400 bits, but they will actually get 3200 bits where the last 800 bits go unused. Or more LEDs could be connected to those pins, but for simplicity let's assume all pins have 100 LEDs. The important point is every pin gets 800 bytes of data, whether the LEDs on that pin need it or not.

Here is a way to compute the destination to write within the buffer, which is not necessarily the most optimal way but rather is meant to show the idea of computing the destination differently depending on which LED strip.

Code:
        uint8_t *dest;
        if (num >= 0 && num <= 99) {
                dest = (uint8_t *)drawBuffer + num * 3;
        } else
        if (num >= 100 && num <= 199) {
                dest = (uint8_t *)drawBuffer + 800 + (num - 100) * 3;
        } else
        if (num >= 200 && num <= 299) {
                dest = (uint8_t *)drawBuffer + 1600 + (num - 200) * 3;
        } else
        if (num >= 300 && num <= 399) {
                dest = (uint8_t *)drawBuffer + 2400 + (num - 300) * 3;
        } else
        if (num >= 400 && num <= 499) {
                dest = (uint8_t *)drawBuffer + 3200 + (num - 400) * 4;
        } else
        if (num >= 500 && num <= 599) {
                dest = (uint8_t *)drawBuffer + 4000 + (num - 500) * 4;
        } else
        if (num >= 600 && num <= 699) {
                dest = (uint8_t *)drawBuffer + 4800 + (num - 600) * 4;
        } else
        if (num >= 700 && num <= 799) {
                dest = (uint8_t *)drawBuffer + 5600 + (num - 700) * 4;
        }

The LEDs for each pin have their own code. Every pin gets 800 bytes transmitted. So this simple not-necessarily-optimal way just computes the location in the buffer where each pin's data begins, then adds the pixel offset times either 3 for the pins with RGB or times 4 for the pins with RGBW.

While this assumes each pin will have all the same type, either 3-byte RGB or 4-byte RGBW, hopefully you can imagine how you might alter the code to "know" about any combination of different LEDs connected to the same pin. You'll have to use of knowledge of what LEDs are really connected and compute the place where each pixel's 3 or 4 bytes get written.

But if you keep the hardware simpler so each pin has all the same type of LED, then hopefully the code above can get you pretty close to a working solution.

As with all OctoWS2811 answers... when you build your large LED project, I really hope you'll share photos or video!
 
Hi Paul !

Thanks for your very (very, very, very) fast reply and for your perfect explanations !


Ok, got it, it's actually just about buffer ! I will do some tests.


Have a good day :D
 
Some news, it's working with some modifications of the OctoWS2811 library :
OctoWS2811.h : (for IMXRT1062)
Code:
void setPixel(int stripNum, uint8_t config, uint32_t num, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) {
      setPixelNew(stripNum, config, num, Color(red, green, blue, white));
}

void setPixelNew(int stripNum, uint8_t config, uint32_t num, int color);

OctoWS2811_imxrt.cpp :
Code:
void OctoWS2811::setPixelNew(int stripNum, uint8_t Stripconfig, uint32_t num, int color) {
	uint8_t b = color;
	uint8_t g = color >> 8;
	uint8_t r = color >> 16;
	uint8_t w = color >> 24;
	uint32_t c = 0;
	bool is3Colors = false;
	switch (Stripconfig & 0x1F) {
		case WS2811_RGBW: c = (r << 24) | (g << 16) | (b << 8) | w; break;
		case WS2811_RBGW: c = (r << 24) | (b << 16) | (g << 8) | w; break;
		case WS2811_GRBW: c = (g << 24) | (r << 16) | (b << 8) | w; break;
		case WS2811_GBRW: c = (g << 24) | (b << 16) | (r << 8) | w; break;
		case WS2811_BRGW: c = (b << 24) | (r << 16) | (g << 8) | w; break;
		case WS2811_BGRW: c = (b << 24) | (b << 16) | (r << 8) | w; break;
		case WS2811_WRGB: c = (w << 24) | (r << 16) | (g << 8) | b; break;
		case WS2811_WRBG: c = (w << 24) | (r << 16) | (b << 8) | g; break;
		case WS2811_WGRB: c = (w << 24) | (g << 16) | (r << 8) | b; break;
		case WS2811_WGBR: c = (w << 24) | (g << 16) | (b << 8) | r; break;
		case WS2811_WBRG: c = (w << 24) | (b << 16) | (r << 8) | g; break;
		case WS2811_WBGR: c = (w << 24) | (b << 16) | (g << 8) | r; break;
		case WS2811_RWGB: c = (r << 24) | (w << 16) | (g << 8) | b; break;
		case WS2811_RWBG: c = (r << 24) | (w << 16) | (b << 8) | g; break;
		case WS2811_GWRB: c = (g << 24) | (w << 16) | (r << 8) | b; break;
		case WS2811_GWBR: c = (g << 24) | (w << 16) | (b << 8) | r; break;
		case WS2811_BWRG: c = (b << 24) | (w << 16) | (r << 8) | g; break;
		case WS2811_BWGR: c = (b << 24) | (w << 16) | (g << 8) | r; break;
		case WS2811_RGWB: c = (r << 24) | (g << 16) | (w << 8) | b; break;
		case WS2811_RBWG: c = (r << 24) | (b << 16) | (w << 8) | g; break;
		case WS2811_GRWB: c = (g << 24) | (r << 16) | (w << 8) | b; break;
		case WS2811_GBWR: c = (g << 24) | (b << 16) | (w << 8) | r; break;
		case WS2811_BRWG: c = (b << 24) | (r << 16) | (w << 8) | g; break;
		case WS2811_BGWR: c = (b << 24) | (g << 16) | (w << 8) | r; break;
		case WS2811_RGB: c = (r << 24) | (g << 16) | (b << 8) | w; is3Colors=true; break;
		case WS2811_RBG: c = (r << 24) | (b << 16) | (g << 8) | w; is3Colors=true; break;
		case WS2811_GRB: c = (g << 24) | (r << 16) | (b << 8) | w; is3Colors=true; break;
		case WS2811_GBR: c = (g << 24) | (b << 16) | (r << 8) | w; is3Colors=true; break;
		case WS2811_BRG: c = (b << 24) | (r << 16) | (g << 8) | w; is3Colors=true; break;
		case WS2811_BGR: c = (b << 24) | (b << 16) | (r << 8) | w; is3Colors=true; break;
	}

	uint8_t *dest;
	if (is3Colors == false) { //4colors strip
		num+=stripLen * (stripNum-1);
		if (is3Colors == true) {}
		dest = (uint8_t *)drawBuffer + (stripLen * 4 * (stripNum-1)) + (num - stripLen * (stripNum-1)) * 4;
		*dest++ = c >> 24;
		*dest++ = c >> 16;
		*dest++ = c >> 8;
		*dest++ = c;
	} else { //3colors strip
		num+=stripLen * (stripNum-1);
		dest = (uint8_t *)drawBuffer + (stripLen * 4 * (stripNum-1)) + (num - stripLen * (stripNum-1)) * 3;
		*dest++ = c >> 24;
		*dest++ = c >> 16;
		*dest++ = c >> 8;
	}
}


Thanks !
 
OctoWS2811 LED Library - Changing parameters while running

Can the OctoWS2811 LED Library parameters be modified at runtime? All the examples show the configurations set at compile time.

For example, if there are settings that are loaded from EEPROM at power-up that set the number of pixels per pin, and whether they are RGB or RBG LEDs connected ?
 
It should be possible. Years ago a begin() function was added to enable this sort of usage. But there isn't an end() function to turn off the hardware. Whether calling begin() more than once in the same run of your program really works is a good question. Odds are probably good if you want until the hardware is idle, but honestly the library hasn't really been tested for that usage. Just calling begin() once with parameters from EEPROM or some other source should be fine. Obviously it's your responsibility to allocate the drawing buffer and display buffer large enough. Buffers can be larger than needed, so probably simplest to just use a fixed size buffer that's large enough for the maximum number / type of LEDs you'll use.
 
Back
Top