Part 2: LED control method using the FlexIO [1]

Document created by edk Employee on May 25, 2016Last modified by Diana Torres on Apr 18, 2017
Version 9Show Document
  • View in full screen mode

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.

 

2016-01-28_215521.png

LED's in cascade:

2016-01-28_215535.png

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:

 

2016-01-28_233613.png

 

How are the "1" and "0" generated?

 

Each pixel needs 24 bits of Red-Green-Blue value (RGB)

2016-01-28_215606.png

 

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.

 

2016-01-28_235702.png

 

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:

 

 

2016-01-29_003243.png

 

Multiplexer implementation:

 

2016-01-29_014122.png

 

 

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

Attachments

    Outcomes