Driving WS2812B Pixels, With DMA Based SPI

WS2812 at 670 kHz

Typically bit-banging an I/O line is the common method of driving the WS2812B (WS2811) RGB LEDs. However, this ties up precious microcontroller cycles while it waits around to flip a bit. A less processor intensive method is to use one of the built-in Serial Peripheral Interface (SPI) modules. This is done using specially crafted data and baud rate settings, that when shifted out over the Serial Data Out (SDO) pin, recreate the needed WS2812B signal timing. Even when running in SPI mode, your hardware TX buffer size will limit how many pixels you can update without CPU intervention.

[Henrik] gets around this limitation by using peripheral DMA (Direct Memory Access) to the SPI module in the Microchip PIC32MX250F128B microcontroller. Once properly configured, the DMA controller will auto increment through the defined section of DMA RAM, sending the pixel data over to the SPI module. Since the DMA controller takes care of the transfer, the micro is free to do other things. This makes all of DMA memory your display buffer. And leaves plenty of precious microcontroller cycles available to calculate what patterns you want the RGB LEDs to display.

Source code is available at the above link for those who would like to peruse, or try it out. This is part of [Henrik’s] Pixel Art Project. Video of DMA based SPI pixels after the break:

For more DMA based WS2812B Pixels, check out a this PWM based version.

18 thoughts on “Driving WS2812B Pixels, With DMA Based SPI

    1. Yes, but keep in mind that the Arduino-based crowd has to relearn all of these concepts from scratch, since they ignore the AVR architecture entirely in favor of C/C++ libraries.

        1. I believe the Atmel 8-bit Xmega series have DMA, but not the 8-bit mega as are used in the 8-bit Arduino’s. I think the ARM based Arduino’s do have it also, but AFAIK it is not exposed by the libraries.

        2. Normal 8 bit AVR, no. But Hack-a-Day has numerous times covered my DMA-based OctoWS2811 library, which works with the Arduino software and Arduino sketches, and lots of awesome large-scale LED projects using OctoWS2811.

          This isn’t an add or plug, and I won’t want to detract from this story any more, by mentioning specific hardware. You can pretty easily find the details with a google search, if you’re inclined.

          Using DMA can be tricky on bare metal microcontroller programming. It’s pretty awesome to see more people doing it.

          1. When I read the Headline I immediately thought this was about [Paul] and his OctoWS2811 Library, and I thought HaD got it wrong since [Paul] doesn’t use SPI. But although I was wrong myself I think [Paul] should at least be mentioned in this Article, since he started the whole DMA-based-LED-driving thing.

  1. I took a somewhat different approach with my clock project here:

    https://learn.adafruit.com/madisons-neoclock-a-pic-kicad-neopixel-adventure

    I’ve wanted to move away from bit-banging in favor of more hardware support while still using a small (PIC16F1847) device. With the ‘1847 I’m using the EUSART as a synchronous slave to drive the dual PWM+DSM producing the bitstream for the NeoPixels. The internal RAM in the PIC contains the 3-byte color values which are retrieved via SPI (the PIC is the SPI Master) from a renderer. (The expectation is the SPI Slave in the renderer would use DMA to provide the color-byte frame whenever the PIC initiated the SPI exchange.)

    All that gives me slightly faster than 50 Hz update rate for 256 NeoPixels – not too bad for a single PIC.

  2. Speaking of PICs, there’s a Microchip appnote describing how to use the configurable logic cell (CLC) to generate a WS2811 compatible signal.
    Some of the newer low- and midrange PIC micros have one or more CLCs.
    Besides the practical use, this is a nice example of what you can do with them.

  3. Henrik is a super nice guy. He is very helpful to anyone with PIC problems, I pick his brain often.

    Also, AVR / ardunio users need to STFU, PICs have been around way longer and everything you see done on an AVR or ardunio has been done 100 times over on other micros for years, so he doesn’t need to credit anyone with anything.

  4. This is good idea with DMA+spi,i even using program delay of debug code to handle the ws2812B led strip(http://www.ledlightmake.com/rgb-addressable-led-strip-c-80_87/led-ws2812b-addressable-digital-stripsmd5050-strips-60-pcsm-p-216.html) .the test code as follows:
    #asm
    MOV P1, #1
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    MOV P1, #0

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop

    ENDASM

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.