Renamed ldp6803 to lpd6803

Added Lpd8806 device


Former-commit-id: 716cd60d1ac750fc2feca6f3621b20196b52a84e
This commit is contained in:
T. van der Zwan 2013-11-13 20:42:18 +00:00
parent d0429387ee
commit ef6ac97f84
6 changed files with 176 additions and 6 deletions

View File

@ -27,6 +27,7 @@ SET(Hyperion_HEADERS
${CURRENT_SOURCE_DIR}/device/LedDeviceSedu.h
${CURRENT_SOURCE_DIR}/device/LedDeviceWs2801.h
${CURRENT_SOURCE_DIR}/device/LedDeviceLpd6803.h
${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.h
${CURRENT_SOURCE_DIR}/device/LedDeviceAdalight.h
)
@ -48,6 +49,7 @@ SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/device/LedDeviceTest.cpp
${CURRENT_SOURCE_DIR}/device/LedDeviceWs2801.cpp
${CURRENT_SOURCE_DIR}/device/LedDeviceLpd6803.cpp
${CURRENT_SOURCE_DIR}/device/LedDeviceLpd8806.cpp
${CURRENT_SOURCE_DIR}/device/LedDeviceAdalight.cpp
)

View File

@ -14,6 +14,7 @@
#include <hyperion/ImageProcessorFactory.h>
#include "device/LedDeviceLpd6803.h"
#include "device/LedDeviceLpd8806.h"
#include "device/LedDeviceSedu.h"
#include "device/LedDeviceTest.h"
#include "device/LedDeviceWs2801.h"
@ -47,11 +48,21 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig)
const std::string output = deviceConfig["output"].asString();
const unsigned rate = deviceConfig["rate"].asInt();
LedDeviceLdp6803* deviceLdp6803 = new LedDeviceLdp6803(output, rate);
LedDeviceLpd6803* deviceLdp6803 = new LedDeviceLpd6803(output, rate);
deviceLdp6803->open();
device = deviceLdp6803;
}
else if (type == "lpd8806" || type == "ldp8806")
{
const std::string output = deviceConfig["output"].asString();
const unsigned rate = deviceConfig["rate"].asInt();
LedDeviceLpd8806* deviceLpd8806 = new LedDeviceLpd8806(output, rate);
deviceLpd8806->open();
device = deviceLpd8806;
}
else if (type == "sedu")
{
const std::string output = deviceConfig["output"].asString();

View File

@ -10,14 +10,14 @@
// hyperion local includes
#include "LedDeviceLpd6803.h"
LedDeviceLdp6803::LedDeviceLdp6803(const std::string& outputDevice, const unsigned baudrate) :
LedDeviceLpd6803::LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate) :
LedSpiDevice(outputDevice, baudrate),
_ledBuffer(0)
{
// empty
}
int LedDeviceLdp6803::write(const std::vector<ColorRgb> &ledValues)
int LedDeviceLpd6803::write(const std::vector<ColorRgb> &ledValues)
{
// Reconfigure if the current connfiguration does not match the required configuration
if (4 + 2*ledValues.size() != _ledBuffer.size())
@ -43,7 +43,7 @@ int LedDeviceLdp6803::write(const std::vector<ColorRgb> &ledValues)
return 0;
}
int LedDeviceLdp6803::switchOff()
int LedDeviceLpd6803::switchOff()
{
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
}

View File

@ -14,7 +14,7 @@
/// (R, G and B in the above illustration) making 16 bits per led. Total bytes = 4 + (2 x number of
/// leds)
///
class LedDeviceLdp6803 : public LedSpiDevice
class LedDeviceLpd6803 : public LedSpiDevice
{
public:
///
@ -23,7 +23,7 @@ public:
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
/// @param[in] baudrate The used baudrate for writing to the output device
///
LedDeviceLdp6803(const std::string& outputDevice, const unsigned baudrate);
LedDeviceLpd6803(const std::string& outputDevice, const unsigned baudrate);
///
/// Writes the led color values to the led-device

View File

@ -0,0 +1,54 @@
// STL includes
#include <cstring>
#include <cstdio>
#include <iostream>
// Linux includes
#include <fcntl.h>
#include <sys/ioctl.h>
// hyperion local includes
#include "LedDeviceLpd8806.h"
LedDeviceLpd8806::LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate) :
LedSpiDevice(outputDevice, baudrate),
_ledBuffer(0)
{
// empty
}
int LedDeviceLpd8806::write(const std::vector<ColorRgb> &ledValues)
{
const unsigned clearSize = ledValues.size()/32+1;
// Reconfigure if the current connfiguration does not match the required configuration
if (3*ledValues.size() + clearSize != _ledBuffer.size())
{
// Initialise the buffer
_ledBuffer.resize(3*ledValues.size() + clearSize, 0x00);
// Perform an initial reset to start accepting data on the first led
writeBytes(clearSize, _ledBuffer.data());
}
// Copy the colors from the ColorRgb vector to the Ldp8806 data vector
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
{
const ColorRgb& rgb = ledValues[iLed];
_ledBuffer[iLed*3] = 0x80 | (rgb.red >> 1);
_ledBuffer[iLed*3+1] = 0x80 | (rgb.green >> 1);
_ledBuffer[iLed*3+2] = 0x80 | (rgb.blue >> 1);
}
// Write the data
if (writeBytes(_ledBuffer.size(), _ledBuffer.data()) < 0)
{
return -1;
}
return 0;
}
int LedDeviceLpd8806::switchOff()
{
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
}

View File

@ -0,0 +1,103 @@
#pragma once
// Local hyperion incluse
#include "LedSpiDevice.h"
///
/// Implementation of the LedDevice interface for writing to LPD8806 led device.
///
/// The following description is copied from 'adafruit' (github.com/adafruit/LPD8806)
///
/// Clearing up some misconceptions about how the LPD8806 drivers work:
///
/// The LPD8806 is not a FIFO shift register. The first data out controls the
/// LED *closest* to the processor (unlike a typical shift register, where the
/// first data out winds up at the *furthest* LED). Each LED driver 'fills up'
/// with data and then passes through all subsequent bytes until a latch
/// condition takes place. This is actually pretty common among LED drivers.
///
/// All color data bytes have the high bit (128) set, with the remaining
/// seven bits containing a brightness value (0-127). A byte with the high
/// bit clear has special meaning (explained later).
///
/// The rest gets bizarre...
///
/// The LPD8806 does not perform an in-unison latch (which would display the
/// newly-transmitted data all at once). Rather, each individual byte (even
/// the separate G, R, B components of each LED) is latched AS IT ARRIVES...
/// or more accurately, as the first bit of the subsequent byte arrives and
/// is passed through. So the strip actually refreshes at the speed the data
/// is issued, not instantaneously (this can be observed by greatly reducing
/// the data rate). This has implications for POV displays and light painting
/// applications. The 'subsequent' rule also means that at least one extra
/// byte must follow the last pixel, in order for the final blue LED to latch.
///
/// To reset the pass-through behavior and begin sending new data to the start
/// of the strip, a number of zero bytes must be issued (remember, all color
/// data bytes have the high bit set, thus are in the range 128 to 255, so the
/// zero is 'special'). This should be done before each full payload of color
/// values to the strip. Curiously, zero bytes can only travel one meter (32
/// LEDs) down the line before needing backup; the next meter requires an
/// extra zero byte, and so forth. Longer strips will require progressively
/// more zeros. *(see note below)
///
/// In the interest of efficiency, it's possible to combine the former EOD
/// extra latch byte and the latter zero reset...the same data can do double
/// duty, latching the last blue LED while also resetting the strip for the
/// next payload.
///
/// So: reset byte(s) of suitable length are issued once at startup to 'prime'
/// the strip to a known ready state. After each subsequent LED color payload,
/// these reset byte(s) are then issued at the END of each payload, both to
/// latch the last LED and to prep the strip for the start of the next payload
/// (even if that data does not arrive immediately). This avoids a tiny bit
/// of latency as the new color payload can begin issuing immediately on some
/// signal, such as a timer or GPIO trigger.
///
/// Technically these zero byte(s) are not a latch, as the color data (save
/// for the last byte) is already latched. It's a start-of-data marker, or
/// an indicator to clear the thing-that's-not-a-shift-register. But for
/// conversational consistency with other LED drivers, we'll refer to it as
/// a 'latch' anyway.
///
/// This has been validated independently with multiple customers'
/// hardware. Please do not report as a bug or issue pull requests for
/// this. Fewer zeros sometimes gives the *illusion* of working, the first
/// payload will correctly load and latch, but subsequent frames will drop
/// data at the end. The data shortfall won't always be visually apparent
/// depending on the color data loaded on the prior and subsequent frames.
/// Tested. Confirmed. Fact.
///
///
/// The summary of the story is that the following needs to be writen on the spi-device:
/// 1RRRRRRR 1GGGGGGG 1BBBBBBB 1RRRRRRR 1GGGGGGG ... ... 1GGGGGGG 1BBBBBBB 00000000 00000000 ...
/// |---------led_1----------| |---------led_2-- -led_n----------| |----clear data--
///
/// The number of zeroes in the 'clear data' is (#led/32 + 1)bytes (or *8 for bits)
///
class LedDeviceLpd8806 : public LedSpiDevice
{
public:
///
/// Constructs the LedDevice for a string containing leds of the type LPD8806
///
/// @param[in] outputDevice The name of the output device (eg '/dev/spidev0.0')
/// @param[in] baudrate The used baudrate for writing to the output device
///
LedDeviceLpd8806(const std::string& outputDevice, const unsigned baudrate);
///
/// 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:
/// The buffer containing the packed RGB values
std::vector<uint8_t> _ledBuffer;
};