mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Initial commit including a linear color smoother
Former-commit-id: ffc00087996324f989e56dc5c95ab734c7c86dfa
This commit is contained in:
parent
73243eb593
commit
0b08341ef1
@ -135,10 +135,11 @@ public:
|
|||||||
///
|
///
|
||||||
const InputInfo& getPriorityInfo(const int priority) const;
|
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 LedString createLedString(const Json::Value & ledsConfig);
|
||||||
static HsvTransform * createHsvTransform(const Json::Value & hsvConfig);
|
static HsvTransform * createHsvTransform(const Json::Value & hsvConfig);
|
||||||
static ColorTransform * createColorTransform(const Json::Value & colorConfig);
|
static ColorTransform * createColorTransform(const Json::Value & colorConfig);
|
||||||
|
static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
@ -175,7 +176,7 @@ private:
|
|||||||
bool _haveBgrOutput;
|
bool _haveBgrOutput;
|
||||||
|
|
||||||
/// The actual LedDevice
|
/// The actual LedDevice
|
||||||
LedDevice* _device;
|
LedDevice * _device;
|
||||||
|
|
||||||
/// The timer for handling priority channel timeouts
|
/// The timer for handling priority channel timeouts
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
|
@ -29,4 +29,7 @@ public:
|
|||||||
/// @return Zero on success else negative
|
/// @return Zero on success else negative
|
||||||
///
|
///
|
||||||
virtual int write(const std::vector<RgbColor>& ledValues) = 0;
|
virtual int write(const std::vector<RgbColor>& ledValues) = 0;
|
||||||
|
|
||||||
|
/// Switch the leds off
|
||||||
|
virtual int switchOff() = 0;
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,8 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
|
|||||||
# Group the headers that go through the MOC compiler
|
# Group the headers that go through the MOC compiler
|
||||||
SET(Hyperion_QT_HEADERS
|
SET(Hyperion_QT_HEADERS
|
||||||
${CURRENT_HEADER_DIR}/Hyperion.h
|
${CURRENT_HEADER_DIR}/Hyperion.h
|
||||||
|
|
||||||
|
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(Hyperion_HEADERS
|
SET(Hyperion_HEADERS
|
||||||
@ -34,6 +36,7 @@ SET(Hyperion_SOURCES
|
|||||||
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
|
||||||
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
|
||||||
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
|
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
|
||||||
|
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(Hyperion_RESOURCES
|
set(Hyperion_RESOURCES
|
||||||
|
@ -13,10 +13,12 @@
|
|||||||
#include "LedDeviceWs2801.h"
|
#include "LedDeviceWs2801.h"
|
||||||
#include "LedDeviceTest.h"
|
#include "LedDeviceTest.h"
|
||||||
|
|
||||||
|
#include "LinearColorSmoothing.h"
|
||||||
|
|
||||||
#include <utils/ColorTransform.h>
|
#include <utils/ColorTransform.h>
|
||||||
#include <utils/HsvTransform.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;
|
std::cout << "Device configuration: " << deviceConfig << std::endl;
|
||||||
LedDevice* device = nullptr;
|
LedDevice* device = nullptr;
|
||||||
@ -36,6 +38,7 @@ LedDevice* Hyperion::constructDevice(const Json::Value& deviceConfig)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::cout << "Unable to create device" << std::endl;
|
||||||
// Unknown / Unimplemented device
|
// Unknown / Unimplemented device
|
||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
@ -59,6 +62,7 @@ ColorTransform* Hyperion::createColorTransform(const Json::Value& colorConfig)
|
|||||||
ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel);
|
ColorTransform* transform = new ColorTransform(threshold, gamma, blacklevel, whitelevel);
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
LedString Hyperion::createLedString(const Json::Value& ledsConfig)
|
LedString Hyperion::createLedString(const Json::Value& ledsConfig)
|
||||||
{
|
{
|
||||||
LedString ledString;
|
LedString ledString;
|
||||||
@ -89,6 +93,12 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig)
|
|||||||
return ledString;
|
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) :
|
Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
||||||
_ledString(createLedString(jsonConfig["leds"])),
|
_ledString(createLedString(jsonConfig["leds"])),
|
||||||
_muxer(_ledString.leds().size()),
|
_muxer(_ledString.leds().size()),
|
||||||
@ -97,11 +107,16 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
|||||||
_greenTransform(createColorTransform(jsonConfig["color"]["green"])),
|
_greenTransform(createColorTransform(jsonConfig["color"]["green"])),
|
||||||
_blueTransform(createColorTransform(jsonConfig["color"]["blue"])),
|
_blueTransform(createColorTransform(jsonConfig["color"]["blue"])),
|
||||||
_haveBgrOutput(jsonConfig["device"].get("bgr-output", false).asBool()),
|
_haveBgrOutput(jsonConfig["device"].get("bgr-output", false).asBool()),
|
||||||
_device(constructDevice(jsonConfig["device"])),
|
_device(createDevice(jsonConfig["device"])),
|
||||||
_timer()
|
_timer()
|
||||||
{
|
{
|
||||||
|
// initialize the image processor factory
|
||||||
ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool());
|
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);
|
_timer.setSingleShot(true);
|
||||||
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
|
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
|
||||||
|
|
||||||
@ -112,6 +127,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) :
|
|||||||
|
|
||||||
Hyperion::~Hyperion()
|
Hyperion::~Hyperion()
|
||||||
{
|
{
|
||||||
|
// switch off all leds
|
||||||
|
clearall();
|
||||||
|
_device->switchOff();
|
||||||
|
|
||||||
// Delete the Led-String
|
// Delete the Led-String
|
||||||
delete _device;
|
delete _device;
|
||||||
|
|
||||||
|
@ -24,3 +24,8 @@ int LedDeviceTest::write(const std::vector<RgbColor> & ledValues)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LedDeviceTest::switchOff()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -32,6 +32,9 @@ public:
|
|||||||
///
|
///
|
||||||
virtual int write(const std::vector<RgbColor> & ledValues);
|
virtual int write(const std::vector<RgbColor> & ledValues);
|
||||||
|
|
||||||
|
/// Switch the leds off
|
||||||
|
virtual int switchOff();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The outputstream
|
/// The outputstream
|
||||||
std::ofstream _ofs;
|
std::ofstream _ofs;
|
||||||
|
@ -15,7 +15,8 @@ LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice,
|
|||||||
const unsigned baudrate) :
|
const unsigned baudrate) :
|
||||||
mDeviceName(outputDevice),
|
mDeviceName(outputDevice),
|
||||||
mBaudRate_Hz(baudrate),
|
mBaudRate_Hz(baudrate),
|
||||||
mFid(-1)
|
mFid(-1),
|
||||||
|
mLedCount(0)
|
||||||
{
|
{
|
||||||
memset(&spi, 0, sizeof(spi));
|
memset(&spi, 0, sizeof(spi));
|
||||||
|
|
||||||
@ -62,6 +63,8 @@ int LedDeviceWs2801::open()
|
|||||||
|
|
||||||
int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues)
|
int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues)
|
||||||
{
|
{
|
||||||
|
mLedCount = ledValues.size();
|
||||||
|
|
||||||
if (mFid < 0)
|
if (mFid < 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Can not write to device which is open." << std::endl;
|
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;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LedDeviceWs2801::switchOff()
|
||||||
|
{
|
||||||
|
return write(std::vector<RgbColor>(mLedCount, RgbColor::BLACK));
|
||||||
|
}
|
||||||
|
@ -44,6 +44,9 @@ public:
|
|||||||
///
|
///
|
||||||
virtual int write(const std::vector<RgbColor> &ledValues);
|
virtual int write(const std::vector<RgbColor> &ledValues);
|
||||||
|
|
||||||
|
/// Switch the leds off
|
||||||
|
virtual int switchOff();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The name of the output device
|
/// The name of the output device
|
||||||
const std::string mDeviceName;
|
const std::string mDeviceName;
|
||||||
@ -56,4 +59,7 @@ private:
|
|||||||
spi_ioc_transfer spi;
|
spi_ioc_transfer spi;
|
||||||
/// The 'latch' time for latching the shifted-value into the leds
|
/// The 'latch' time for latching the shifted-value into the leds
|
||||||
timespec latchTime;
|
timespec latchTime;
|
||||||
|
|
||||||
|
/// the number of leds (needed when switching off)
|
||||||
|
size_t mLedCount;
|
||||||
};
|
};
|
||||||
|
91
libsrc/hyperion/LinearColorSmoothing.cpp
Normal file
91
libsrc/hyperion/LinearColorSmoothing.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
72
libsrc/hyperion/LinearColorSmoothing.h
Normal file
72
libsrc/hyperion/LinearColorSmoothing.h
Normal 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;
|
||||||
|
};
|
@ -157,9 +157,6 @@ int main(int argc, char** argv)
|
|||||||
int rc = app.exec();
|
int rc = app.exec();
|
||||||
std::cout << "Application closed with code " << rc << std::endl;
|
std::cout << "Application closed with code " << rc << std::endl;
|
||||||
|
|
||||||
// Clear all colors (switchting off all leds)
|
|
||||||
hyperion.clearall();
|
|
||||||
|
|
||||||
// Delete all component
|
// Delete all component
|
||||||
delete bootSequence;
|
delete bootSequence;
|
||||||
delete dispmanx;
|
delete dispmanx;
|
||||||
|
Loading…
Reference in New Issue
Block a user