
So, I couldn't hold myself and bought a bunch of WS2812b LEDs. These are really cheap RGB leds with an integrated controller/driver IC. They use a one-wire protocol to set the desired color and can be daisy-chained.
The protocol is quite easy and is well described in the
data-sheet.
Short version: Each bit is represented by a 1.25us long (800kHz) high-low pattern with a 1⁄3:2⁄3 (2⁄3:1⁄3) duty cycle for a 0-value (1-value).
For a detailed timing overview and a comparison between the ws2812 and ws2812b version have a look at
cpldcpu, it is a very good resource.
As this is a serial protocol, you need to serialize your data bytes into a bit-stream. This can be done with the CPU and your controllers IO pins (bit-banging) or with a serial protocol peripheral like the SPI module.
SPI is here the weapon of choice, as it has an integrated shift register, which shifts a bit out with every clock cycle.
All implementations I saw on the web so far, which used the SPI module, converted one bit of LED data to one byte of SPI data, for example a 1 to 0xF8 and a 0 to 0xE0. With this you get 2⁄3 (1⁄3) high time and 1⁄3 (2⁄3) low time for 0xF8 (0xE0). It's quite an easy implementation, because you just have to decide for each LED data bit, if you send a 0xF8 or a 0xE0. But on the downside it also needs a high SPI clock to reach the 800kHz for the one-wire LED data stream. You need 8x800kHz = 6.4MHz for your SPI clock and an even higher CPU clock to bring the data to the SPI module. When your CPU speed is limited and you can't convert your data while transmitting, you need to pre-calculate, store the result in a buffer and transmit afterwards. You need also 8 times the memory of your raw LED data for you buffer, which is 24bytes per LED.
In my
implementation for the MSP430 (FR5739) I decided to go for a SPI transfer sourced by DMA from a buffer in RAM (or FRAM). But instead of the one bit to one byte (8-bit) encoding, I implemented a 4-bit and a 3-bit encoding to reduce buffer size and clock frequency. The 4-bit encoding is running with an SPI clock of half of the CPU frequency (6.7MHz⁄2 = 3.35MHz) which results in a one-wire signal clock of 837.5kHz (3.35MHz⁄4) which is well within the specification. The 3-bit encoding runs on a third of the CPU clock (8MHz⁄3 = 2.66MHz) which is an effective clock of 888.88kHz.
Both encoding implementations work pretty fine with the ws2812b I have, but you can test it yourself with the code I released on
GitHub.
In part two I'll write about the data encoding some more, the pros and cons of each and some implementation details. In part three I'll describe the msp430 specific code in the demo application, which is also in the GitHub repository.