From a2db590d2a1547882c0aba3ee3cc2e0965cc1823 Mon Sep 17 00:00:00 2001 From: LordGrey <48840279+Lord-Grey@users.noreply.github.com> Date: Sun, 27 Nov 2022 15:47:54 +0100 Subject: [PATCH] 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 --- assets/webconfig/i18n/en.json | 2 - assets/webconfig/js/content_remote.js | 115 ++++++++++-------- config/hyperion.config.json.default | 1 - include/hyperion/LinearColorSmoothing.h | 8 +- libsrc/hyperion/LinearColorSmoothing.cpp | 13 +- libsrc/hyperion/schema/schema-smoothing.json | 14 --- .../dev_serial/LedDeviceAdalight.cpp | 27 +++- .../leddevice/dev_serial/LedDeviceAdalight.h | 8 ++ libsrc/leddevice/dev_serial/ProviderRs232.cpp | 24 +++- libsrc/leddevice/dev_serial/ProviderRs232.h | 5 + 10 files changed, 130 insertions(+), 87 deletions(-) diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index aa3251d4..1ae5e0e4 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -443,8 +443,6 @@ "edt_conf_smooth_heading_title": "Smoothing", "edt_conf_smooth_interpolationRate_expl": "Speed of the calculation of smooth intermediate frames.", "edt_conf_smooth_interpolationRate_title": "Interpolation Rate", - "edt_conf_smooth_outputRate_expl": "The output speed to your LED controller.", - "edt_conf_smooth_outputRate_title": "Output Rate", "edt_conf_smooth_time_ms_expl": "How long should the smoothing gather pictures?", "edt_conf_smooth_time_ms_title": "Time", "edt_conf_smooth_type_expl": "Type of smoothing.", diff --git a/assets/webconfig/js/content_remote.js b/assets/webconfig/js/content_remote.js index d0b21285..d0c1d9c2 100644 --- a/assets/webconfig/js/content_remote.js +++ b/assets/webconfig/js/content_remote.js @@ -19,7 +19,6 @@ $(document).ready(function () { $('.ssthead').html(createTableRow([$.i18n('remote_input_origin'), $.i18n('remote_input_owner'), $.i18n('remote_input_priority'), $.i18n('remote_input_status')], true, true)); createTable('crthead', 'crtbody', 'adjust_content', true); - //create introduction if (window.showOptHelp) { createHint("intro", $.i18n('remote_color_intro', $.i18n('remote_losthint')), "color_intro"); @@ -30,56 +29,6 @@ $(document).ready(function () { createHint("intro", $.i18n('remote_videoMode_intro', $.i18n('remote_losthint')), "videomode_intro"); } - //color adjustment - var sColor = sortProperties(window.serverSchema.properties.color.properties.channelAdjustment.items.properties); - var values = window.serverInfo.adjustment[0]; - - for (var key in sColor) { - if (sColor[key].key != "id" && sColor[key].key != "leds") { - var title = ''; - var property; - var value = values[sColor[key].key]; - - if (sColor[key].type == "array") { - property = '
'; - $('.crtbody').append(createTableRow([title, property], false, true)); - createCP('cr_' + sColor[key].key, value, function (rgb, hex, e) { - requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), '[' + rgb.r + ',' + rgb.g + ',' + rgb.b + ']'); - }); - } - else if (sColor[key].type == "boolean") { - property = '
'; - $('.crtbody').append(createTableRow([title, property], false, true)); - - $('#cr_' + sColor[key].key).off().on('change', function (e) { - requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.checked); - }); - } - else { - if (sColor[key].key == "brightness" || - sColor[key].key == "brightnessCompensation" || - sColor[key].key == "backlightThreshold" || - sColor[key].key == "saturationGain" || - sColor[key].key == "brightnessGain") { - - property = ''; - if (sColor[key].append === "edt_append_percent") { - property = '
' + property + '' + $.i18n("edt_append_percent") + '
'; - } - } - else { - property = ''; - } - - $('.crtbody').append(createTableRow([title, property], false, true)); - $('#cr_' + sColor[key].key).off().on('change', function (e) { - valValue(this.id, this.value, this.min, this.max); - requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.value); - }); - } - } - } - function sendEffect() { var efx = $("#effect_select").val(); if (efx != "__none__") { @@ -94,6 +43,59 @@ $(document).ready(function () { requestSetColor(rgb.r, rgb.g, rgb.b, duration); } + function updateChannelAdjustments() { + + $('.crtbody').html(""); + var sColor = sortProperties(window.serverSchema.properties.color.properties.channelAdjustment.items.properties); + var values = window.serverInfo.adjustment[0]; + + for (var key in sColor) { + if (sColor[key].key != "id" && sColor[key].key != "leds") { + var title = ''; + var property; + var value = values[sColor[key].key]; + + if (sColor[key].type == "array") { + property = '
'; + $('.crtbody').append(createTableRow([title, property], false, true)); + createCP('cr_' + sColor[key].key, value, function (rgb, hex, e) { + requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), '[' + rgb.r + ',' + rgb.g + ',' + rgb.b + ']'); + }); + } + else if (sColor[key].type == "boolean") { + property = '
'; + $('.crtbody').append(createTableRow([title, property], false, true)); + + $('#cr_' + sColor[key].key).off().on('change', function (e) { + requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.checked); + }); + } + else { + if (sColor[key].key == "brightness" || + sColor[key].key == "brightnessCompensation" || + sColor[key].key == "backlightThreshold" || + sColor[key].key == "saturationGain" || + sColor[key].key == "brightnessGain") { + + property = ''; + if (sColor[key].append === "edt_append_percent") { + property = '
' + property + '' + $.i18n("edt_append_percent") + '
'; + } + } + else { + property = ''; + } + + $('.crtbody').append(createTableRow([title, property], false, true)); + $('#cr_' + sColor[key].key).off().on('change', function (e) { + valValue(this.id, this.value, this.min, this.max); + requestAdjustment(e.target.id.substr(e.target.id.indexOf("_") + 1), e.currentTarget.value); + }); + } + } + } + } + function updateInputSelect() { $('.sstbody').html(""); var prios = window.serverInfo.priorities; @@ -389,6 +391,7 @@ $(document).ready(function () { updateInputSelect(); updateLedMapping(); updateVideoMode(); + updateChannelAdjustments(); if (EFFECTENGINE_ENABLED) { updateEffectlist(); } else { @@ -421,6 +424,16 @@ $(document).ready(function () { updateEffectlist(); }); + $(window.hyperion).on("cmd-settings-update", function (event) { + if (event.response.data.color) { + window.serverInfo.imageToLedMappingType = event.response.data.color.imageToLedMappingType; + updateLedMapping(); + + window.serverInfo.adjustment = event.response.data.color.channelAdjustment; + updateChannelAdjustments(); + } + }); + removeOverlay(); }); diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default index c54cb28f..a52f64ba 100644 --- a/config/hyperion.config.json.default +++ b/config/hyperion.config.json.default @@ -60,7 +60,6 @@ "time_ms" : 200, "updateFrequency" : 25.0000, "interpolationRate" : 25.0000, - "outputRate" : 25.0000, "decay" : 1, "dithering" : false, "updateDelay" : 0 diff --git a/include/hyperion/LinearColorSmoothing.h b/include/hyperion/LinearColorSmoothing.h index c80188b0..5636c278 100644 --- a/include/hyperion/LinearColorSmoothing.h +++ b/include/hyperion/LinearColorSmoothing.h @@ -230,9 +230,6 @@ private: /// Flag for pausing bool _pause; - /// The rate at which color frames should be written to LED device. - double _outputRate; - /// The interval time in microseconds for writing of LED Frames. int64_t _outputIntervalMicros; @@ -268,9 +265,6 @@ private: /// The type of smoothing to perform SmoothingType _type; - /// The rate at which color frames should be written to LED device. - double _outputRate; - /// The rate at which interpolation of LED frames should be performed. double _interpolationRate; @@ -284,7 +278,7 @@ private: double _decay; SmoothingCfg(); - 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); + SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type = SmoothingType::Linear, double interpolationRate = 0, unsigned outputDelay = 0, bool dithering = false, double decay = 1); static QString EnumToString(SmoothingType type); }; diff --git a/libsrc/hyperion/LinearColorSmoothing.cpp b/libsrc/hyperion/LinearColorSmoothing.cpp index d5850134..c91309b0 100644 --- a/libsrc/hyperion/LinearColorSmoothing.cpp +++ b/libsrc/hyperion/LinearColorSmoothing.cpp @@ -47,7 +47,6 @@ const char* SETTINGS_KEY_OUTPUT_DELAY = "updateDelay"; const char* SETTINGS_KEY_DECAY = "decay"; const char* SETTINGS_KEY_INTERPOLATION_RATE = "interpolationRate"; -const char* SETTINGS_KEY_OUTPUT_RATE = "outputRate"; const char* SETTINGS_KEY_DITHERING = "dithering"; const int64_t DEFAULT_SETTLINGTIME = 200; // in ms @@ -133,7 +132,6 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson cfg._pause = false; cfg._outputDelay = static_cast(obj[SETTINGS_KEY_OUTPUT_DELAY].toInt(DEFAULT_OUTPUTDEPLAY)); - cfg._outputRate = obj[SETTINGS_KEY_OUTPUT_RATE].toDouble(DEFAULT_UPDATEFREQUENCY); cfg._interpolationRate = obj[SETTINGS_KEY_INTERPOLATION_RATE].toDouble(DEFAULT_UPDATEFREQUENCY); cfg._dithering = obj[SETTINGS_KEY_DITHERING].toBool(false); cfg._decay = obj[SETTINGS_KEY_DECAY].toDouble(1.0); @@ -584,7 +582,6 @@ unsigned LinearColorSmoothing::addConfig(int settlingTime_ms, double ledUpdateFr static_cast(MS_PER_MICRO / ledUpdateFrequency_hz), SmoothingType::Linear, ledUpdateFrequency_hz, - ledUpdateFrequency_hz, updateDelay }; _cfgList.append(cfg); @@ -605,7 +602,6 @@ unsigned LinearColorSmoothing::updateConfig(int cfgID, int settlingTime_ms, doub static_cast(MS_PER_MICRO / ledUpdateFrequency_hz), SmoothingType::Linear, ledUpdateFrequency_hz, - ledUpdateFrequency_hz, updateDelay }; _cfgList[updatedCfgID] = cfg; @@ -631,8 +627,7 @@ bool LinearColorSmoothing::selectConfig(int cfgID, bool force) _settlingTime = _cfgList[cfgID]._settlingTime; _outputDelay = _cfgList[cfgID]._outputDelay; _pause = _cfgList[cfgID]._pause; - _outputRate = _cfgList[cfgID]._outputRate; - _outputIntervalMicros = int64_t(1000000.0 / _outputRate); // 1s = 1e6 µs + _outputIntervalMicros = int64_t(1000000.0 / _updateInterval); // 1s = 1e6 µs _interpolationRate = _cfgList[cfgID]._interpolationRate; _interpolationIntervalMicros = int64_t(1000000.0 / _interpolationRate); _dithering = _cfgList[cfgID]._dithering; @@ -711,8 +706,7 @@ QString LinearColorSmoothing::getConfig(int cfgID) case SmoothingType::Decay: { const double thalf = (1.0-std::pow(1.0/2, 1.0/_decay))*_settlingTime; - configText += QString (", outputRate %1Hz, interpolationRate: %2Hz, dithering: %3, decay: %4 -> halftime: %5ms") - .arg(cfg._outputRate,0,'f',2) + configText += QString (", interpolationRate: %1Hz, dithering: %2, decay: %3 -> halftime: %4ms") .arg(cfg._interpolationRate,0,'f',2) .arg((cfg._dithering) ? "true" : "false") .arg(cfg._decay,0,'f',2) @@ -732,12 +726,11 @@ LinearColorSmoothing::SmoothingCfg::SmoothingCfg() : { } -LinearColorSmoothing::SmoothingCfg::SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type, double outputRate, double interpolationRate, unsigned outputDelay, bool dithering, double decay) : +LinearColorSmoothing::SmoothingCfg::SmoothingCfg(bool pause, int64_t settlingTime, int updateInterval, SmoothingType type, double interpolationRate, unsigned outputDelay, bool dithering, double decay) : _pause(pause), _settlingTime(settlingTime), _updateInterval(updateInterval), _type(type), - _outputRate(outputRate), _interpolationRate(interpolationRate), _outputDelay(outputDelay), _dithering(dithering), diff --git a/libsrc/hyperion/schema/schema-smoothing.json b/libsrc/hyperion/schema/schema-smoothing.json index 3f51c214..b5aea7b2 100644 --- a/libsrc/hyperion/schema/schema-smoothing.json +++ b/libsrc/hyperion/schema/schema-smoothing.json @@ -50,20 +50,6 @@ } } }, - "outputRate": { - "type": "number", - "title": "edt_conf_smooth_outputRate_title", - "minimum": 1.0, - "maximum": 1000.0, - "default": 1.0, - "append": "edt_append_hz", - "propertyOrder": 6, - "options": { - "dependencies": { - "type": "decay" - } - } - }, "decay": { "type": "number", "title": "edt_conf_smooth_decay_title", diff --git a/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp b/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp index 109e76ff..1fdc11b3 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp +++ b/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp @@ -119,7 +119,7 @@ void LedDeviceAdalight::prepareHeader() qToBigEndian(static_cast(totalLedCount), &_ledBuffer[3]); _ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum - Debug( _log, "Adalight header for %d leds: %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount, + Debug( _log, "Adalight header for %d leds (size: %d): %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount, _ledBuffer.size(), _ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3], _ledBuffer[4], _ledBuffer[5] ); } @@ -179,6 +179,31 @@ int LedDeviceAdalight::write(const std::vector & ledValues) return rc; } +void LedDeviceAdalight::readFeedback() +{ + if (_streamProtocol == Adalight::AWA) + { + bool continuousLines {true}; + while ( _rs232Port.canReadLine() ) + { + QByteArray record = _rs232Port.readLine(); + if (record.startsWith("FPS:")) + { + if (continuousLines) + { + continuousLines = false; + } + Debug(_log, "Statistics %s", record.trimmed().constData()); + } + else + { + std::cout << record.toStdString() << std::flush; + continuousLines = true; + } + } + } +} + void LedDeviceAdalight::whiteChannelExtension(uint8_t*& writer) { if (_streamProtocol == Adalight::AWA && _white_channel_calibration) diff --git a/libsrc/leddevice/dev_serial/LedDeviceAdalight.h b/libsrc/leddevice/dev_serial/LedDeviceAdalight.h index 2507bad8..56065127 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAdalight.h +++ b/libsrc/leddevice/dev_serial/LedDeviceAdalight.h @@ -37,6 +37,14 @@ public: /// @return LedDevice constructed static LedDevice* construct(const QJsonObject &deviceConfig); +private slots: + + /// + /// @brief Handle feedback provided by the device + /// Allows to show statistics and error for the "Awa" protocol, if configured in the ESP-sketch + /// + void readFeedback() override; + private: /// diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.cpp b/libsrc/leddevice/dev_serial/ProviderRs232.cpp index f1298d2e..bd4349db 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.cpp +++ b/libsrc/leddevice/dev_serial/ProviderRs232.cpp @@ -18,7 +18,7 @@ namespace { constexpr std::chrono::milliseconds WRITE_TIMEOUT{ 1000 }; // device write timeout in ms constexpr std::chrono::milliseconds OPEN_TIMEOUT{ 5000 }; // device open timeout in ms const int MAX_WRITE_TIMEOUTS = 5; // Maximum number of allowed timeouts - const int NUM_POWEROFF_WRITE_BLACK = 2; // Number of write "BLACK" during powering off + const int NUM_POWEROFF_WRITE_BLACK = 5; // Number of write "BLACK" during powering off constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 500 }; @@ -86,6 +86,8 @@ int ProviderRs232::open() // open device physically if ( tryOpen(_delayAfterConnect_ms) ) { + connect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::readFeedback); + // Everything is OK, device is ready _isDeviceReady = true; retval = 0; @@ -106,6 +108,9 @@ int ProviderRs232::close() { Debug(_log,"Flush was successful"); } + + disconnect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::readFeedback); + Debug(_log,"Close UART: %s", QSTRING_CSTR(_deviceName) ); _rs232Port.close(); // Everything is OK -> device is closed @@ -261,6 +266,23 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data) return rc; } +void ProviderRs232::readFeedback() +{ + QByteArray readData = _rs232Port.readAll(); + if (!readData.isEmpty()) + { + //Output as received + std::cout << readData.toStdString(); + + //Output as Hex +//#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) +// std::cout << readData.toHex(':').toStdString(); +//#else +// std::cout << readData.toHex().toStdString(); +//#endif + } +} + QString ProviderRs232::discoverFirst() { // take first available USB serial port - currently no probing! diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.h b/libsrc/leddevice/dev_serial/ProviderRs232.h index 2cb94398..36348b55 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.h +++ b/libsrc/leddevice/dev_serial/ProviderRs232.h @@ -123,6 +123,11 @@ protected slots: /// void setInError( const QString& errorMsg) override; + /// + /// @brief Handle any feedback provided by the device + /// + virtual void readFeedback(); + private: ///