From d2973ff20bd248591e5300432d2a4415c67b23de Mon Sep 17 00:00:00 2001 From: Mark Walker Date: Sun, 20 Mar 2016 21:22:19 -0700 Subject: [PATCH] Add ws281x driver parameter for PWM channel The RPi 2 and 3 have two PWM channels and 3 PWM pins available to the gpio header. BCM18 and BCM12 run on PWM channel 0. BCM13 runs on PWM channel 1. This change allows BCM13 to be used by allowing the PWM channel to be specified. Former-commit-id: 3693ab438c2b369e6307c262d32bba509409e5b9 --- libsrc/leddevice/LedDeviceFactory.cpp | 3 ++- libsrc/leddevice/LedDeviceWS281x.cpp | 39 +++++++++++++++------------ libsrc/leddevice/LedDeviceWS281x.h | 3 ++- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 49b197f6..e693ae7c 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -327,8 +327,9 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) const int leds = deviceConfig.get("leds", 12).asInt(); const uint32_t freq = deviceConfig.get("freq", (Json::UInt)800000ul).asInt(); const int dmanum = deviceConfig.get("dmanum", 5).asInt(); + const int pwmchannel = deviceConfig.get("pwmchannel", 0).asInt(); - LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum); + LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum, pwmchannel); device = ledDeviceWS281x; } #endif diff --git a/libsrc/leddevice/LedDeviceWS281x.cpp b/libsrc/leddevice/LedDeviceWS281x.cpp index 10b5d2e0..3871b553 100644 --- a/libsrc/leddevice/LedDeviceWS281x.cpp +++ b/libsrc/leddevice/LedDeviceWS281x.cpp @@ -3,22 +3,27 @@ #include "LedDeviceWS281x.h" // Constructor -LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum) +LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel) { initialized = false; led_string.freq = freq; led_string.dmanum = dmanum; - led_string.channel[0].gpionum = gpio; - led_string.channel[0].invert = 0; - led_string.channel[0].count = leds; - led_string.channel[0].brightness = 255; - led_string.channel[0].strip_type = WS2811_STRIP_RGB; + if (pwmchannel != 0 && pwmchannel != 1) { + std::cout << "WS281x: invalid PWM channel; must be 0 or 1." << std::endl; + throw -1; + } + chan = pwmchannel; + led_string.channel[chan].gpionum = gpio; + led_string.channel[chan].invert = 0; + led_string.channel[chan].count = leds; + led_string.channel[chan].brightness = 255; + led_string.channel[chan].strip_type = WS2811_STRIP_RGB; - led_string.channel[1].gpionum = 0; - led_string.channel[1].invert = 0; - led_string.channel[1].count = 0; - led_string.channel[1].brightness = 0; - led_string.channel[0].strip_type = WS2811_STRIP_RGB; + led_string.channel[!chan].gpionum = 0; + led_string.channel[!chan].invert = 0; + led_string.channel[!chan].count = 0; + led_string.channel[!chan].brightness = 0; + led_string.channel[!chan].strip_type = WS2811_STRIP_RGB; if (ws2811_init(&led_string) < 0) { std::cout << "Unable to initialize ws281x library." << std::endl; throw -1; @@ -35,12 +40,12 @@ int LedDeviceWS281x::write(const std::vector &ledValues) int idx = 0; for (const ColorRgb& color : ledValues) { - if (idx >= led_string.channel[0].count) + if (idx >= led_string.channel[chan].count) break; - led_string.channel[0].leds[idx++] = ((uint32_t)color.red << 16) + ((uint32_t)color.green << 8) + color.blue; + led_string.channel[chan].leds[idx++] = ((uint32_t)color.red << 16) + ((uint32_t)color.green << 8) + color.blue; } - while (idx < led_string.channel[0].count) - led_string.channel[0].leds[idx++] = 0; + while (idx < led_string.channel[chan].count) + led_string.channel[chan].leds[idx++] = 0; if (ws2811_render(&led_string)) return -1; @@ -57,8 +62,8 @@ int LedDeviceWS281x::switchOff() return -1; int idx = 0; - while (idx < led_string.channel[0].count) - led_string.channel[0].leds[idx++] = 0; + while (idx < led_string.channel[chan].count) + led_string.channel[chan].leds[idx++] = 0; if (ws2811_render(&led_string)) return -1; diff --git a/libsrc/leddevice/LedDeviceWS281x.h b/libsrc/leddevice/LedDeviceWS281x.h index 429a092f..61a58800 100644 --- a/libsrc/leddevice/LedDeviceWS281x.h +++ b/libsrc/leddevice/LedDeviceWS281x.h @@ -17,7 +17,7 @@ public: /// @param freq The target frequency for the data line, default is 800000 /// @param dmanum The DMA channel to use, default is 5 /// - LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum); + LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, int dmanum, int pwmchannel); /// /// Destructor of the LedDevice, waits for DMA to complete and then cleans up @@ -37,6 +37,7 @@ public: private: ws2811_t led_string; + int chan; bool initialized; };