diff --git a/README.md b/README.md index d3ce0936..bef09004 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Userspace Raspberry Pi library for controlling WS281X LEDs. This includes WS2812 and SK6812RGB RGB LEDs Preliminary support is now included for SK6812RGBW LEDs (yes, RGB + W) The LEDs can be controlled by either the PWM (2 independent channels) -or PCM controller (1 channel) or the SPI interfacei (1 channel). +or PCM controller (1 channel) or the SPI interface (1 channel). ### Background: @@ -13,8 +13,8 @@ The BCM2835 in the Raspberry Pi has both a PWM and a PCM module that are well suited to driving individually controllable WS281X LEDs. Using the DMA, PWM or PCM FIFO, and serial mode in the PWM, it's possible to control almost any number of WS281X LEDs in a chain connected -to the appropirate output pin. -For SPI the Raspbian spidev driver is used (/dev/spidev0.0). +to the appropriate output pin. +For SPI the Raspbian spidev driver is used (`/dev/spidev0.0`). This library and test program set the clock rate to 3X the desired output frequency and creates a bit pattern in RAM from an array of colors where each bit is represented by 3 bits as follows. @@ -73,8 +73,8 @@ reponsibility for damage, harm, or mistakes. ### Build: -- Install Scons (on raspbian, apt-get install scons). -- Make sure to adjust the parameters in main.c to suit your hardare. +- Install Scons (on raspbian, `apt-get install scons`). +- Make sure to adjust the parameters in main.c to suit your hardware. - Signal rate (400kHz to 800kHz). Default 800kHz. - ledstring.invert=1 if using a inverting level shifter. - Width and height of LED matrix (height=1 for LED string). @@ -93,7 +93,7 @@ Usage: ./test -s (--strip) - strip type - rgb, grb, gbr, rgbw -x (--width) - matrix width (default 8) -y (--height) - matrix height (default 8) --d (--dma) - dma channel to use (default 5) +-d (--dma) - dma channel to use (default 10) -g (--gpio) - GPIO to use If omitted, default is 18 (PWM0) -i (--invert) - invert pin output (pulse LOW) @@ -101,6 +101,14 @@ Usage: ./test -v (--version) - version information ``` +### Important warning about DMA channels + +You must make sure that the DMA channel you choose to use for the LEDs is not [already in use](https://www.raspberrypi.org/forums/viewtopic.php?p=609380#p609380) by the operating system. + +For example, **using DMA channel 5 [will cause](https://github.com/jgarff/rpi_ws281x/issues/224) filesystem corruption** on the Raspberry Pi 3 Model B. + +The default DMA channel (10) should be safe for the Raspberry Pi 3 Model B, but this may change in future software releases. + ### Limitations: #### PWM @@ -108,7 +116,7 @@ Usage: ./test Since this library and the onboard Raspberry Pi audio both use the PWM, they cannot be used together. You will need to blacklist the Broadcom audio kernel module by creating a file -/etc/modprobe.d/snd-blacklist.conf with +`/etc/modprobe.d/snd-blacklist.conf` with blacklist snd_bcm2835 @@ -137,7 +145,7 @@ When using SPI the ledstring is the only device which can be connected to the SPI bus. Both digital (I2S/PCM) and analog (PWM) audio can be used. Many distributions have a maximum SPI transfer of 4096 bytes. This can be -changed in /boot/cmdline.txt by appending +changed in `/boot/cmdline.txt` by appending ``` spidev.bufsiz=32768 ``` @@ -167,14 +175,14 @@ When controlling a LED string of 240 LEDs the CPU load on the original Pi 2 (BCM ### Usage: -The API is very simple. Make sure to create and initialize the ws2811_t -structure as seen in main.c. From there it can be initialized -by calling ws2811_init(). LEDs are changed by modifying the color in -the .led[index] array and calling ws2811_render(). +The API is very simple. Make sure to create and initialize the `ws2811_t` +structure as seen in [`main.c`](main.c). From there it can be initialized +by calling `ws2811_init()`. LEDs are changed by modifying the color in +the `.led[index]` array and calling `ws2811_render()`. The rest is handled by the library, which either creates the DMA memory and starts the DMA for PWM and PCM or prepares the SPI transfer buffer and sends it out on the MISO pin. Make sure to hook a signal handler for SIGKILL to do cleanup. From the -handler make sure to call ws2811_fini(). It'll make sure that the DMA +handler make sure to call `ws2811_fini()`. It'll make sure that the DMA is finished before program execution stops and cleans up after itself. diff --git a/golang/ws2811/ws2811.go.h b/golang/ws2811/ws2811.go.h index 48c12f5d..5e078f74 100644 --- a/golang/ws2811/ws2811.go.h +++ b/golang/ws2811/ws2811.go.h @@ -1,7 +1,7 @@ /*********************************************************************************** * Copyright (c) 2015, Jacques Supcik, HEIA-FR * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -12,7 +12,7 @@ * * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -24,14 +24,14 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***********************************************************************************/ - + #include #include #include ws2811_t ledstring = { .freq = 800000, - .dmanum = 5, + .dmanum = 10, .channel = { [0] = { .gpionum = 18, diff --git a/main.c b/main.c index cd5a2e83..85ecd67f 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,7 @@ static char VERSION[] = "XX.YY.ZZ"; // defaults for cmdline options #define TARGET_FREQ WS2811_TARGET_FREQ #define GPIO_PIN 18 -#define DMA 5 +#define DMA 10 //#define STRIP_TYPE WS2811_STRIP_RGB // WS2812/SK6812RGB integrated chip+leds #define STRIP_TYPE WS2811_STRIP_GBR // WS2812/SK6812RGB integrated chip+leds //#define STRIP_TYPE SK6812_STRIP_RGBW // SK6812RGBW (NOT SK6812RGB) @@ -263,9 +263,9 @@ void parseargs(int argc, char **argv, ws2811_t *ws2811) if (optarg) { int gpio = atoi(optarg); /* - PWM0, which can be set to use GPIOs 12, 18, 40, and 52. + PWM0, which can be set to use GPIOs 12, 18, 40, and 52. Only 12 (pin 32) and 18 (pin 12) are available on the B+/2B/3B - PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53. + PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53. Only 13 is available on the B+/2B/PiZero/3B, on pin 33 PCM_DOUT, which can be set to use GPIOs 21 and 31. Only 21 is available on the B+/2B/PiZero/3B, on pin 40. @@ -417,4 +417,3 @@ int main(int argc, char *argv[]) printf ("\n"); return ret; } - diff --git a/python/examples/SK6812_lowlevel.py b/python/examples/SK6812_lowlevel.py index 2d293b93..67ff8998 100644 --- a/python/examples/SK6812_lowlevel.py +++ b/python/examples/SK6812_lowlevel.py @@ -15,7 +15,7 @@ LED_CHANNEL = 0 LED_COUNT = 16 # How many LEDs to light. LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz. -LED_DMA_NUM = 5 # DMA channel to use, can be 0-14. +LED_DMA_NUM = 10 # DMA channel to use, can be 0-14. LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM! LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN diff --git a/python/examples/SK6812_strandtest.py b/python/examples/SK6812_strandtest.py index 266dcaab..5f4228bf 100644 --- a/python/examples/SK6812_strandtest.py +++ b/python/examples/SK6812_strandtest.py @@ -12,11 +12,11 @@ LED_COUNT = 40 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_DMA = 5 # DMA channel to use for generating signal (try 5) +LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 0 -LED_STRIP = ws.SK6812_STRIP_RGBW +LED_STRIP = ws.SK6812_STRIP_RGBW #LED_STRIP = ws.SK6812W_STRIP diff --git a/python/examples/SK6812_white_test.py b/python/examples/SK6812_white_test.py index f4c88ddb..ba0815a6 100644 --- a/python/examples/SK6812_white_test.py +++ b/python/examples/SK6812_white_test.py @@ -11,11 +11,11 @@ LED_COUNT = 30 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_DMA = 5 # DMA channel to use for generating signal (try 5) +LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 0 -#LED_STRIP = ws.SK6812_STRIP_RGBW +#LED_STRIP = ws.SK6812_STRIP_RGBW LED_STRIP = ws.SK6812W_STRIP diff --git a/python/examples/lowlevel.py b/python/examples/lowlevel.py index df0617f6..39d69081 100644 --- a/python/examples/lowlevel.py +++ b/python/examples/lowlevel.py @@ -15,7 +15,7 @@ LED_CHANNEL = 0 LED_COUNT = 16 # How many LEDs to light. LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz. -LED_DMA_NUM = 5 # DMA channel to use, can be 0-14. +LED_DMA_NUM = 10 # DMA channel to use, can be 0-14. LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM! LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN diff --git a/python/examples/multistrandtest.py b/python/examples/multistrandtest.py index 88d76c41..afde32cc 100644 --- a/python/examples/multistrandtest.py +++ b/python/examples/multistrandtest.py @@ -11,20 +11,20 @@ LED_1_COUNT = 30 # Number of LED pixels. LED_1_PIN = 18 # GPIO pin connected to the pixels (must support PWM! GPIO 13 and 18 on RPi 3). LED_1_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_1_DMA = 5 # DMA channel to use for generating signal (Between 1 and 14) +LED_1_DMA = 10 # DMA channel to use for generating signal (Between 1 and 14) LED_1_BRIGHTNESS = 128 # Set to 0 for darkest and 255 for brightest LED_1_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_1_CHANNEL = 0 # 0 or 1 -LED_1_STRIP = ws.SK6812_STRIP_GRBW +LED_1_STRIP = ws.SK6812_STRIP_GRBW LED_2_COUNT = 15 # Number of LED pixels. LED_2_PIN = 13 # GPIO pin connected to the pixels (must support PWM! GPIO 13 or 18 on RPi 3). LED_2_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_2_DMA = 10 # DMA channel to use for generating signal (Between 1 and 14) +LED_2_DMA = 11 # DMA channel to use for generating signal (Between 1 and 14) LED_2_BRIGHTNESS = 128 # Set to 0 for darkest and 255 for brightest LED_2_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_2_CHANNEL = 1 # 0 or 1 -LED_2_STRIP = ws.WS2811_STRIP_GRB +LED_2_STRIP = ws.WS2811_STRIP_GRB def multiColorWipe(color1, color2, wait_ms=5): global strip1 diff --git a/python/examples/neopixelclock.py b/python/examples/neopixelclock.py index 00f74fef..e9501576 100644 --- a/python/examples/neopixelclock.py +++ b/python/examples/neopixelclock.py @@ -16,7 +16,7 @@ LED_COUNT = 12 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_DMA = 5 # DMA channel to use for generating signal (try 5) +LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest # True to invert the signal (when using NPN transistor level shift) LED_INVERT = False diff --git a/python/examples/strandtest.py b/python/examples/strandtest.py index 844a629d..33cf3ab0 100644 --- a/python/examples/strandtest.py +++ b/python/examples/strandtest.py @@ -26,7 +26,7 @@ def opt_parse(): LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!). #LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) -LED_DMA = 5 # DMA channel to use for generating signal (try 5) +LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53