Merge remote-tracking branch 'upstream/master/master'

Former-commit-id: 089220e45a
This commit is contained in:
redpanther 2016-02-29 04:25:19 +01:00
commit 102d56b8f9
21 changed files with 387 additions and 69 deletions

View File

@ -6,8 +6,8 @@ SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER ${CUBIXCROSS_DIR}/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER ${CUBIXCROSS_DIR}/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-g++)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard")
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH ${CUBIXCROSS_DIR}/rootfs)

View File

@ -28,6 +28,7 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore
"$builddir/bin/hyperiond" \
"$builddir/bin/hyperion-remote" \
"$builddir/bin/hyperion-v4l2" \
"$builddir/bin/gpio2spi" \
"$builddir/bin/dispmanx2png" \
"$repodir/effects/"* \
"$repodir/bin/hyperion.init.sh" \

View File

@ -40,7 +40,7 @@ if [ $IS_OPENELEC -eq 1 ]; then
if [ $IS_IMX6 -eq 1 ]; then
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz | tar -C /storage -xz
else
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz | tar -C /storage -xz
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz | tar -C /storage -xz
fi
curl -L --get https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.deps.openelec-rpi.tar.gz | tar -C /storage/hyperion/bin -xz
# modify the default config to have a correct effect path
@ -49,7 +49,7 @@ else
if [ $IS_IMX6 -eq 1 ]; then
wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_imx6.tar.gz -O - | tar -C /opt -xz
else
wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion.tar.gz -O - | tar -C /opt -xz
wget https://raw.githubusercontent.com/tvdzwan/hyperion/master/deploy/hyperion_rpi.tar.gz -O - | tar -C /opt -xz
fi
fi

View File

@ -1 +1 @@
471d676fb66aa53e3b10d887a1d9e6d3b4afea90
44d552b5adb3dc5af38edd5e6fb208a0dc75d63d

View File

@ -1 +1 @@
5c164e4ff52076a530461cdf6966943d52cd39df
5b0f057a8591d76be009018b302977faeec5159a

View File

@ -1 +1 @@
d2bf44cca4e7753b53acc2ebbdb933ba8f74f93f
7f0d60e7e0c7075cae5cef69ec5408f3087c00df

View File

@ -1 +1 @@
7936b39302bec31b18f11a321ba6904c12b5c3ec
511ab205cce688c5d7151087d8659905402e5015

View File

@ -1 +1 @@
774c67bd8e4e46d2ebf9c223a38fdfd93cae1100
e26ac1a0bf52bcd54ab00c37ff25d01a457eec9d

57
doc/UDP_led_driver.txt Normal file
View File

@ -0,0 +1,57 @@
BACKGROUND
---------------------------------------------------------
The UDP led device type can be used to send LED data over UDP packets.
It was originally designed to support an ESP8266 Wifi module based WS2812
LED strip controller.
I've used this to support :
- A string of 600 LEDs as xmas decorations
The effects development kit is great for these scenarios
- a 61 LED collection of concentric circles
This has been used as a "night light" and a super lo-res
TV
In each of these cases, the hyperion-remote iOS app is a great way to
control the effects.
CONFIG
---------------------------------------------------------
Simple example for devices that support a raw binary protocol.
"device" :
{
"name" : "MyPi",
"type" : "udp",
"output" : "esp201-0.home:2391", "protocol" : 0,
"rate" : 1000000,
"colorOrder" : "grb"
},
If you are using an ESP8266/Arduino device with a long LED strip, you chould use this alternate protocol.
The ESP8266/Arduino doesnt support datagram re-assembly so will never see any udp packets greater than 1450.
"device" :
{
"name" : "MyPi",
"type" : "udp",
// "output" : "esp201-0.home:2392", "protocol" : 2, "maxpacket" : 1450,
"rate" : 1000000,
"colorOrder" : "rgb"
},
PROTOCOL
---------------------------------------------------------
Simple UDP packets are sent.
Packet Format protocol 0:
3 bytes per LED as R, G, B
Packet Format protocol 2:
0: update number & 0xf;
1: fragment of this update
2: 1st led# of this update - high byte
3: 1st led# of this update - low byte
4..n 3 bytes per LED as R, G, B

8
effects/udp.json Normal file
View File

@ -0,0 +1,8 @@
{
"name" : "UDP listener",
"script" : "udp.py",
"args" :
{
"udpPort" : 2391
}
}

47
effects/udp.py Normal file
View File

@ -0,0 +1,47 @@
import hyperion
import time
import colorsys
import socket
import errno
# Get the parameters
udpPort = int(hyperion.args.get('udpPort', 2812))
UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
UDPSock.setblocking(False)
listen_addr = ("",udpPort)
print "udp.py: bind socket port:",udpPort
UDPSock.bind(listen_addr)
hyperion.setColor(hyperion.ledCount * bytearray((int(0), int(0), int(0))) )
# Start the write data loop
while not hyperion.abort():
try:
data,addr = UDPSock.recvfrom(4500)
# print data.strip(),len(data),addr
if (len(data)%3 == 0):
# print "numleds ",len(data)/3
ledData = bytearray()
for i in range(hyperion.ledCount):
if (i<(len(data)/3)):
ledData += data[i*3+0]
ledData += data[i*3+1]
ledData += data[i*3+2]
else:
ledData += bytearray((int(0), int(0), int(0)))
hyperion.setColor(ledData)
else:
print "not div 3"
except IOError as e:
if e.errno == errno.EWOULDBLOCK:
pass
else:
print "errno:", e.errno
print "udp.py: closing socket"
UDPSock.close()

View File

@ -1,3 +1,4 @@
//#include <iostream>
#pragma once
// Utils includes
@ -82,10 +83,13 @@ namespace hyperion
int firstNonBlackXPixelIndex = -1;
int firstNonBlackYPixelIndex = -1;
width--; // remove 1 pixel to get end pixel index
height--;
// find first X pixel of the image
for (int x = 0; x < width33percent; ++x)
{
const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check
const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check
const Pixel_T & color2 = image(x, height33percent);
const Pixel_T & color3 = image(x, height66percent);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
@ -98,7 +102,7 @@ namespace hyperion
// find first Y pixel of the image
for (int y = 0; y < height33percent; ++y)
{
const Pixel_T & color1 = image(xCenter, (height - 1 - y)); // bottom center line check
const Pixel_T & color1 = image(xCenter, (height - y)); // bottom center line check
const Pixel_T & color2 = image(width33percent, y );
const Pixel_T & color3 = image(width66percent, y);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
@ -174,7 +178,8 @@ namespace hyperion
}
// osd detection mode (find x then y at detected x to avoid changes by osd overlays)
///
/// osd detection mode (find x then y at detected x to avoid changes by osd overlays)
template <typename Pixel_T>
BlackBorder process_osd(const Image<Pixel_T> & image)
{
@ -184,20 +189,21 @@ namespace hyperion
int height = image.height();
int width33percent = width / 3;
int height33percent = height / 3;
// int width66percent = width33percent * 2;
int height66percent = height33percent * 2;
// int xCenter = width / 2;
int yCenter = height / 2;
int firstNonBlackXPixelIndex = -1;
int firstNonBlackYPixelIndex = -1;
width--; // remove 1 pixel to get end pixel index
height--;
// find first X pixel of the image
int x;
for (x = 0; x < width33percent; ++x)
{
const Pixel_T & color1 = image( (width - 1 - x), yCenter); // right side center line check
const Pixel_T & color1 = image( (width - x), yCenter); // right side center line check
const Pixel_T & color2 = image(x, height33percent);
const Pixel_T & color3 = image(x, height66percent);
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
@ -210,11 +216,13 @@ namespace hyperion
// find first Y pixel of the image
for (int y = 0; y < height33percent; ++y)
{
const Pixel_T & color1 = image(x, (height - 1 - y)); // left side bottom check
const Pixel_T & color2 = image(x, y );// left side top check
const Pixel_T & color3 = image( (width - 1 - x), y); // right side top check
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3))
const Pixel_T & color1 = image(x, y );// left side top check
const Pixel_T & color2 = image(x, (height - y)); // left side bottom check
const Pixel_T & color3 = image( (width - x), y); // right side top check
const Pixel_T & color4 = image( (width - x), (height - y)); // right side bottom check
if (!isBlack(color1) || !isBlack(color2) || !isBlack(color3) || !isBlack(color4))
{
// std::cout << "y " << y << " lt " << int(isBlack(color1)) << " lb " << int(isBlack(color2)) << " rt " << int(isBlack(color3)) << " rb " << int(isBlack(color4)) << std::endl;
firstNonBlackYPixelIndex = y;
break;
}

View File

@ -1,6 +1,7 @@
#include <iostream>
// BlackBorders includes
#include <blackborder/BlackBorderDetector.h>
#include <cmath>
using namespace hyperion;

View File

@ -1,12 +1,9 @@
//*
#include <iostream>
/*
#include <iomanip>
using std::cout;
using std::endl;
using std::setw;
using std::left;
//*/
// Blackborder includes
#include <blackborder/BlackBorderProcessor.h>

View File

@ -1,7 +1,3 @@
// STL includes
#include <cmath>
// Hyperion includes
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>

View File

@ -33,8 +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}/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
@ -55,8 +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}/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

View File

@ -1,7 +1,9 @@
// STL includes
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
// Linux includes
#include <fcntl.h>
@ -17,46 +19,27 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned
// empty
}
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define APA102_START_FRAME_BYTES 4
#define APA102_LED_BYTES 4
#define APA102_END_FRAME_BITS_MIN 32
#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN)
#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1)
#define APA102_LED_HEADER 0xe0
#define APA102_LED_MAX_INTENSITY 0x1f
int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
{
const unsigned int startFrameSize = APA102_START_FRAME_BYTES;
const unsigned int ledsCount = ledValues.size() ;
const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ;
const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ;
const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ;
const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ;
if(_ledBuffer.size() != transferSize){
_ledBuffer.resize(transferSize, 0x00);
const unsigned int startFrameSize = 4;
const unsigned int endFrameSize = std::max<unsigned int>(((ledValues.size() + 15) / 16), 4);
const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize;
if(_ledBuffer.size() != mLedCount){
_ledBuffer.resize(mLedCount, 0xFF);
_ledBuffer[0] = 0x00;
_ledBuffer[1] = 0x00;
_ledBuffer[2] = 0x00;
_ledBuffer[3] = 0x00;
}
unsigned idx = 0, i;
for (i=0; i<APA102_START_FRAME_BYTES; i++) {
_ledBuffer[idx++] = 0x00 ;
for (unsigned iLed=1; iLed<=ledValues.size(); ++iLed) {
const ColorRgb& rgb = ledValues[iLed-1];
_ledBuffer[iLed*4] = 0xFF;
_ledBuffer[iLed*4+1] = rgb.red;
_ledBuffer[iLed*4+2] = rgb.green;
_ledBuffer[iLed*4+3] = rgb.blue;
}
for (i=0; i<ledsCount; i++) {
const ColorRgb& rgb = ledValues[i];
_ledBuffer[idx++] = APA102_LED_HEADER + APA102_LED_MAX_INTENSITY;
_ledBuffer[idx++] = rgb.red;
_ledBuffer[idx++] = rgb.green;
_ledBuffer[idx++] = rgb.blue;
}
for(i=0; i<endFrameSize; i++)
_ledBuffer[idx++] = 0x00 ;
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}

View File

@ -31,6 +31,7 @@
#include "LedDeviceSedu.h"
#include "LedDeviceTest.h"
#include "LedDeviceFadeCandy.h"
#include "LedDeviceUdp.h"
#include "LedDeviceHyperionUsbasp.h"
#include "LedDevicePhilipsHue.h"
#include "LedDeviceTpm2.h"
@ -251,6 +252,14 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
const uint16_t channel = deviceConfig.get("channel", 0).asInt();
device = new LedDeviceFadeCandy(host, port, channel);
}
else if (type == "udp")
{
const std::string output = deviceConfig["output"].asString();
const unsigned rate = deviceConfig["rate"].asInt();
const unsigned protocol = deviceConfig["protocol"].asInt();
const unsigned maxPacket = deviceConfig["maxpacket"].asInt();
device = new LedDeviceUdp(output, rate, protocol, maxPacket);
}
else if (type == "tpm2")
{
const std::string output = deviceConfig["output"].asString();

View File

@ -1,8 +1,8 @@
#include "LedDeviceFadeCandy.h"
static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
static const unsigned OPC_SET_PIXELS = 0; // OPC command codes
static const unsigned OPC_HEADER_SIZE = 4; // OPC header size
static const ssize_t MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
static const ssize_t OPC_SET_PIXELS = 0; // OPC command codes
static const ssize_t OPC_HEADER_SIZE = 4; // OPC header size
LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) :

View File

@ -0,0 +1,165 @@
// Local-Hyperion includes
#include "LedDeviceUdp.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <assert.h>
struct addrinfo hints, *servinfo, *p;
//char udpbuffer[1024];
int sockfd;
int ledprotocol;
int leds_per_pkt;
int update_number;
int fragment_number;
LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket)
//LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate) :
// _ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str())
{
std::string hostname;
std::string port;
ledprotocol = protocol;
leds_per_pkt = ((maxPacket-4)/3);
if (leds_per_pkt <= 0) {
leds_per_pkt = 200;
}
//printf ("leds_per_pkt is %d\n", leds_per_pkt);
int got_colon=0;
for (unsigned int i=0; i<output.length(); i++) {
if (output[i] == ':') {
got_colon++;
} else if (got_colon == 0) {
hostname+=output[i];
} else {
port+=output[i];
}
}
//std::cout << "output " << output << " hostname " << hostname << " port " << port <<std::endl;
assert(got_colon==1);
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
assert(rv==0);
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to create socket\n");
assert(p!=NULL);
}
}
LedDeviceUdp::~LedDeviceUdp()
{
// empty
}
int LedDeviceUdp::write(const std::vector<ColorRgb> & ledValues)
{
char udpbuffer[4096];
int udpPtr=0;
update_number++;
update_number &= 0xf;
if (ledprotocol == 0) {
int i=0;
for (const ColorRgb& color : ledValues)
{
if (i<4090) {
udpbuffer[i++] = color.red;
udpbuffer[i++] = color.green;
udpbuffer[i++] = color.blue;
}
//printf ("c.red %d sz c.red %d\n", color.red, sizeof(color.red));
}
sendto(sockfd, udpbuffer, i, 0, p->ai_addr, p->ai_addrlen);
}
if (ledprotocol == 1) {
#define MAXLEDperFRAG 450
int mLedCount = ledValues.size();
for (int frag=0; frag<4; frag++) {
udpPtr=0;
udpbuffer[udpPtr++] = 0;
udpbuffer[udpPtr++] = 0;
udpbuffer[udpPtr++] = (frag*MAXLEDperFRAG)/256; // high byte
udpbuffer[udpPtr++] = (frag*MAXLEDperFRAG)%256; // low byte
int ct=0;
for (int this_led = frag*300; ((this_led<mLedCount) && (ct++<MAXLEDperFRAG)); this_led++) {
const ColorRgb& color = ledValues[this_led];
if (udpPtr<4090) {
udpbuffer[udpPtr++] = color.red;
udpbuffer[udpPtr++] = color.green;
udpbuffer[udpPtr++] = color.blue;
}
}
if (udpPtr > 7)
sendto(sockfd, udpbuffer, udpPtr, 0, p->ai_addr, p->ai_addrlen);
}
}
if (ledprotocol == 2) {
udpPtr = 0;
unsigned int ledCtr = 0;
fragment_number = 0;
udpbuffer[udpPtr++] = update_number & 0xf;
udpbuffer[udpPtr++] = fragment_number++;
udpbuffer[udpPtr++] = ledCtr/256; // high byte
udpbuffer[udpPtr++] = ledCtr%256; // low byte
for (const ColorRgb& color : ledValues)
{
if (udpPtr<4090) {
udpbuffer[udpPtr++] = color.red;
udpbuffer[udpPtr++] = color.green;
udpbuffer[udpPtr++] = color.blue;
}
ledCtr++;
if ( (ledCtr % leds_per_pkt == 0) || (ledCtr == ledValues.size()) ) {
sendto(sockfd, udpbuffer, udpPtr, 0, p->ai_addr, p->ai_addrlen);
memset(udpbuffer, 0, sizeof udpbuffer);
udpPtr = 0;
udpbuffer[udpPtr++] = update_number & 0xf;
udpbuffer[udpPtr++] = fragment_number++;
udpbuffer[udpPtr++] = ledCtr/256; // high byte
udpbuffer[udpPtr++] = ledCtr%256; // low byte
}
}
}
return 0;
}
int LedDeviceUdp::switchOff()
{
// return write(std::vector<ColorRgb>(mLedCount, ColorRgb{0,0,0}));
return 0;
}

View File

@ -0,0 +1,44 @@
#pragma once
// STL includes0
#include <fstream>
// Leddevice includes
#include <leddevice/LedDevice.h>
///
/// Implementation of the LedDevice that write the led-colors to an
/// ASCII-textfile('/home/pi/LedDevice.out')
///
class LedDeviceUdp : public LedDevice
{
public:
///
/// Constructs the test-device, which opens an output stream to the file
///
LedDeviceUdp(const std::string& output, const unsigned baudrate, const unsigned protocol, const unsigned maxPacket);
///
/// Destructor of this test-device
///
virtual ~LedDeviceUdp();
///
/// Writes the given led-color values to the output stream
///
/// @param ledValues The color-value per led
///
/// @return Zero on success else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues);
/// Switch the leds off
virtual int switchOff();
private:
/// The outputstream
// std::ofstream _ofs;
/// the number of leds (needed when switching off)
size_t mLedCount;
};