2013-10-27 18:04:37 +01:00
|
|
|
// Qt includes
|
|
|
|
#include <QDateTime>
|
|
|
|
|
|
|
|
#include "LinearColorSmoothing.h"
|
|
|
|
|
2013-10-27 21:06:35 +01:00
|
|
|
LinearColorSmoothing::LinearColorSmoothing(LedDevice *ledDevice, double ledUpdateFrequency_hz, int settlingTime_ms) :
|
2013-10-27 18:04:37 +01:00
|
|
|
QObject(),
|
|
|
|
LedDevice(),
|
|
|
|
_ledDevice(ledDevice),
|
2013-10-27 21:06:35 +01:00
|
|
|
_updateInterval(1000 / ledUpdateFrequency_hz),
|
|
|
|
_settlingTime(settlingTime_ms),
|
2013-10-27 18:04:37 +01:00
|
|
|
_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);
|
|
|
|
}
|
|
|
|
}
|