I am using Adafruit LED stripes with 60 LED's per meter. Each LED integrates the W2812B controller. WS2812B uses a serial protocol, and you can control each LED individually. The strip is made of flexible PCB material, and comes with a weatherproof sheathing.
https://www.adafruit.com/products/1138
WS2812B is an intelligent control LED light source that the control circuit and RGB chip are integrated in a package.
The data transfer protocol use single NZR communication mode. After the pixel power-on reset, the DIN port receive data from controller, the first pixel collects initial 24bit data, then send to the internal data latch, the other data is sent to the next cascade pixel through the DO port.
LED's in cascade:
My LED panel uses 16 rows x 30 columns = 480 leds.
In a first approach, in order to generate the bit stream, a timer in PWM mode could be used and generate two different duty cycles for sending a "0" logic or "1" logic. Using PWM's + DMA can unload the CPU in the generation of each single bit. FlexIO module in the Kinetis K82 can do that in a very effective mode and generate 8 channels simultaneously.
But my objective is to unload the CPU as much as possible in the bit stream generation task and find an easy method of multiplexing the 8 FlexIO outputs. In this way, we can control more LED rows and get a minimum number of interrupts and CPU intervention.
I will use the FlexIO internal data shifters to send the data bit stream. One shifter for each row. As we only have 8 shifters, I can use external multiplexor to increase the number of rows. Unloading the CPU for the LED refresh process, we can mux several rows in each shifter output. The limit of LED’s will be the refresh time of the full panel.
FlexIO block diagram:
How are the "1" and "0" generated?
Each pixel needs 24 bits of Red-Green-Blue value (RGB)
For each row, I need to send 30 x 24 bits of RGB information. But I have to encode the data in the NZR/PWM protocol. I use a lookup table to transform 24 bpp information in
24 x 3 = 72 bits per pixel.
In this way the DMA can send 30 x 24 x 3 = 1440 bits (A full row) in 60 transfers of 24 bits into the shifter. We get only one DMA interrupt for each row:
Multiplexer implementation:
Frame Buffer LED:
typedef union
{
uint32_t rgb;
struct{
uint8_t b;
uint8_t r;
uint8_t g;
uint8_t a;
}bytes;
}ledrgb;
Extended LED encoded data:
typedef struct
{
uint32_t g;
uint32_t r;
uint32_t b;
}ledrgb_ext;
Lookup Table:
void init_conv_matrix(void)
{
videoconv[0]=0x92492400;
videoconv[1]=0x92492600;
videoconv[2]=0x92493400;
videoconv[3]=0x92493600;
videoconv[4]=0x9249A400;
videoconv[5]=0x9249A600;
videoconv[6]=0x9249B400;
videoconv[7]=0x9249B600;
videoconv[8]=0x924D2400;
videoconv[9]=0x924D2600;
videoconv[10]=0x924D3400;
...
};
Part 3: Software for LED Panel emulation
Or
Return to Project page: LED Panel control with FlexIO