Initial commit including a linear color smoother

Former-commit-id: ffc00087996324f989e56dc5c95ab734c7c86dfa
This commit is contained in:
johan 2013-10-27 18:04:37 +01:00
parent 73243eb593
commit 0b08341ef1
11 changed files with 216 additions and 8 deletions

View File

@ -135,10 +135,11 @@ public:
///
const InputInfo& getPriorityInfo(const int priority) const;
static LedDevice * constructDevice(const Json::Value & deviceConfig);
static LedDevice * createDevice(const Json::Value & deviceConfig);
static LedString createLedString(const Json::Value & ledsConfig);
static HsvTransform * createHsvTransform(const Json::Value & hsvConfig);
static ColorTransform * createColorTransform(const Json::Value & colorConfig);
static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice);
private slots:
///
@ -175,7 +176,7 @@ private:
bool _haveBgrOutput;
/// The actual LedDevice
LedDevice* _device;
LedDevice * _device;
/// The timer for handling priority channel timeouts
QTimer _timer;

View File

@ -29,4 +29,7 @@ public:
/// @return Zero on success else negative
///
virtual int write(const std::vector<RgbColor>& ledValues) = 0;
/// Switch the leds off
virtual int switchOff() = 0;
};

View File

@ -6,6 +6,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
# Group the headers that go through the MOC compiler
SET(Hyperion_QT_HEADERS
${CURRENT_HEADER_DIR}/Hyperion.h
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
)
SET(Hyperion_HEADERS
@ -34,6 +36,7 @@ SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
)
set(Hyperion_RESOURCES

View File

@ -13,10 +13,12 @@
#include "LedDeviceWs2801.h"
#include "LedDeviceTest.h"
#include "LinearColorSmoothing.h"
#include <utils/ColorTransform.h>
#include <utils/HsvTransform.h>
LedDevice* Hyperion::constructDevice(const Json::Value& deviceConfig)
LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig)
{
std::cout << "Device configuration: " << deviceConfig << std::endl;
LedDevice* device = nullptr;
@ -36,6 +38,7 @@ LedDevice* Hyperion::constructDevice(const Json::Value& deviceConfig)
}
else
{
std::cout << "Unable to create device" << std::endl;
// Unknown / Unimplemented device
}
return device;
@ -59,6 +62,7 @@ ColorTransform* Hyperion::createColorTransform(const Json::Value& colorConfig)
ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel);
return transform;
}
LedString Hyperion::createLedString(const Json::Value& ledsConfig)
{
LedString ledString;
@ -89,6 +93,12 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig)
return ledString;
}
LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice)
{
//return new LinearColorSmoothing(ledDevice, 20.0, .3);
return ledDevice;
}
Hyperion::Hyperion(const Json::Value &jsonConfig) :
_ledString(createLedString(jsonConfig["leds"])),
_muxer(_ledString.leds().size()),
@ -97,11 +107,16 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
_greenTransform(createColorTransform(jsonConfig["color"]["green"])),
_blueTransform(createColorTransform(jsonConfig["color"]["blue"])),
_haveBgrOutput(jsonConfig["device"].get("bgr-output", false).asBool()),
_device(constructDevice(jsonConfig["device"])),
_device(createDevice(jsonConfig["device"])),
_timer()
{
// initialize the image processor factory
ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool());
// initialize the color smoothing filter
_device = createColorSmoothing(jsonConfig["smoothing"], _device);
// setup the timer
_timer.setSingleShot(true);
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
@ -112,6 +127,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
Hyperion::~Hyperion()
{
// switch off all leds
clearall();
_device->switchOff();
// Delete the Led-String
delete _device;

View File

@ -24,3 +24,8 @@ int LedDeviceTest::write(const std::vector<RgbColor> & ledValues)
return 0;
}
int LedDeviceTest::switchOff()
{
return 0;
}

View File

@ -32,6 +32,9 @@ public:
///
virtual int write(const std::vector<RgbColor> & ledValues);
/// Switch the leds off
virtual int switchOff();
private:
/// The outputstream
std::ofstream _ofs;

View File

@ -15,7 +15,8 @@ LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice,
const unsigned baudrate) :
mDeviceName(outputDevice),
mBaudRate_Hz(baudrate),
mFid(-1)
mFid(-1),
mLedCount(0)
{
memset(&spi, 0, sizeof(spi));
@ -62,6 +63,8 @@ int LedDeviceWs2801::open()
int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues)
{
mLedCount = ledValues.size();
if (mFid < 0)
{
std::cerr << "Can not write to device which is open." << std::endl;
@ -81,3 +84,8 @@ int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues)
return retVal;
}
int LedDeviceWs2801::switchOff()
{
return write(std::vector<RgbColor>(mLedCount, RgbColor::BLACK));
}

View File

@ -44,6 +44,9 @@ public:
///
virtual int write(const std::vector<RgbColor> &ledValues);
/// Switch the leds off
virtual int switchOff();
private:
/// The name of the output device
const std::string mDeviceName;
@ -56,4 +59,7 @@ private:
spi_ioc_transfer spi;
/// The 'latch' time for latching the shifted-value into the leds
timespec latchTime;
/// the number of leds (needed when switching off)
size_t mLedCount;
};

View File

@ -0,0 +1,91 @@
// Qt includes
#include <QDateTime>
#include "LinearColorSmoothing.h"
LinearColorSmoothing::LinearColorSmoothing(LedDevice *ledDevice, double ledUpdateFrequency, double settlingTime) :
QObject(),
LedDevice(),
_ledDevice(ledDevice),
_updateInterval(1000.0 / ledUpdateFrequency),
_settlingTime(1000 * settlingTime),
_timer()
{
_timer.setSingleShot(false);
_timer.setInterval(_updateInterval);
connect(&_timer, SIGNAL(timeout()), this, SLOT(updateLeds()));
}
LinearColorSmoothing::~LinearColorSmoothing()
{
delete _ledDevice;
}
int LinearColorSmoothing::write(const std::vector<RgbColor> &ledValues)
{
// received a new target color
if (_previousValues.size() == 0)
{
// not initialized yet
_targetTime = QDateTime::currentMSecsSinceEpoch() + _settlingTime;
_targetValues = ledValues;
_previousTime = QDateTime::currentMSecsSinceEpoch();
_previousValues = ledValues;
_timer.start();
}
else
{
_targetTime = QDateTime::currentMSecsSinceEpoch() + _settlingTime;
memcpy(_targetValues.data(), ledValues.data(), ledValues.size() * sizeof(RgbColor));
}
return 0;
}
int LinearColorSmoothing::switchOff()
{
// stop smoothing filter
_timer.stop();
// return to uninitialized state
_previousValues.clear();
_previousTime = 0;
_targetValues.clear();
_targetTime = 0;
// finally switch off all leds
return _ledDevice->switchOff();
}
void LinearColorSmoothing::updateLeds()
{
int64_t now = QDateTime::currentMSecsSinceEpoch();
int deltaTime = _targetTime - now;
if (deltaTime < 0)
{
memcpy(_previousValues.data(), _targetValues.data(), _targetValues.size() * sizeof(RgbColor));
_previousTime = now;
_ledDevice->write(_previousValues);
}
else
{
float k = 1.0f - 1.0f * deltaTime / (_targetTime - _previousTime);
for (size_t i = 0; i < _previousValues.size(); ++i)
{
RgbColor & prev = _previousValues[i];
RgbColor & target = _targetValues[i];
prev.red += k * (target.red - prev.red);
prev.green += k * (target.green - prev.green);
prev.blue += k * (target.blue - prev.blue);
}
_previousTime = now;
_ledDevice->write(_previousValues);
}
}

View File

@ -0,0 +1,72 @@
#pragma once
// STL includes
#include <string>
#include <vector>
// Qt includes
#include <QTimer>
// Linux-SPI includes
#include <linux/spi/spidev.h>
// hyperion incluse
#include <hyperion/LedDevice.h>
/// Linear Smooting class
///
/// This class processes the requested led values and forwards them to the device after applying
/// a linear smoothing effect. This class can be handled as a generic LedDevice.
class LinearColorSmoothing : public QObject, public LedDevice
{
Q_OBJECT
public:
/// Constructor
/// @param LedDevice the led device
/// @param LedUpdatFrequency The frequency at which the leds will be updated (Hz)
/// @param settingTime The time after which the updated led values have been fully applied (sec)
LinearColorSmoothing(LedDevice *ledDevice, double ledUpdateFrequency, double settlingTime);
/// Destructor
virtual ~LinearColorSmoothing();
/// write updated values as input for the smoothing filter
///
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<RgbColor> &ledValues);
/// Switch the leds off
virtual int switchOff();
private slots:
/// Timer callback which writes updated led values to the led device
void updateLeds();
private:
/// The led device
LedDevice * _ledDevice;
/// The interval at which to update the leds (msec)
const int64_t _updateInterval;
/// The time after which the updated led values have been fully applied (msec)
const int64_t _settlingTime;
/// The Qt timer object
QTimer _timer;
/// The timestamp at which the target data should be fully applied
int64_t _targetTime;
/// The target led data
std::vector<RgbColor> _targetValues;
/// The timestamp of the previously written led data
int64_t _previousTime;
/// The previously written led data
std::vector<RgbColor> _previousValues;
};

View File

@ -157,9 +157,6 @@ int main(int argc, char** argv)
int rc = app.exec();
std::cout << "Application closed with code " << rc << std::endl;
// Clear all colors (switchting off all leds)
hyperion.clearall();
// Delete all component
delete bootSequence;
delete dispmanx;