hyperion.ng/libsrc/hyperion/LinearColorSmoothing.cpp
johan 3e4c38b57a Added smoothing to the Hyperion configuration
Former-commit-id: 85e27d54841de5030199dd7f70bb0f29250abb6a
2013-10-27 21:06:35 +01:00

92 lines
2.1 KiB
C++

// Qt includes
#include <QDateTime>
#include "LinearColorSmoothing.h"
LinearColorSmoothing::LinearColorSmoothing(LedDevice *ledDevice, double ledUpdateFrequency_hz, int settlingTime_ms) :
QObject(),
LedDevice(),
_ledDevice(ledDevice),
_updateInterval(1000 / ledUpdateFrequency_hz),
_settlingTime(settlingTime_ms),
_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);
}
}