diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index bb8efdd3..ca7144c3 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -542,6 +542,8 @@ "edt_dev_general_heading_title": "General Settings", "edt_dev_general_name_title": "Configuration name", "edt_dev_general_rewriteTime_title": "Refresh time", + "edt_dev_spec_ada_mode_title": "Adalight - Standard", + "edt_dev_spec_awa_mode_title": "HyperSerial - High speed", "edt_dev_spec_FCledToOn_title": "Fadecandy LED set to on", "edt_dev_spec_FCmanualControl_title": "Manual control of fadecandy LED", "edt_dev_spec_FCsetConfig_title": "Set fadecandy configuration", @@ -612,6 +614,11 @@ "edt_dev_spec_razer_device_title": "Razer Chroma Device", "edt_dev_spec_restoreOriginalState_title": "Restore lights' state", "edt_dev_spec_restoreOriginalState_title_info": "Restore the device's original state when device is disabled", + "edt_dev_spec_rgbw_calibration_enable" : "White channel calibration (RGBW only)", + "edt_dev_spec_rgbw_calibration_limit" : "White channel limit", + "edt_dev_spec_rgbw_calibration_red" : "Red/White channel aspect", + "edt_dev_spec_rgbw_calibration_green" : "Green/White channel aspect", + "edt_dev_spec_rgbw_calibration_blue" : "Blue/White channel aspect", "edt_dev_spec_serial_title": "Serial number", "edt_dev_spec_spipath_title": "SPI Device", "edt_dev_spec_sslHSTimeoutMax_title": "Streamer handshake timeout maximum", diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js index 8fc3359d..26ef9529 100755 --- a/assets/webconfig/js/content_leds.js +++ b/assets/webconfig/js/content_leds.js @@ -62,7 +62,7 @@ function createLedPreview(leds) { $('#image_preview').css({ "width": canvas_width, "height": canvas_height }); var leds_html = ""; - for (var idx = leds.length-1; idx >= 0; idx--) { + for (var idx = leds.length - 1; idx >= 0; idx--) { var led = leds[idx]; var led_id = 'ledc_' + [idx]; var bgcolor = "background-color:hsla(" + (idx * 360 / leds.length) + ",100%,50%,0.75);"; @@ -112,7 +112,7 @@ function createLedPreview(leds) { width: parseInt(maxWidth + $('#top_left_point').outerWidth()), height: parseInt(maxHeight + $('#top_left_point').outerHeight()), }, - onMove: function(newPosition) { + onMove: function (newPosition) { var keystone_correction_area_offsets = $('#keystone_correction_area').offset(); var left = newPosition.left - keystone_correction_area_offsets.left + size / 2; var top = newPosition.top - keystone_correction_area_offsets.top + size / 2; @@ -137,7 +137,7 @@ function createLedPreview(leds) { width: parseInt(maxWidth + $('#top_right_point').outerWidth()), height: parseInt(maxHeight + $('#top_right_point').outerHeight()) }, - onMove: function(newPosition) { + onMove: function (newPosition) { var keystone_correction_area_offsets = $('#keystone_correction_area').offset(); var left = newPosition.left - keystone_correction_area_offsets.left + $('#top_right_point').outerWidth() - size / 2; var top = newPosition.top - keystone_correction_area_offsets.top + size / 2; @@ -162,7 +162,7 @@ function createLedPreview(leds) { width: parseInt(maxWidth + $('#bottom_right_point').outerWidth()), height: parseInt(maxHeight + $('#bottom_right_point').outerHeight()) }, - onMove: function(newPosition) { + onMove: function (newPosition) { var keystone_correction_area_offsets = $('#keystone_correction_area').offset(); var left = newPosition.left - keystone_correction_area_offsets.left + $('#bottom_right_point').outerWidth() - size / 2; var top = newPosition.top - keystone_correction_area_offsets.top + $('#bottom_right_point').outerHeight() - size / 2; @@ -187,7 +187,7 @@ function createLedPreview(leds) { width: parseInt(maxWidth + $('#bottom_left_point').outerWidth()), height: parseInt(maxHeight + $('#bottom_left_point').outerHeight()) }, - onMove: function(newPosition) { + onMove: function (newPosition) { var keystone_correction_area_offsets = $('#keystone_correction_area').offset(); var left = newPosition.left - keystone_correction_area_offsets.left + size / 2; var top = newPosition.top - keystone_correction_area_offsets.top + $('#bottom_left_point').outerHeight() - size / 2; @@ -225,12 +225,12 @@ function createLedPreview(leds) { var lineColor = $(".keystone_correction_corners").css("border-color"); // Add lines - topLeft2topRight = new LeaderLine(LeaderLine.pointAnchor(top_left_point, {x: '50%', y: '50%'}), LeaderLine.pointAnchor(top_right_point, {x: '50%', y: '50%'}), {path: 'straight', size: 1, color: lineColor, endPlug: 'behind'}); - topRight2bottomRight = new LeaderLine(LeaderLine.pointAnchor(top_right_point, {x: '50%', y: '50%'}), LeaderLine.pointAnchor(bottom_right_point, {x: '50%', y: '50%'}), {path: 'straight', size: 1, color: lineColor, endPlug: 'behind'}); - bottomRight2bottomLeft = new LeaderLine(LeaderLine.pointAnchor(bottom_right_point, {x: '50%', y: '50%'}), LeaderLine.pointAnchor(bottom_left_point, {x: '50%', y: '50%'}), {path: 'straight', size: 1, color: lineColor, endPlug: 'behind'}); - bottomLeft2topLeft = new LeaderLine(LeaderLine.pointAnchor(bottom_left_point, {x: '50%', y: '50%'}), LeaderLine.pointAnchor(top_left_point, {x: '50%', y: '50%'}), {path: 'straight', size: 1, color: lineColor, endPlug: 'behind'}); + topLeft2topRight = new LeaderLine(LeaderLine.pointAnchor(top_left_point, { x: '50%', y: '50%' }), LeaderLine.pointAnchor(top_right_point, { x: '50%', y: '50%' }), { path: 'straight', size: 1, color: lineColor, endPlug: 'behind' }); + topRight2bottomRight = new LeaderLine(LeaderLine.pointAnchor(top_right_point, { x: '50%', y: '50%' }), LeaderLine.pointAnchor(bottom_right_point, { x: '50%', y: '50%' }), { path: 'straight', size: 1, color: lineColor, endPlug: 'behind' }); + bottomRight2bottomLeft = new LeaderLine(LeaderLine.pointAnchor(bottom_right_point, { x: '50%', y: '50%' }), LeaderLine.pointAnchor(bottom_left_point, { x: '50%', y: '50%' }), { path: 'straight', size: 1, color: lineColor, endPlug: 'behind' }); + bottomLeft2topLeft = new LeaderLine(LeaderLine.pointAnchor(bottom_left_point, { x: '50%', y: '50%' }), LeaderLine.pointAnchor(top_left_point, { x: '50%', y: '50%' }), { path: 'straight', size: 1, color: lineColor, endPlug: 'behind' }); } else { - $('#keystone_correction_area').html("").css({ "width" : 0, "height" : 0 }); + $('#keystone_correction_area').html("").css({ "width": 0, "height": 0 }); // Remove existing lines if (topLeft2topRight != null) { @@ -256,7 +256,7 @@ function createLedPreview(leds) { // Change on window resize. Is this correct? $(window).off("resize.createLedPreview"); - $(window).on("resize.createLedPreview",(function() { + $(window).on("resize.createLedPreview", (function () { createLedPreview(leds); })); } @@ -776,16 +776,16 @@ $(document).ready(function () { var maxLEDs = ledstop + ledsbottom + ledsleft + ledsright; var gpos = parseInt($("#ip_cl_gpos").val()); - $("#ip_cl_gpos").attr({'max':maxLEDs-1}); + $("#ip_cl_gpos").attr({ 'max': maxLEDs - 1 }); - var max = maxLEDs-gpos; + var max = maxLEDs - gpos; if (gpos == 0) { --max; } - $("#ip_cl_glength").attr({'max':max}); + $("#ip_cl_glength").attr({ 'max': max }); - var glength = parseInt($("#ip_cl_glength").val()); - if (glength+gpos >= maxLEDs) { + var glength = parseInt($("#ip_cl_glength").val()); + if (glength + gpos >= maxLEDs) { $("#ip_cl_glength").val($("#ip_cl_glength").attr('max')); } break; @@ -804,20 +804,20 @@ $(document).ready(function () { configPanel = "classic"; $("#leds_prev_toggle_keystone_correction_area").show(); createClassicLeds(); -}); + }); $('#collapse2').on('shown.bs.collapse', function () { configPanel = "matrix"; $("#leds_prev_toggle_keystone_correction_area").hide(); createMatrixLeds(); -}); + }); $('#collapse5').on('shown.bs.collapse', function () { configPanel = "text"; $("#leds_prev_toggle_keystone_correction_area").hide(); createLedPreview(finalLedArray); aceEdt.set(finalLedArray); -}); + }); // Initialise from config and apply blacklist rules nonBlacklistLedArray = window.serverConfig.leds; @@ -891,20 +891,20 @@ $(document).ready(function () { }); // toggle right icon on "Advanced Settings" click - $('#advanced_settings').on('click', function(e) { + $('#advanced_settings').on('click', function (e) { $('#advanced_settings_right_icon').toggleClass('fa-angle-down fa-angle-up'); }); // toggle fullscreen button in led preview - $(".fullscreen-btn").mousedown(function(e) { + $(".fullscreen-btn").mousedown(function (e) { e.preventDefault(); }); - $(".fullscreen-btn").click(function(e) { + $(".fullscreen-btn").click(function (e) { e.preventDefault(); - $(this).children('i') - .toggleClass('fa-expand') - .toggleClass('fa-compress'); + $(this).children('i') + .toggleClass('fa-expand') + .toggleClass('fa-compress'); $('#layout_type').toggle(); $('#layout_preview').toggleClass('col-lg-6 col-lg-12'); window.dispatchEvent(new Event('resize')); @@ -1084,7 +1084,7 @@ $(document).ready(function () { case "wled": case "nanoleaf": showAllDeviceInputOptions("hostList", false); - case "apa102": + case "apa102": case "apa104": case "ws2801": case "lpd6803": @@ -1187,6 +1187,18 @@ $(document).ready(function () { } break; + case "adalight": + case "atmo": + case "karate": + case "dmx": + case "sedu": + case "tpm2": + var rate = conf_editor.getEditor("root.specificOptions.rate").getValue(); + if (rate > 0) { + canSave = true; + } + break; + case "philipshue": var host = conf_editor.getEditor("root.specificOptions.host").getValue(); var username = conf_editor.getEditor("root.specificOptions.username").getValue(); @@ -1264,7 +1276,7 @@ $(document).ready(function () { var val = hostList.getValue(); var host = conf_editor.getEditor("root.specificOptions.host"); var showOptions = true; - + switch (val) { case 'CUSTOM': case '': @@ -1381,6 +1393,15 @@ $(document).ready(function () { default: } + if ($.inArray(ledType, devSerial) != -1) { + var rateList = conf_editor.getEditor("root.specificOptions.rateList").getValue(); + var showRate = false; + if (rateList == "CUSTOM") { + showRate = true; + } + showInputOptionForItem(conf_editor, 'specificOptions', 'rate', showRate); + } + if (!conf_editor.validate().length) { if (canIdentify) { $("#btn_test_controller").show(); @@ -1409,6 +1430,61 @@ $(document).ready(function () { } }); + conf_editor.watch('root.specificOptions.streamProtocol', () => { + var streamProtocol = conf_editor.getEditor("root.specificOptions.streamProtocol").getValue(); + + switch (ledType) { + case "adalight": + var rate; + if (streamProtocol === window.serverConfig.device.streamProtocol) { + rate = window.serverConfig.device.rate.toString(); + } else { + // Set default rates per protocol type + switch (streamProtocol) { + case "2": + rate = "2000000"; + break; + case "0": + case "1": + default: + rate = "115200"; + } + } + conf_editor.getEditor("root.specificOptions.rateList").setValue(rate); + break; + default: + } + }); + + conf_editor.watch('root.specificOptions.rateList', () => { + var specOptPath = 'root.specificOptions.'; + var rateList = conf_editor.getEditor("root.specificOptions.rateList"); + if (rateList) { + var val = rateList.getValue(); + var rate = conf_editor.getEditor("root.specificOptions.rate"); + + switch (val) { + case 'CUSTOM': + case '': + rate.enable(); + //Populate existing rate for current custom config + if (ledType === window.serverConfig.device.type) { + rate.setValue(window.serverConfig.device.rate); + } else { + rate.setValue(""); + } + break; + default: + rate.disable(); + rate.setValue(val); + //Trigger getProperties via rate value + conf_editor.notifyWatchers(specOptPath + "rate"); + break; + } + } + showInputOptionForItem(conf_editor, 'specificOptions', 'rate', rate.isEnabled()); + }); + conf_editor.watch('root.specificOptions.token', () => { var token = conf_editor.getEditor("root.specificOptions.token").getValue(); @@ -1852,8 +1928,13 @@ var updateSelectList = function (ledType, discoveryInfo) { // Select configured device var configuredDeviceType = window.serverConfig.device.type; var configuredOutput = window.serverConfig.device.output; - if (ledType === configuredDeviceType && $.inArray(configuredOutput, enumVals) != -1) { - enumDefaultVal = configuredOutput; + if (ledType === configuredDeviceType) { + if ($.inArray(configuredOutput, enumVals) != -1) { + enumDefaultVal = configuredOutput; + } else { + enumVals.push(window.serverConfig.device.output); + enumDefaultVal = configuredOutput; + } } else { addSelect = true; @@ -2108,3 +2189,4 @@ function disableAutoResolvedGeneralOptions() { conf_editor.getEditor("root.generalOptions.hardwareLedCount").disable(); conf_editor.getEditor("root.generalOptions.colorOrder").disable(); } + diff --git a/libsrc/hyperion/SettingsManager.cpp b/libsrc/hyperion/SettingsManager.cpp index b045100d..e8e444a9 100644 --- a/libsrc/hyperion/SettingsManager.cpp +++ b/libsrc/hyperion/SettingsManager.cpp @@ -699,6 +699,59 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config) } } } + + //Migration steps for versions <= 2.0.13 + targetVersion.setVersion("2.0.13"); + if (_previousVersion <= targetVersion) + { + Info(_log, "Instance [%u]: Migrate from version [%s] to version [%s] or later", _instance, _previousVersion.getVersion().c_str(), targetVersion.getVersion().c_str()); + + + // Have Hostname/IP-address separate from port for LED-Devices + if (config.contains("device")) + { + QJsonObject newDeviceConfig = config["device"].toObject(); + + if (newDeviceConfig.contains("type")) + { + QString type = newDeviceConfig["type"].toString(); + + const QStringList serialDevices {"adalight", "dmx", "atmo", "sedu", "tpm2", "karate"}; + if ( serialDevices.contains(type )) + { + if (!newDeviceConfig.contains("rateList")) + { + newDeviceConfig["rateList"] = "CUSTOM"; + migrated = true; + } + } + + if (type == "adalight") + { + if (newDeviceConfig.contains("lightberry_apa102_mode")) + { + bool lightberry_apa102_mode = newDeviceConfig["lightberry_apa102_mode"].toBool(); + if (lightberry_apa102_mode) + { + newDeviceConfig["streamProtocol"] = "1"; + } + else + { + newDeviceConfig["streamProtocol"] = "0"; + } + newDeviceConfig.remove("lightberry_apa102_mode"); + migrated = true; + } + } + } + + if (migrated) + { + config["device"] = newDeviceConfig; + Debug(_log, "LED-Device records migrated"); + } + } + } } } return migrated; diff --git a/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp b/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp index 0e74e13a..109e76ff 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp +++ b/libsrc/leddevice/dev_serial/LedDeviceAdalight.cpp @@ -2,12 +2,23 @@ #include -#include +// Constants +namespace { + +// Configuration settings +const char CONFIG_STREAM_PROTOCOL[] = "streamProtocol"; + +const char CONFIG_WHITE_CHANNEL_CALLIBRATION[] = "white_channel_calibration"; +const char CONFIG_WHITE_CHANNEL_LIMIT[] = "white_channel_limit"; +const char CONFIG_WHITE_CHANNEL_RED[] = "white_channel_red"; +const char CONFIG_WHITE_CHANNEL_GREEN[] = "white_channel_green"; +const char CONFIG_WHITE_CHANNEL_BLUE[] = "white_channel_blue"; +constexpr int HEADER_SIZE {6}; + +} //End of constants LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig) : ProviderRs232(deviceConfig) - , _headerSize(6) - , _ligthBerryAPA102Mode(false) { } @@ -23,66 +34,158 @@ bool LedDeviceAdalight::init(const QJsonObject &deviceConfig) // Initialise sub-class if ( ProviderRs232::init(deviceConfig) ) { + _streamProtocol = static_cast(deviceConfig[CONFIG_STREAM_PROTOCOL].toString().toInt()); + switch (_streamProtocol) { - _ligthBerryAPA102Mode = deviceConfig["lightberry_apa102_mode"].toBool(false); - - // create ledBuffer - unsigned int totalLedCount = _ledCount; - - if (_ligthBerryAPA102Mode) + case Adalight::AWA: { - const unsigned int startFrameSize = 4; - const unsigned int bytesPerRGBLed = 4; - const unsigned int endFrameSize = qMax(((_ledCount + 15) / 16), bytesPerRGBLed); - _ledBuffer.resize(_headerSize + (_ledCount * bytesPerRGBLed) + startFrameSize + endFrameSize, 0x00); + Debug( _log, "Adalight driver uses Hyperserial protocol"); + _white_channel_calibration = deviceConfig[CONFIG_WHITE_CHANNEL_CALLIBRATION].toBool(false); + double _white_channel_limit_percent = deviceConfig[CONFIG_WHITE_CHANNEL_LIMIT].toDouble(1); + _white_channel_limit = static_cast(qMin(qRound(_white_channel_limit_percent * 255.0 / 100.0), 255)); + _white_channel_red = static_cast(qMin(deviceConfig[CONFIG_WHITE_CHANNEL_RED].toInt(255), 255)); + _white_channel_green = static_cast(qMin(deviceConfig[CONFIG_WHITE_CHANNEL_GREEN].toInt(255), 255)); + _white_channel_blue = static_cast(qMin(deviceConfig[CONFIG_WHITE_CHANNEL_BLUE].toInt(255), 255)); - // init constant data values - for (signed iLed=1; iLed<= static_cast( _ledCount); iLed++) - { - _ledBuffer[iLed*4+_headerSize] = 0xFF; - } - Debug( _log, "Adalight driver with activated LightBerry APA102 mode"); + DebugIf(_white_channel_calibration, _log, "White channel limit: %i (%.2f%), red: %i, green: %i, blue: %i", _white_channel_limit, _white_channel_limit_percent, _white_channel_red, _white_channel_green, _white_channel_blue); } - else - { - totalLedCount -= 1; - _ledBuffer.resize(_headerSize + _ledRGBCount, 0x00); + break; + + case Adalight::LBAPA: + Debug( _log, "Adalight driver uses LightBerry APA102 protocol"); + break; + + case Adalight::ADA: + Debug( _log, "Adalight driver uses standard Adalight protocol"); + break; + default: + Error( _log, "Adalight driver - unsupported protocol"); + return false; } - _ledBuffer[0] = 'A'; - _ledBuffer[1] = 'd'; - _ledBuffer[2] = 'a'; - 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, - _ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3], _ledBuffer[4], _ledBuffer[5] ); - + prepareHeader(); isInitOK = true; } return isInitOK; } +void LedDeviceAdalight::prepareHeader() +{ + // create ledBuffer + uint totalLedCount = _ledCount; + _bufferLength = static_cast(HEADER_SIZE + _ledRGBCount); + + switch (_streamProtocol) { + case Adalight::LBAPA: + { + const unsigned int startFrameSize = 4; + const unsigned int bytesPerRGBLed = 4; + const unsigned int endFrameSize = qMax(((_ledCount + 15) / 16), bytesPerRGBLed); + _bufferLength = HEADER_SIZE + (_ledCount * bytesPerRGBLed) + startFrameSize + endFrameSize; + + _ledBuffer.resize(static_cast(_bufferLength), 0x00); + + // init constant data values + for (uint iLed=1; iLed <= _ledCount; iLed++) + { + _ledBuffer[iLed*4+HEADER_SIZE] = 0xFF; + } + } + break; + + case Adalight::AWA: + _bufferLength += 7; + [[clang::fallthrough]]; + case Adalight::ADA: + [[clang::fallthrough]]; + default: + totalLedCount -= 1; + _ledBuffer.resize(static_cast(_bufferLength), 0x00); + break; + } + + _ledBuffer[0] = 'A'; + if (_streamProtocol == Adalight::AWA ) + { + _ledBuffer[1] = 'w'; + _ledBuffer[2] = _white_channel_calibration ? 'A' : 'a'; + } + else + { + _ledBuffer[1] = 'd'; + _ledBuffer[2] = 'a'; + } + + 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, + _ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3], _ledBuffer[4], _ledBuffer[5] ); +} + + int LedDeviceAdalight::write(const std::vector & ledValues) { - if(_ligthBerryAPA102Mode) + if (_ledCount != ledValues.size()) + { + Warning(_log, "Adalight LED count has changed (old: %d, new: %d). Rebuilding header.", _ledCount, ledValues.size()); + _ledCount = static_cast(ledValues.size()); + _ledRGBCount = _ledCount * 3; + prepareHeader(); + } + + if (_bufferLength > static_cast(_ledBuffer.size())) + { + Warning(_log, "Adalight buffer's size has changed. Skipping refresh."); + return 0; + } + + if (_streamProtocol == Adalight::LBAPA ) { for (signed iLed=1; iLed<=static_cast( _ledCount); iLed++) { - const ColorRgb& rgb = ledValues[iLed-1]; - _ledBuffer[iLed*4+7] = rgb.red; - _ledBuffer[iLed*4+8] = rgb.green; - _ledBuffer[iLed*4+9] = rgb.blue; + const ColorRgb& rgb = ledValues[static_cast(iLed-1)]; + _ledBuffer[static_cast(iLed*4+7)] = rgb.red; + _ledBuffer[static_cast(iLed*4+8)] = rgb.green; + _ledBuffer[static_cast(iLed*4+9)] = rgb.blue; } } else { - assert(_headerSize + ledValues.size() * sizeof(ColorRgb) <= _ledBuffer.size()); + uint8_t* writer = _ledBuffer.data() + HEADER_SIZE; + uint8_t* hasher = writer; - memcpy(_headerSize + _ledBuffer.data(), ledValues.data(), ledValues.size() * sizeof(ColorRgb)); + memcpy(writer, ledValues.data(), ledValues.size() * sizeof(ColorRgb)); + writer += ledValues.size() * sizeof(ColorRgb); + + if (_streamProtocol == Adalight::AWA) + { + whiteChannelExtension(writer); + + uint16_t fletcher1 = 0, fletcher2 = 0; + while (hasher < writer) + { + fletcher1 = (fletcher1 + *(hasher++)) % 255; + fletcher2 = (fletcher2 + fletcher1) % 255; + } + *(writer++) = static_cast(fletcher1); + *(writer++) = static_cast(fletcher2); + } + _bufferLength = writer - _ledBuffer.data(); } - int rc = writeBytes(_ledBuffer.size(), _ledBuffer.data()); + int rc = writeBytes(_bufferLength, _ledBuffer.data()); return rc; } + +void LedDeviceAdalight::whiteChannelExtension(uint8_t*& writer) +{ + if (_streamProtocol == Adalight::AWA && _white_channel_calibration) + { + *(writer++) = _white_channel_limit; + *(writer++) = _white_channel_red; + *(writer++) = _white_channel_green; + *(writer++) = _white_channel_blue; + } +} diff --git a/libsrc/leddevice/dev_serial/LedDeviceAdalight.h b/libsrc/leddevice/dev_serial/LedDeviceAdalight.h index f7df1601..2507bad8 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAdalight.h +++ b/libsrc/leddevice/dev_serial/LedDeviceAdalight.h @@ -4,6 +4,16 @@ // hyperion includes #include "ProviderRs232.h" +namespace Adalight +{ +typedef enum ProtocolType +{ + ADA = 0, + LBAPA, + AWA +} PROTOCOLTYPE; +} + /// /// Implementation of the LedDevice interface for writing to an Adalight LED-device. /// @@ -37,6 +47,11 @@ private: /// bool init(const QJsonObject &deviceConfig) override; + /// + /// @brief Prepare the protocol's header + /// + void prepareHeader(); + /// /// @brief Writes the RGB-Color values to the LEDs. /// @@ -45,8 +60,17 @@ private: /// int write(const std::vector & ledValues) override; - const short _headerSize; - bool _ligthBerryAPA102Mode; + void whiteChannelExtension(uint8_t*& writer); + + qint64 _bufferLength; + + Adalight::PROTOCOLTYPE _streamProtocol; + + bool _white_channel_calibration; + uint8_t _white_channel_limit; + uint8_t _white_channel_red; + uint8_t _white_channel_green; + uint8_t _white_channel_blue; }; #endif // LEDEVICETADALIGHT_H diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.cpp b/libsrc/leddevice/dev_serial/ProviderRs232.cpp index 8a995996..f1298d2e 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.cpp +++ b/libsrc/leddevice/dev_serial/ProviderRs232.cpp @@ -60,7 +60,7 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig) _deviceName = _deviceName.mid(5); } - _baudRate_Hz = deviceConfig["rate"].toInt(); + _baudRate_Hz = deviceConfig["rate"].toInt(); _delayAfterConnect_ms = deviceConfig["delayAfterConnect"].toInt(1500); Debug(_log, "DeviceName : %s", QSTRING_CSTR(_deviceName)); diff --git a/libsrc/leddevice/schemas/schema-adalight.json b/libsrc/leddevice/schemas/schema-adalight.json index 2aa1142e..ac9575d4 100644 --- a/libsrc/leddevice/schemas/schema-adalight.json +++ b/libsrc/leddevice/schemas/schema-adalight.json @@ -8,12 +8,112 @@ "default":"auto", "propertyOrder" : 1 }, + "streamProtocol": { + "type": "string", + "title": "edt_dev_spec_stream_protocol_title", + "enum": [ "0", "1", "2" ], + "default": "0", + "options": { + "enum_titles": [ "edt_dev_spec_ada_mode_title", "edt_dev_spec_LBap102Mode_title","edt_dev_spec_awa_mode_title" ] + }, + "propertyOrder": 2 + }, + "rateList": { + "type": "string", + "title":"edt_dev_spec_baudrate_title", + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "115200", + "access": "advanced", + "propertyOrder" : 3 + }, "rate": { "type": "integer", - "title":"edt_dev_spec_baudrate_title", + "title":"", "default": 115200, - "access" : "advanced", - "propertyOrder" : 2 + "access": "advanced", + "propertyOrder" : 4 + }, + "white_channel_calibration": { + "type": "boolean", + "format": "checkbox", + "title":"edt_dev_spec_rgbw_calibration_enable", + "required" : true, + "default": false, + "options": { + "dependencies": { + "streamProtocol": "2" + } + }, + "access": "advanced", + "propertyOrder" : 5 + }, + "white_channel_limit": { + "type": "number", + "title":"edt_dev_spec_rgbw_calibration_limit", + "required" : true, + "default" : 100, + "step": 0.25, + "minimum" : 0, + "maximum" : 100, + "append" : "edt_append_percent", + "options": { + "dependencies": { + "white_channel_calibration": true + } + }, + "access": "advanced", + "propertyOrder" : 6 + }, + "white_channel_red": { + "type": "integer", + "title":"edt_dev_spec_rgbw_calibration_red", + "required" : true, + "default" : 255, + "step": 1, + "minimum" : 0, + "maximum" : 255, + "options": { + "dependencies": { + "white_channel_calibration": true + } + }, + "access": "advanced", + "propertyOrder" : 7 + }, + "white_channel_green": { + "type": "integer", + "title":"edt_dev_spec_rgbw_calibration_green", + "required" : true, + "default" : 255, + "step": 1, + "minimum" : 0, + "maximum" : 255, + "options": { + "dependencies": { + "white_channel_calibration": true + } + }, + "access": "advanced", + "propertyOrder" : 8 + }, + "white_channel_blue": { + "type": "integer", + "title":"edt_dev_spec_rgbw_calibration_blue", + "required" : true, + "default" : 255, + "step": 1, + "minimum" : 0, + "maximum" : 255, + "options": { + "dependencies": { + "white_channel_calibration": true + } + }, + "access": "advanced", + "propertyOrder" : 9 }, "delayAfterConnect": { "type": "integer", @@ -21,15 +121,7 @@ "default": 0, "append" : "ms", "access" : "expert", - "propertyOrder" : 3 - }, - "lightberry_apa102_mode": { - "type": "boolean", - "title": "edt_dev_spec_LBap102Mode_title", - "default": false, - "required": true, - "access": "advanced", - "propertyOrder": 4 + "propertyOrder" : 10 }, "latchTime": { "type": "integer", @@ -42,7 +134,7 @@ "options": { "infoText": "edt_dev_spec_latchtime_title_info" }, - "propertyOrder": 5 + "propertyOrder": 11 }, "rewriteTime": { "type": "integer", @@ -51,7 +143,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 12 } }, "additionalProperties": true diff --git a/libsrc/leddevice/schemas/schema-atmo.json b/libsrc/leddevice/schemas/schema-atmo.json index b216f61f..50f7608f 100644 --- a/libsrc/leddevice/schemas/schema-atmo.json +++ b/libsrc/leddevice/schemas/schema-atmo.json @@ -8,18 +8,31 @@ "default":"ttyUSB0", "propertyOrder" : 1 }, - "rate": { - "type": "integer", + "rateList": { + "type": "string", "title":"edt_dev_spec_baudrate_title", - "default": 1000000, + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "1000000", + "access": "advanced", "propertyOrder" : 2 }, + "rate": { + "type": "integer", + "title":"", + "default": 1000000, + "access": "advanced", + "propertyOrder" : 3 + }, "delayAfterConnect": { "type": "integer", "title":"edt_dev_spec_delayAfterConnect_title", "default": 250, "append" : "ms", - "propertyOrder" : 3 + "access" : "expert", + "propertyOrder" : 4 }, "latchTime": { "type": "integer", @@ -29,7 +42,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 4 + "propertyOrder" : 5 }, "rewriteTime": { "type": "integer", @@ -38,7 +51,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 6 } }, "additionalProperties": true diff --git a/libsrc/leddevice/schemas/schema-dmx.json b/libsrc/leddevice/schemas/schema-dmx.json index 33abe89f..31c0e2c1 100644 --- a/libsrc/leddevice/schemas/schema-dmx.json +++ b/libsrc/leddevice/schemas/schema-dmx.json @@ -20,17 +20,30 @@ "default":"ttyUSB0", "propertyOrder" : 2 }, - "rate": { - "type": "integer", + "rateList": { + "type": "string", "title":"edt_dev_spec_baudrate_title", - "default": 250000, + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","250000","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "250000", + "access": "advanced", "propertyOrder" : 3 }, + "rate": { + "type": "integer", + "title":"", + "default": 250000, + "access": "advanced", + "propertyOrder" : 4 + }, "delayAfterConnect": { "type": "integer", "title":"edt_dev_spec_delayAfterConnect_title", "default": 250, - "propertyOrder" : 4 + "access" : "expert", + "propertyOrder" : 5 }, "latchTime": { "type": "integer", @@ -40,7 +53,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 6 }, "rewriteTime": { "type": "integer", @@ -49,7 +62,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 6 + "propertyOrder" : 7 } }, "additionalProperties": true diff --git a/libsrc/leddevice/schemas/schema-karate.json b/libsrc/leddevice/schemas/schema-karate.json index 6a6ec7d8..6a515a94 100644 --- a/libsrc/leddevice/schemas/schema-karate.json +++ b/libsrc/leddevice/schemas/schema-karate.json @@ -8,18 +8,31 @@ "default":"ttyACM0", "propertyOrder" : 1 }, + "rateList": { + "type": "string", + "title":"edt_dev_spec_baudrate_title", + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "1000000", + "access": "advanced", + "propertyOrder" : 2 + }, "rate": { "type": "integer", - "title":"edt_dev_spec_baudrate_title", + "title":"", "default": 1000000, - "propertyOrder" : 2 + "access": "advanced", + "propertyOrder" : 3 }, "delayAfterConnect": { "type": "integer", "title":"edt_dev_spec_delayAfterConnect_title", "default": 1500, "append" : "ms", - "propertyOrder" : 3 + "access" : "expert", + "propertyOrder" : 4 }, "latchTime": { "type": "integer", @@ -29,7 +42,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 4 + "propertyOrder" : 5 }, "rewriteTime": { "type": "integer", @@ -38,7 +51,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 6 } }, "additionalProperties": true diff --git a/libsrc/leddevice/schemas/schema-sedu.json b/libsrc/leddevice/schemas/schema-sedu.json index cb22d564..ba7978eb 100644 --- a/libsrc/leddevice/schemas/schema-sedu.json +++ b/libsrc/leddevice/schemas/schema-sedu.json @@ -8,17 +8,30 @@ "default":"ttyACM0", "propertyOrder" : 1 }, + "rateList": { + "type": "string", + "title":"edt_dev_spec_baudrate_title", + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "1000000", + "access": "advanced", + "propertyOrder" : 2 + }, "rate": { "type": "integer", - "title":"edt_dev_spec_baudrate_title", + "title":"", "default": 1000000, - "propertyOrder" : 2 + "access": "advanced", + "propertyOrder" : 3 }, "delayAfterConnect": { "type": "integer", "title":"edt_dev_spec_delayAfterConnect_title", "default": 250, - "propertyOrder" : 3 + "access" : "expert", + "propertyOrder" : 4 }, "latchTime": { "type": "integer", @@ -28,7 +41,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 4 + "propertyOrder" : 5 }, "rewriteTime": { "type": "integer", @@ -37,7 +50,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 6 } }, "additionalProperties": true diff --git a/libsrc/leddevice/schemas/schema-tpm2.json b/libsrc/leddevice/schemas/schema-tpm2.json index dd5b7c6a..ce49945d 100644 --- a/libsrc/leddevice/schemas/schema-tpm2.json +++ b/libsrc/leddevice/schemas/schema-tpm2.json @@ -8,17 +8,30 @@ "default":"ttyACM0", "propertyOrder" : 1 }, + "rateList": { + "type": "string", + "title":"edt_dev_spec_baudrate_title", + "enum": [ "CUSTOM","9600","14400","19200","28800","33600","38400","56000","57600","76800","115200","128000","153600","230400","256000","307200","460800","921600","1000000","1500000","2000000","3000000","4000000" ], + "options": { + "enum_titles": [ "edt_conf_enum_custom" ] + }, + "default": "1000000", + "access": "advanced", + "propertyOrder" : 2 + }, "rate": { "type": "integer", - "title":"edt_dev_spec_baudrate_title", + "title":"", "default": 1000000, - "propertyOrder" : 2 + "access": "advanced", + "propertyOrder" : 3 }, "delayAfterConnect": { "type": "integer", "title":"edt_dev_spec_delayAfterConnect_title", "default": 250, - "propertyOrder" : 3 + "access" : "expert", + "propertyOrder" : 4 }, "latchTime": { "type": "integer", @@ -28,7 +41,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 4 + "propertyOrder" : 5 }, "rewriteTime": { "type": "integer", @@ -37,7 +50,7 @@ "append" : "edt_append_ms", "minimum": 0, "access" : "expert", - "propertyOrder" : 5 + "propertyOrder" : 6 } }, "additionalProperties": true }