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;
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -24,3 +24,8 @@ int LedDeviceTest::write(const std::vector<RgbColor> & ledValues)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LedDeviceTest::switchOff()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
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();
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user