Skip to content

Commit a2db590

Browse files
authored
Fixes - Smoothing, Color-Calibration (#1532)
* Smoothing Remove ouputrate as duplicate to update frequency * Serial LDEDDevices -Increase writeBlack to overcome issues on high baud rates * Serial LED-Devices - Support device feedback, show statistics provided by HyperSerial * Fix - Update Color Calibration on Remote Control when settings saved * Serial LED-Devices - Support device feedback, show statistics provided by HyperSerial
1 parent 46f9963 commit a2db590

File tree

10 files changed

+130
-87
lines changed

10 files changed

+130
-87
lines changed

assets/webconfig/i18n/en.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,6 @@
443443
"edt_conf_smooth_heading_title": "Smoothing",
444444
"edt_conf_smooth_interpolationRate_expl": "Speed of the calculation of smooth intermediate frames.",
445445
"edt_conf_smooth_interpolationRate_title": "Interpolation Rate",
446-
"edt_conf_smooth_outputRate_expl": "The output speed to your LED controller.",
447-
"edt_conf_smooth_outputRate_title": "Output Rate",
448446
"edt_conf_smooth_time_ms_expl": "How long should the smoothing gather pictures?",
449447
"edt_conf_smooth_time_ms_title": "Time",
450448
"edt_conf_smooth_type_expl": "Type of smoothing.",

assets/webconfig/js/content_remote.js

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ $(document).ready(function () {
1919
$('.ssthead').html(createTableRow([$.i18n('remote_input_origin'), $.i18n('remote_input_owner'), $.i18n('remote_input_priority'), $.i18n('remote_input_status')], true, true));
2020
createTable('crthead', 'crtbody', 'adjust_content', true);
2121

22-
2322
//create introduction
2423
if (window.showOptHelp) {
2524
createHint("intro", $.i18n('remote_color_intro', $.i18n('remote_losthint')), "color_intro");
@@ -30,56 +29,6 @@ $(document).ready(function () {
3029
createHint("intro", $.i18n('remote_videoMode_intro', $.i18n('remote_losthint')), "videomode_intro");
3130
}
3231

33-
//color adjustment
34-
var sColor = sortProperties(window.serverSchema.properties.color.properties.channelAdjustment.items.properties);
35-
var values = window.serverInfo.adjustment[0];
36-
37-
for (var key in sColor) {
38-
if (sColor[key].key != "id" && sColor[key].key != "leds") {
39-
var title = '<label for="cr_' + sColor[key].key + '">' + $.i18n(sColor[key].title) + '</label>';
40-
var property;
41-
var value = values[sColor[key].key];
42-
43-
if (sColor[key].type == "array") {
44-
property = '<div id="cr_' + sColor[key].key + '" class="input-group colorpicker-component" ><input type="text" class="form-control" /><span class="input-group-addon"><i></i></span></div>';
45-
$('.crtbody').append(createTableRow([title, property], false, true));
46-
createCP('cr_' + sColor[key].key, value, function (rgb, hex, e) {
47-
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), '[' + rgb.r + ',' + rgb.g + ',' + rgb.b + ']');
48-
});
49-
}
50-
else if (sColor[key].type == "boolean") {
51-
property = '<div class="checkbox"><input id="cr_' + sColor[key].key + '" type="checkbox" value="' + value + '"/><label></label></div>';
52-
$('.crtbody').append(createTableRow([title, property], false, true));
53-
54-
$('#cr_' + sColor[key].key).off().on('change', function (e) {
55-
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.checked);
56-
});
57-
}
58-
else {
59-
if (sColor[key].key == "brightness" ||
60-
sColor[key].key == "brightnessCompensation" ||
61-
sColor[key].key == "backlightThreshold" ||
62-
sColor[key].key == "saturationGain" ||
63-
sColor[key].key == "brightnessGain") {
64-
65-
property = '<input id="cr_' + sColor[key].key + '" type="number" class="form-control" min="' + sColor[key].minimum + '" max="' + sColor[key].maximum + '" step="' + sColor[key].step + '" value="' + value + '"/>';
66-
if (sColor[key].append === "edt_append_percent") {
67-
property = '<div class="input-group">' + property + '<span class="input-group-addon">' + $.i18n("edt_append_percent") + '</span></div>';
68-
}
69-
}
70-
else {
71-
property = '<input id="cr_' + sColor[key].key + '" type="number" class="form-control" min="0.1" max="4.0" step="0.1" value="' + value + '"/>';
72-
}
73-
74-
$('.crtbody').append(createTableRow([title, property], false, true));
75-
$('#cr_' + sColor[key].key).off().on('change', function (e) {
76-
valValue(this.id, this.value, this.min, this.max);
77-
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.value);
78-
});
79-
}
80-
}
81-
}
82-
8332
function sendEffect() {
8433
var efx = $("#effect_select").val();
8534
if (efx != "__none__") {
@@ -94,6 +43,59 @@ $(document).ready(function () {
9443
requestSetColor(rgb.r, rgb.g, rgb.b, duration);
9544
}
9645

46+
function updateChannelAdjustments() {
47+
48+
$('.crtbody').html("");
49+
var sColor = sortProperties(window.serverSchema.properties.color.properties.channelAdjustment.items.properties);
50+
var values = window.serverInfo.adjustment[0];
51+
52+
for (var key in sColor) {
53+
if (sColor[key].key != "id" && sColor[key].key != "leds") {
54+
var title = '<label for="cr_' + sColor[key].key + '">' + $.i18n(sColor[key].title) + '</label>';
55+
var property;
56+
var value = values[sColor[key].key];
57+
58+
if (sColor[key].type == "array") {
59+
property = '<div id="cr_' + sColor[key].key + '" class="input-group colorpicker-component" ><input type="text" class="form-control" /><span class="input-group-addon"><i></i></span></div>';
60+
$('.crtbody').append(createTableRow([title, property], false, true));
61+
createCP('cr_' + sColor[key].key, value, function (rgb, hex, e) {
62+
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), '[' + rgb.r + ',' + rgb.g + ',' + rgb.b + ']');
63+
});
64+
}
65+
else if (sColor[key].type == "boolean") {
66+
property = '<div class="checkbox"><input id="cr_' + sColor[key].key + '" type="checkbox" ' + (value ? "checked" : "") + '/><label></label></div>';
67+
$('.crtbody').append(createTableRow([title, property], false, true));
68+
69+
$('#cr_' + sColor[key].key).off().on('change', function (e) {
70+
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.checked);
71+
});
72+
}
73+
else {
74+
if (sColor[key].key == "brightness" ||
75+
sColor[key].key == "brightnessCompensation" ||
76+
sColor[key].key == "backlightThreshold" ||
77+
sColor[key].key == "saturationGain" ||
78+
sColor[key].key == "brightnessGain") {
79+
80+
property = '<input id="cr_' + sColor[key].key + '" type="number" class="form-control" min="' + sColor[key].minimum + '" max="' + sColor[key].maximum + '" step="' + sColor[key].step + '" value="' + value + '"/>';
81+
if (sColor[key].append === "edt_append_percent") {
82+
property = '<div class="input-group">' + property + '<span class="input-group-addon">' + $.i18n("edt_append_percent") + '</span></div>';
83+
}
84+
}
85+
else {
86+
property = '<input id="cr_' + sColor[key].key + '" type="number" class="form-control" min="0.1" max="4.0" step="0.1" value="' + value + '"/>';
87+
}
88+
89+
$('.crtbody').append(createTableRow([title, property], false, true));
90+
$('#cr_' + sColor[key].key).off().on('change', function (e) {
91+
valValue(this.id, this.value, this.min, this.max);
92+
requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.value);
93+
});
94+
}
95+
}
96+
}
97+
}
98+
9799
function updateInputSelect() {
98100
$('.sstbody').html("");
99101
var prios = window.serverInfo.priorities;
@@ -389,6 +391,7 @@ $(document).ready(function () {
389391
updateInputSelect();
390392
updateLedMapping();
391393
updateVideoMode();
394+
updateChannelAdjustments();
392395
if (EFFECTENGINE_ENABLED) {
393396
updateEffectlist();
394397
} else {
@@ -421,6 +424,16 @@ $(document).ready(function () {
421424
updateEffectlist();
422425
});
423426

427+
$(window.hyperion).on("cmd-settings-update", function (event) {
428+
if (event.response.data.color) {
429+
window.serverInfo.imageToLedMappingType = event.response.data.color.imageToLedMappingType;
430+
updateLedMapping();
431+
432+
window.serverInfo.adjustment = event.response.data.color.channelAdjustment;
433+
updateChannelAdjustments();
434+
}
435+
});
436+
424437
removeOverlay();
425438
});
426439

config/hyperion.config.json.default

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
"time_ms" : 200,
6161
"updateFrequency" : 25.0000,
6262
"interpolationRate" : 25.0000,
63-
"outputRate" : 25.0000,
6463
"decay" : 1,
6564
"dithering" : false,
6665
"updateDelay" : 0

include/hyperion/LinearColorSmoothing.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,6 @@ private slots:
230230
/// Flag for pausing
231231
bool _pause;
232232

233-
/// The rate at which color frames should be written to LED device.
234-
double _outputRate;
235-
236233
/// The interval time in microseconds for writing of LED Frames.
237234
int64_t _outputIntervalMicros;
238235

@@ -268,9 +265,6 @@ private slots:
268265
/// The type of smoothing to perform
269266
SmoothingType _type;
270267

271-
/// The rate at which color frames should be written to LED device.
272-
double _outputRate;
273-
274268
/// The rate at which interpolation of LED frames should be performed.
275269
double _interpolationRate;
276270

@@ -284,7 +278,7 @@ private slots:
284278
double _decay;
285279

286280
SmoothingCfg();
287-
SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type = SmoothingType::Linear, double outputRate = 0, double interpolationRate = 0, unsigned outputDelay = 0, bool dithering = false, double decay = 1);
281+
SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type = SmoothingType::Linear, double interpolationRate = 0, unsigned outputDelay = 0, bool dithering = false, double decay = 1);
288282

289283
static QString EnumToString(SmoothingType type);
290284
};

libsrc/hyperion/LinearColorSmoothing.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ const char* SETTINGS_KEY_OUTPUT_DELAY = "updateDelay";
4747

4848
const char* SETTINGS_KEY_DECAY = "decay";
4949
const char* SETTINGS_KEY_INTERPOLATION_RATE = "interpolationRate";
50-
const char* SETTINGS_KEY_OUTPUT_RATE = "outputRate";
5150
const char* SETTINGS_KEY_DITHERING = "dithering";
5251

5352
const int64_t DEFAULT_SETTLINGTIME = 200; // in ms
@@ -133,7 +132,6 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson
133132
cfg._pause = false;
134133
cfg._outputDelay = static_cast<unsigned>(obj[SETTINGS_KEY_OUTPUT_DELAY].toInt(DEFAULT_OUTPUTDEPLAY));
135134

136-
cfg._outputRate = obj[SETTINGS_KEY_OUTPUT_RATE].toDouble(DEFAULT_UPDATEFREQUENCY);
137135
cfg._interpolationRate = obj[SETTINGS_KEY_INTERPOLATION_RATE].toDouble(DEFAULT_UPDATEFREQUENCY);
138136
cfg._dithering = obj[SETTINGS_KEY_DITHERING].toBool(false);
139137
cfg._decay = obj[SETTINGS_KEY_DECAY].toDouble(1.0);
@@ -584,7 +582,6 @@ unsigned LinearColorSmoothing::addConfig(int settlingTime_ms, double ledUpdateFr
584582
static_cast<int>(MS_PER_MICRO / ledUpdateFrequency_hz),
585583
SmoothingType::Linear,
586584
ledUpdateFrequency_hz,
587-
ledUpdateFrequency_hz,
588585
updateDelay
589586
};
590587
_cfgList.append(cfg);
@@ -605,7 +602,6 @@ unsigned LinearColorSmoothing::updateConfig(int cfgID, int settlingTime_ms, doub
605602
static_cast<int>(MS_PER_MICRO / ledUpdateFrequency_hz),
606603
SmoothingType::Linear,
607604
ledUpdateFrequency_hz,
608-
ledUpdateFrequency_hz,
609605
updateDelay
610606
};
611607
_cfgList[updatedCfgID] = cfg;
@@ -631,8 +627,7 @@ bool LinearColorSmoothing::selectConfig(int cfgID, bool force)
631627
_settlingTime = _cfgList[cfgID]._settlingTime;
632628
_outputDelay = _cfgList[cfgID]._outputDelay;
633629
_pause = _cfgList[cfgID]._pause;
634-
_outputRate = _cfgList[cfgID]._outputRate;
635-
_outputIntervalMicros = int64_t(1000000.0 / _outputRate); // 1s = 1e6 µs
630+
_outputIntervalMicros = int64_t(1000000.0 / _updateInterval); // 1s = 1e6 µs
636631
_interpolationRate = _cfgList[cfgID]._interpolationRate;
637632
_interpolationIntervalMicros = int64_t(1000000.0 / _interpolationRate);
638633
_dithering = _cfgList[cfgID]._dithering;
@@ -711,8 +706,7 @@ QString LinearColorSmoothing::getConfig(int cfgID)
711706
case SmoothingType::Decay:
712707
{
713708
const double thalf = (1.0-std::pow(1.0/2, 1.0/_decay))*_settlingTime;
714-
configText += QString (", outputRate %1Hz, interpolationRate: %2Hz, dithering: %3, decay: %4 -> halftime: %5ms")
715-
.arg(cfg._outputRate,0,'f',2)
709+
configText += QString (", interpolationRate: %1Hz, dithering: %2, decay: %3 -> halftime: %4ms")
716710
.arg(cfg._interpolationRate,0,'f',2)
717711
.arg((cfg._dithering) ? "true" : "false")
718712
.arg(cfg._decay,0,'f',2)
@@ -732,12 +726,11 @@ LinearColorSmoothing::SmoothingCfg::SmoothingCfg() :
732726
{
733727
}
734728

735-
LinearColorSmoothing::SmoothingCfg::SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type, double outputRate, double interpolationRate, unsigned outputDelay, bool dithering, double decay) :
729+
LinearColorSmoothing::SmoothingCfg::SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type, double interpolationRate, unsigned outputDelay, bool dithering, double decay) :
736730
_pause(pause),
737731
_settlingTime(settlingTime),
738732
_updateInterval(updateInterval),
739733
_type(type),
740-
_outputRate(outputRate),
741734
_interpolationRate(interpolationRate),
742735
_outputDelay(outputDelay),
743736
_dithering(dithering),

libsrc/hyperion/schema/schema-smoothing.json

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,6 @@
5050
}
5151
}
5252
},
53-
"outputRate": {
54-
"type": "number",
55-
"title": "edt_conf_smooth_outputRate_title",
56-
"minimum": 1.0,
57-
"maximum": 1000.0,
58-
"default": 1.0,
59-
"append": "edt_append_hz",
60-
"propertyOrder": 6,
61-
"options": {
62-
"dependencies": {
63-
"type": "decay"
64-
}
65-
}
66-
},
6753
"decay": {
6854
"type": "number",
6955
"title": "edt_conf_smooth_decay_title",

libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void LedDeviceAdalight::prepareHeader()
119119
qToBigEndian<quint16>(static_cast<quint16>(totalLedCount), &_ledBuffer[3]);
120120
_ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum
121121

122-
Debug( _log, "Adalight header for %d leds: %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount,
122+
Debug( _log, "Adalight header for %d leds (size: %d): %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount, _ledBuffer.size(),
123123
_ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3], _ledBuffer[4], _ledBuffer[5] );
124124
}
125125

@@ -179,6 +179,31 @@ int LedDeviceAdalight::write(const std::vector<ColorRgb> & ledValues)
179179
return rc;
180180
}
181181

182+
void LedDeviceAdalight::readFeedback()
183+
{
184+
if (_streamProtocol == Adalight::AWA)
185+
{
186+
bool continuousLines {true};
187+
while ( _rs232Port.canReadLine() )
188+
{
189+
QByteArray record = _rs232Port.readLine();
190+
if (record.startsWith("FPS:"))
191+
{
192+
if (continuousLines)
193+
{
194+
continuousLines = false;
195+
}
196+
Debug(_log, "Statistics %s", record.trimmed().constData());
197+
}
198+
else
199+
{
200+
std::cout << record.toStdString() << std::flush;
201+
continuousLines = true;
202+
}
203+
}
204+
}
205+
}
206+
182207
void LedDeviceAdalight::whiteChannelExtension(uint8_t*& writer)
183208
{
184209
if (_streamProtocol == Adalight::AWA && _white_channel_calibration)

libsrc/leddevice/dev_serial/LedDeviceAdalight.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ class LedDeviceAdalight : public ProviderRs232
3737
/// @return LedDevice constructed
3838
static LedDevice* construct(const QJsonObject &deviceConfig);
3939

40+
private slots:
41+
42+
///
43+
/// @brief Handle feedback provided by the device
44+
/// Allows to show statistics and error for the "Awa" protocol, if configured in the ESP-sketch
45+
///
46+
void readFeedback() override;
47+
4048
private:
4149

4250
///

libsrc/leddevice/dev_serial/ProviderRs232.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace {
1818
constexpr std::chrono::milliseconds WRITE_TIMEOUT{ 1000 }; // device write timeout in ms
1919
constexpr std::chrono::milliseconds OPEN_TIMEOUT{ 5000 }; // device open timeout in ms
2020
const int MAX_WRITE_TIMEOUTS = 5; // Maximum number of allowed timeouts
21-
const int NUM_POWEROFF_WRITE_BLACK = 2; // Number of write "BLACK" during powering off
21+
const int NUM_POWEROFF_WRITE_BLACK = 5; // Number of write "BLACK" during powering off
2222

2323
constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 500 };
2424

@@ -86,6 +86,8 @@ int ProviderRs232::open()
8686
// open device physically
8787
if ( tryOpen(_delayAfterConnect_ms) )
8888
{
89+
connect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::readFeedback);
90+
8991
// Everything is OK, device is ready
9092
_isDeviceReady = true;
9193
retval = 0;
@@ -106,6 +108,9 @@ int ProviderRs232::close()
106108
{
107109
Debug(_log,"Flush was successful");
108110
}
111+
112+
disconnect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::readFeedback);
113+
109114
Debug(_log,"Close UART: %s", QSTRING_CSTR(_deviceName) );
110115
_rs232Port.close();
111116
// Everything is OK -> device is closed
@@ -261,6 +266,23 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data)
261266
return rc;
262267
}
263268

269+
void ProviderRs232::readFeedback()
270+
{
271+
QByteArray readData = _rs232Port.readAll();
272+
if (!readData.isEmpty())
273+
{
274+
//Output as received
275+
std::cout << readData.toStdString();
276+
277+
//Output as Hex
278+
//#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
279+
// std::cout << readData.toHex(':').toStdString();
280+
//#else
281+
// std::cout << readData.toHex().toStdString();
282+
//#endif
283+
}
284+
}
285+
264286
QString ProviderRs232::discoverFirst()
265287
{
266288
// take first available USB serial port - currently no probing!

0 commit comments

Comments
 (0)