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
This commit is contained in:
Mark Walker 2016-03-20 21:22:19 -07:00
parent bb9b3808e0
commit d2973ff20b
3 changed files with 26 additions and 19 deletions

View File

@ -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

View File

@ -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<ColorRgb> &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;

View File

@ -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;
};