Merge branch 'master' into macos_compile

Conflicts:
	libsrc/leddevice/CMakeLists.txt
	libsrc/leddevice/LedDeviceFactory.cpp
	test/TestRs232HighSpeed.cpp

Former-commit-id: 5583f2f881afd1a9b0c8ec3a52d7d3b54fe1dff7
This commit is contained in:
T. van der Zwan
2013-12-28 08:55:06 +01:00
27 changed files with 1428 additions and 187 deletions

View File

@@ -24,6 +24,8 @@ SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2811.h
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.h
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.h
@@ -37,6 +39,9 @@ SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedRs232Device.cpp
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
${CURRENT_SOURCE_DIR}/LedDeviceWs2811.cpp
${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.cpp
${CURRENT_SOURCE_DIR}/LedDeviceAdalight.cpp
${CURRENT_SOURCE_DIR}/LedDeviceLightpack.cpp
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp
${CURRENT_SOURCE_DIR}/LedDeviceMultiLightpack.cpp

View File

@@ -7,11 +7,12 @@
#include "LedDeviceLpd6803.h"
#include "LedDeviceLpd8806.h"
#include "LedDeviceWs2801.h"
#include "LedDeviceWs2811.h"
#endif
#include "LedDeviceSedu.h"
#include "LedDeviceTest.h"
#include "LedDeviceWs2811.h"
#include "LedDeviceWs2812b.h"
#include "LedDeviceAdalight.h"
#include "LedDevicePaintpack.h"
#include "LedDeviceLightpack.h"
@@ -37,23 +38,6 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
device = deviceWs2801;
}
// else if (type == "ws2811")
// {
// const std::string output = deviceConfig["output"].asString();
// const std::string outputSpeed = deviceConfig["output"].asString();
// const std::string timingOption = deviceConfig["timingOption"].asString();
// ws2811::SpeedMode speedMode = (outputSpeed == "high")? ws2811::highspeed : ws2811::lowspeed;
// if (outputSpeed != "high" && outputSpeed != "low")
// {
// std::cerr << "Incorrect speed-mode selected for WS2811: " << outputSpeed << " != {'high', 'low'}" << std::endl;
// }
// LedDeviceWs2811 * deviceWs2811 = new LedDeviceWs2811(output, ws2811::fromString(timingOption, ws2811::option_2855), speedMode);
// deviceWs2811->open();
// device = deviceWs2811;
// }
else if (type == "lpd6803" || type == "ldp6803")
{
const std::string output = deviceConfig["output"].asString();
@@ -75,6 +59,30 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
device = deviceLpd8806;
}
#endif
// else if (type == "ws2811")
// {
// const std::string output = deviceConfig["output"].asString();
// const std::string outputSpeed = deviceConfig["output"].asString();
// const std::string timingOption = deviceConfig["timingOption"].asString();
// ws2811::SpeedMode speedMode = (outputSpeed == "high")? ws2811::highspeed : ws2811::lowspeed;
// if (outputSpeed != "high" && outputSpeed != "low")
// {
// std::cerr << "Incorrect speed-mode selected for WS2811: " << outputSpeed << " != {'high', 'low'}" << std::endl;
// }
// LedDeviceWs2811 * deviceWs2811 = new LedDeviceWs2811(output, ws2811::fromString(timingOption, ws2811::option_2855), speedMode);
// deviceWs2811->open();
// device = deviceWs2811;
// }
else if (type == "ws2812b")
{
LedDeviceWs2812b * deviceWs2812b = new LedDeviceWs2812b();
deviceWs2812b->open();
device = deviceWs2812b;
}
else if (type == "adalight")
{
const std::string output = deviceConfig["output"].asString();

View File

@@ -0,0 +1,114 @@
// Linux includes
#include <unistd.h>
// Local Hyperion-Leddevice includes
#include "LedDeviceWs2812b.h"
LedDeviceWs2812b::LedDeviceWs2812b() :
LedRs232Device("/dev/ttyAMA0", 4000000)
{
fillTable();
}
int LedDeviceWs2812b::write(const std::vector<ColorRgb> & ledValues)
{
// Ensure the size of the led-buffer
if (_ledBuffer.size() != ledValues.size()*3)
{
_ledBuffer.resize(ledValues.size()*3);
}
// Translate the channel of each color to a signal
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
{
const ColorRgb & color = ledValues[iLed];
_ledBuffer[3*iLed] = _byte2signalTable[color.red];
_ledBuffer[3*iLed + 1] = _byte2signalTable[color.green];
_ledBuffer[3*iLed + 2] = _byte2signalTable[color.blue];
}
const int result = writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
// Official latch time is 50us (lets give it 50us more)
usleep(100);
return result;
}
int LedDeviceWs2812b::switchOff()
{
// Set all bytes in the signal buffer to zero
for (ByteSignal & signal : _ledBuffer)
{
signal = _byte2signalTable[0];
}
return writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
}
void LedDeviceWs2812b::fillTable()
{
_byte2signalTable.clear();
for (int byte=0; byte<256; ++byte)
{
const ByteSignal signal = byte2Signal(uint8_t(byte));
_byte2signalTable.push_back(signal);
}
}
LedDeviceWs2812b::ByteSignal LedDeviceWs2812b::byte2Signal(const uint8_t byte) const
{
ByteSignal result;
result.bit_12 = bits2Signal(byte & 0x80, byte & 0x40);
result.bit_34 = bits2Signal(byte & 0x20, byte & 0x10);
result.bit_56 = bits2Signal(byte & 0x08, byte & 0x04);
result.bit_78 = bits2Signal(byte & 0x02, byte & 0x01);
return result;
}
uint8_t LedDeviceWs2812b::bits2Signal(const bool bit1, const bool bit2) const
{
// See https://github.com/tvdzwan/hyperion/wiki/Ws2812b for the explanation of the given
// translations
// Encoding scheme 1
// 00 1 1000 1100 0 1 0111 0011 0 1 1100 1110 0 0xCE
// 01 1 1000 1110 0 1 0111 0001 0 1 1000 1110 0 0x8E
// 10 1 1100 1100 0 1 0011 0011 0 1 1100 1100 0 0xCC
// 11 1 1100 1110 0 1 0011 0001 0 1 1000 1100 0 0x8C
// Encoding schem 2
// 00 - 1 0000 1000 0 - 1 1111 0111 0 - 1 1110 1111 0 - 0xEF
// 01 - 1 0000 1111 0 - 1 1111 0000 0 - 1 0000 1111 0 - 0x0F
// 10 - 1 1110 1000 0 - 1 0001 0111 0 - 1 1110 1000 0 - 0xE8
// 11 - 1 1110 1111 0 - 1 0001 0000 0 - 1 0000 1000 0 - 0x08
if (bit1)
{
if (bit2)
{
// return 0x08;
return 0x8C;
}
else
{
// return 0xE8;
return 0xCC;
}
}
else
{
if (bit2)
{
// return 0x0F;
return 0x8E;
}
else
{
// return 0xEF;
return 0xCE;
}
}
return 0x00;
}

View File

@@ -0,0 +1,76 @@
#pragma once
// Hyperion leddevice includes
#include "LedRs232Device.h"
///
/// The LedDevice for controlling a string of WS2812B leds. These are controlled over the mini-UART
/// of the RPi (/dev/ttyAMA0).
///
class LedDeviceWs2812b : public LedRs232Device
{
public:
///
/// Constructs the device (all required parameters are hardcoded)
///
LedDeviceWs2812b();
///
/// Write the color data the the WS2812B led string
///
/// @param ledValues The color data
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues);
///
/// Write zero to all leds(that have been written by a previous write operation)
///
/// @return Zero on succes else negative
///
virtual int switchOff();
private:
///
/// Structure holding the four output-bytes corresponding to a single input byte
///
struct ByteSignal
{
uint8_t bit_12;
uint8_t bit_34;
uint8_t bit_56;
uint8_t bit_78;
};
/// Translation table from single input-byte to output-bytes
std::vector<ByteSignal> _byte2signalTable;
///
/// Fills the translation table (_byte2signalTable)
///
void fillTable();
///
/// Computes the output bytes that belong to a given input-byte (no table lookup)
///
/// @param byte The input byte
/// @return The four bytes (ByteSignal) for the output signal
///
ByteSignal byte2Signal(const uint8_t byte) const;
///
/// Translates two bits to a single byte
///
/// @param bit1 The value of the first bit (1=true, zero=false)
/// @param bit1 The value of the ssecond bit (1=true, zero=false)
///
/// @return The output-byte for the given two bit
///
uint8_t bits2Signal(const bool bit1, const bool bit2) const;
///
/// The output buffer for writing bytes to the output
///
std::vector<ByteSignal> _ledBuffer;
};

View File

@@ -57,7 +57,9 @@ int LedRs232Device::writeBytes(const unsigned size, const uint8_t * data)
try
{
_rs232Port.flushOutput();
_rs232Port.write(data, size);
_rs232Port.flush();
}
catch (const serial::SerialException & serialExc)
{
@@ -77,6 +79,7 @@ int LedRs232Device::writeBytes(const unsigned size, const uint8_t * data)
{
_rs232Port.open();
_rs232Port.write(data, size);
_rs232Port.flush();
}
catch (const std::exception & e)
{