Test program for my Multi_WS2811 library that started out as a fork of heroic/WS2811. My library uses hardware DMA on the FRDM-KL25Z to drive up to 16 strings of WS2811 or WS2812 LEDs in parallel.
Dependencies: Multi_WS2811 mbed MMA8451Q
Fork of WS2811 by
You are viewing an older revision! See the latest version
Homepage
After being frustrated by the SPI system's performance, I ended up using an approach inspired by Paul Stoffregen's OctoWS2811. This uses 3 of the 4 DMA channels triggered by the TPM0 timer PWM and overflow events.
This design will allow for up to 16 strings of up to 60 (limited by RAM space) WS2811/WS2812 LEDs to be driven on a single port.
Note though that the 3.3V output from the FRDM-KL25Z's GPIO pins is OUT OF SPEC for driving the 5V WS2812 inputs, which require 3.5V for a logic HIGH signal. It only works on my board if I don't connect my scope or logic analyzer to the output pin. I recommend that you add a 5V buffer to the outputs to properly drive the LED strings. You could use something like a CD74HCT244 to do this.
Adding more strings takes the same time to DMA, because the bits are output in parallel.
Each LED in a string takes 24/800e3 seconds to DMA, so if MAX_LEDS_PER_STRING is set to 60, then it takes 1.8 msec to actually do the DMA, plus 0.3 msec of guard time, or 2.1 msec per frame (476 frames/second). Of course, actually composing the frame will take most of the time in a real program.
The way I have my code set up, I can use up to 8 pins on PORTD. However, changing the defines at the top of WS2811.cpp will change the selected port.
Alternatively, you could use another port to get more strings. Watch out for pin mux conflicts, though.
Here are your choices:
- PORTE: 15 total: PTE0-PTE5, PTE20-PTE25, PTE29-PTE31
- PORTD: 8 total: PTD0-PTD7
- PORTC: 16 total: PTC0-PTC13, PTC16-17
- PORTB: 16 total: PTB0-PTB11, PTB16-19
- PORTA: 15 total: PTA0-PTA5, PTA12-PTA20
Here is how the DMA channels are interleaved: