mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Add new WS281x driver
Add a new WS281x driver which is a wrapper around jgarff's ws281x library which works on Pi B+, Pi 2, Pi Zero and probably Pi 3 as well. jgarff's ws281x library is included as a submodule Former-commit-id: e473dfd36d31b14598da5e56e4b8bf9f2aa7bb24
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | ||||
| [submodule "dependencies/external/protobuf"] | ||||
| 	path = dependencies/external/protobuf | ||||
| 	url = https://github.com/tvdzwan/protobuf.git | ||||
| [submodule "dependencies/external/rpi_ws281x"] | ||||
| 	path = dependencies/external/rpi_ws281x | ||||
| 	url = https://github.com/jgarff/rpi_ws281x | ||||
|   | ||||
| @@ -34,6 +34,9 @@ message(STATUS "ENABLE_V4L2 = " ${ENABLE_V4L2}) | ||||
| option(ENABLE_WS2812BPWM   "Enable the WS2812b-PWM device" OFF) | ||||
| message(STATUS "ENABLE_WS2812BPWM = " ${ENABLE_WS2812BPWM}) | ||||
|  | ||||
| option(ENABLE_WS281XPWM   "Enable the WS281x-PWM device" OFF) | ||||
| message(STATUS "ENABLE_WS281XPWM = " ${ENABLE_WS281XPWM}) | ||||
|  | ||||
| option(ENABLE_X11 "Enable the X11 grabber" OFF) | ||||
| message(STATUS "ENABLE_X11 = " ${ENABLE_X11}) | ||||
|  | ||||
| @@ -56,6 +59,10 @@ if(ENABLE_OSX AND ENABLE_DISPMANX) | ||||
| 	message(FATAL_ERROR "dispmanx grabber and osx grabber cannot be used at the same time") | ||||
| endif(ENABLE_OSX AND ENABLE_DISPMANX) | ||||
|  | ||||
| if(ENABLE_WS2812BPWM AND ENABLE_WS281XPWM) | ||||
| 	message(FATAL_ERROR "WS2812b and WS281x drivers cannot be used at the same time") | ||||
| endif(ENABLE_WS2812BPWM AND ENABLE_WS281XPWM) | ||||
|  | ||||
| #if(ENABLE_QT5) | ||||
| # TODO vs ENABLE_QT4? | ||||
| #endif(ENABLE_QT5) | ||||
|   | ||||
| @@ -12,6 +12,9 @@ | ||||
| // Define to enable the ws2812b-pwm-device | ||||
| #cmakedefine ENABLE_WS2812BPWM | ||||
|  | ||||
| // Define to enable the ws281x-pwm-via-dma-device using jgarff's library | ||||
| #cmakedefine ENABLE_WS281XPWM | ||||
|  | ||||
| // Define to enable the spi-device | ||||
| #cmakedefine ENABLE_TINKERFORGE | ||||
|  | ||||
|   | ||||
							
								
								
									
										7
									
								
								dependencies/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								dependencies/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -4,6 +4,13 @@ add_subdirectory(build/jsoncpp) | ||||
| add_subdirectory(build/serial) | ||||
| add_subdirectory(build/tinkerforge) | ||||
|  | ||||
| if(ENABLE_WS281XPWM) | ||||
| 	add_library(ws281x | ||||
| 		external/rpi_ws281x/mailbox.c external/rpi_ws281x/ws2811.c | ||||
| 		external/rpi_ws281x/pwm.c external/rpi_ws281x/dma.c | ||||
| 		external/rpi_ws281x/rpihw.c) | ||||
| endif(ENABLE_WS281XPWM) | ||||
|  | ||||
| if(ENABLE_PROTOBUF) | ||||
| 	set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library") | ||||
| 	add_subdirectory(external/protobuf) | ||||
|   | ||||
							
								
								
									
										1
									
								
								dependencies/external/rpi_ws281x
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								dependencies/external/rpi_ws281x
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule dependencies/external/rpi_ws281x added at 34c917e250
									
								
							| @@ -33,9 +33,9 @@ SET(Leddevice_HEADERS | ||||
| 		${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceSedu.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTest.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceUdp.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTest.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceUdp.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h | ||||
| @@ -56,9 +56,9 @@ SET(Leddevice_SOURCES | ||||
| 		${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp | ||||
| @@ -97,6 +97,18 @@ SET(Leddevice_SOURCES | ||||
| ) | ||||
| endif(ENABLE_WS2812BPWM) | ||||
|  | ||||
| if(ENABLE_WS281XPWM) | ||||
| include_directories(../../dependencies/external/rpi_ws281x) | ||||
| SET(Leddevice_HEADERS | ||||
| 		${Leddevice_HEADERS} | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceWS281x.h | ||||
| 	) | ||||
| SET(Leddevice_SOURCES | ||||
| 		${Leddevice_SOURCES} | ||||
| 		${CURRENT_SOURCE_DIR}/LedDeviceWS281x.cpp | ||||
| ) | ||||
| endif(ENABLE_WS281XPWM) | ||||
|  | ||||
| if(ENABLE_TINKERFORGE) | ||||
| 	SET(Leddevice_HEADERS | ||||
| 			${Leddevice_HEADERS} | ||||
| @@ -138,6 +150,10 @@ if(ENABLE_TINKERFORGE) | ||||
| 	target_link_libraries(leddevice tinkerforge) | ||||
| endif() | ||||
|  | ||||
| if(ENABLE_WS281XPWM) | ||||
| 	target_link_libraries(leddevice ws281x) | ||||
| endif() | ||||
|  | ||||
| if(APPLE) | ||||
| 	target_link_libraries(leddevice hidapi-mac) | ||||
| else() | ||||
|   | ||||
| @@ -42,6 +42,10 @@ | ||||
| 	#include "LedDeviceWS2812b.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef ENABLE_WS281XPWM | ||||
| 	#include "LedDeviceWS281x.h" | ||||
| #endif | ||||
|  | ||||
| LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) | ||||
| { | ||||
| 	std::cout << "Device configuration: " << deviceConfig << std::endl; | ||||
| @@ -285,6 +289,18 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) | ||||
| 		LedDeviceWS2812b * ledDeviceWS2812b = new LedDeviceWS2812b(); | ||||
| 		device = ledDeviceWS2812b; | ||||
| 	} | ||||
| #endif | ||||
| #ifdef ENABLE_WS281XPWM | ||||
| 	else if (type == "ws281x") | ||||
| 	{ | ||||
| 		const int gpio = deviceConfig.get("gpio", 18).asInt(); | ||||
| 		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(); | ||||
|  | ||||
| 		LedDeviceWS281x * ledDeviceWS281x = new LedDeviceWS281x(gpio, leds, freq, dmanum); | ||||
| 		device = ledDeviceWS281x; | ||||
| 	} | ||||
| #endif | ||||
| 	else | ||||
| 	{ | ||||
|   | ||||
							
								
								
									
										78
									
								
								libsrc/leddevice/LedDeviceWS281x.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								libsrc/leddevice/LedDeviceWS281x.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #include <iostream> | ||||
|  | ||||
| #include "LedDeviceWS281x.h" | ||||
|  | ||||
| // Constructor | ||||
| LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum) | ||||
| { | ||||
| 	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; | ||||
|  | ||||
| 	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; | ||||
| 	if (ws2811_init(&led_string) < 0) { | ||||
| 		std::cout << "Unable to initialize ws281x library." << std::endl; | ||||
| 		throw -1; | ||||
| 	} | ||||
| 	initialized = true; | ||||
| } | ||||
|  | ||||
| // Send new values down the LED chain | ||||
| int LedDeviceWS281x::write(const std::vector<ColorRgb> &ledValues) | ||||
| { | ||||
| 	if (!initialized) | ||||
| 		return -1; | ||||
|  | ||||
| 	int idx = 0; | ||||
| 	for (const ColorRgb& color : ledValues) | ||||
| 	{ | ||||
| 		if (idx >= led_string.channel[0].count) | ||||
| 			break; | ||||
| 		led_string.channel[0].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; | ||||
|  | ||||
| 	if (ws2811_render(&led_string)) | ||||
| 		return -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| // Turn off the LEDs by sending 000000's | ||||
| // TODO Allow optional power switch out another gpio, if this code handles it can | ||||
| // make it more likely we don't accidentally drive data into an off strip | ||||
| int LedDeviceWS281x::switchOff() | ||||
| { | ||||
| 	if (!initialized) | ||||
| 		return -1; | ||||
|  | ||||
| 	int idx = 0; | ||||
| 	while (idx < led_string.channel[0].count) | ||||
| 		led_string.channel[0].leds[idx++] = 0; | ||||
|  | ||||
| 	if (ws2811_render(&led_string)) | ||||
| 		return -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| // Destructor | ||||
| LedDeviceWS281x::~LedDeviceWS281x() | ||||
| { | ||||
| 	if (initialized) | ||||
| 	{ | ||||
| 		std::cout << "Shutdown WS281x PWM and DMA channel" << std::endl; | ||||
| 		ws2811_fini(&led_string); | ||||
| 	} | ||||
| 	initialized = false; | ||||
| } | ||||
							
								
								
									
										43
									
								
								libsrc/leddevice/LedDeviceWS281x.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libsrc/leddevice/LedDeviceWS281x.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #ifndef LEDDEVICEWS281X_H_ | ||||
| #define LEDDEVICEWS281X_H_ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <leddevice/LedDevice.h> | ||||
| #include <ws2811.h> | ||||
|  | ||||
| class LedDeviceWS281x : public LedDevice | ||||
| { | ||||
| public: | ||||
| 	/// | ||||
| 	/// Constructs the LedDevice for WS281x (one wire 800kHz) | ||||
| 	/// | ||||
| 	/// @param gpio   The gpio pin to use (BCM chip counting, default is 18) | ||||
| 	/// @param leds   The number of leds attached to the gpio pin | ||||
| 	/// @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); | ||||
|  | ||||
| 	/// | ||||
| 	/// Destructor of the LedDevice, waits for DMA to complete and then cleans up | ||||
| 	/// | ||||
| 	~LedDeviceWS281x(); | ||||
|  | ||||
| 	/// | ||||
| 	/// Writes the led color values to the led-device | ||||
| 	/// | ||||
| 	/// @param ledValues The color-value per led | ||||
| 	/// @return Zero on succes else negative | ||||
| 	/// | ||||
| 	virtual int write(const std::vector<ColorRgb> &ledValues); | ||||
|  | ||||
| 	/// Switch the leds off | ||||
| 	virtual int switchOff(); | ||||
|  | ||||
| private: | ||||
| 	ws2811_t led_string; | ||||
| 	bool initialized; | ||||
| }; | ||||
|  | ||||
| #endif /* LEDDEVICEWS281X_H_ */ | ||||
		Reference in New Issue
	
	Block a user