Add rainbow effect to led strip and cleanup (#3322)

* Add rainbow effect and cleanup

* reduce indentation
master
ASDosjani 2023-03-16 15:08:59 +01:00 committed by GitHub
parent 36628523db
commit b21468d41f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 174 additions and 113 deletions

View File

@ -3527,17 +3527,16 @@
"message": "LEDs without wire ordering number will not be saved.", "message": "LEDs without wire ordering number will not be saved.",
"description": "Message in the wiring modes in Led Strip" "description": "Message in the wiring modes in Led Strip"
}, },
"ledStripVtxFunction": { "ledStripLarsonOverlay": {
"message": "Larson scanner" "message": "Larson scanner",
}, "description": "Larson effect switch label on LED Strip tab"
"ledStripBlinkTitle": {
"message": "Blink"
}, },
"ledStripBlinkAlwaysOverlay": { "ledStripBlinkAlwaysOverlay": {
"message": "Blink always" "message": "Blink always"
}, },
"ledStripBlinkLandingOverlay": { "ledStripRainbowOverlay": {
"message": "Blink on landing" "message": "Rainbow",
"description": "Rainbow effect switch label on LED Strip tab"
}, },
"ledStripOverlayTitle": { "ledStripOverlayTitle": {
"message": "Overlay" "message": "Overlay"

View File

@ -150,14 +150,14 @@
margin-left: -9px; margin-left: -9px;
} }
} }
.gPoint.function-n { .gPoint.function-y {
.overlay-n { .overlay-y {
float: left; float: left;
height: 6px; height: 6px;
width: 16px; width: 16px;
background-image: radial-gradient(1px at 8px 50% , blue 0%, blue 2px, rgba(0, 0, 0, 0.3) 3px, rgba(0, 0, 0, 0) 4px); background-image: radial-gradient(1px at 8px 50% , rgb(0, 242, 12) 0%, rgb(0, 242, 12) 0% 2px, rgba(0, 0, 0, 0.3) 3px, rgba(0, 0, 0, 0) 4px);
margin-top: -18px; margin-top: -30px;
margin-left: 16px; margin-left: 4px;
} }
} }
.gPoint { .gPoint {
@ -232,9 +232,6 @@
.overlays { .overlays {
display: inline-block; display: inline-block;
} }
.blinkers {
display: inline-block;
}
.modifiers { .modifiers {
display: inline-block; display: inline-block;
.auxSelect { .auxSelect {
@ -384,14 +381,14 @@
} }
.north { .north {
top: -9px; top: -9px;
left: 4px; left: 5px;
border-left: 7px solid transparent; border-left: 7px solid transparent;
border-right: 7px solid transparent; border-right: 7px solid transparent;
border-bottom: 7px solid rgba(0,0,0,.8); border-bottom: 7px solid rgba(0,0,0,.8);
} }
.south { .south {
bottom: -8px; bottom: -8px;
left: 4px; left: 5px;
border-left: 7px solid transparent; border-left: 7px solid transparent;
border-right: 7px solid transparent; border-right: 7px solid transparent;
border-top: 7px solid rgba(0,0,0,.8); border-top: 7px solid rgba(0,0,0,.8);

View File

@ -8,7 +8,7 @@ import semver from 'semver';
import vtxDeviceStatusFactory from "../utils/VtxDeviceStatus/VtxDeviceStatusFactory"; import vtxDeviceStatusFactory from "../utils/VtxDeviceStatus/VtxDeviceStatusFactory";
import MSP from "../msp"; import MSP from "../msp";
import MSPCodes from "./MSPCodes"; import MSPCodes from "./MSPCodes";
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from '../data_storage'; import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45, API_VERSION_1_46 } from '../data_storage';
import EscProtocols from "../utils/EscProtocols"; import EscProtocols from "../utils/EscProtocols";
import huffmanDecodeBuf from "../huffman"; import huffmanDecodeBuf from "../huffman";
import { defaultHuffmanTree, defaultHuffmanLenIndex } from "../default_huffman_tree"; import { defaultHuffmanTree, defaultHuffmanLenIndex } from "../default_huffman_tree";
@ -20,7 +20,7 @@ import { OSD } from "../tabs/osd";
// Used for LED_STRIP // Used for LED_STRIP
const ledDirectionLetters = ['n', 'e', 's', 'w', 'u', 'd']; // in LSB bit order const ledDirectionLetters = ['n', 'e', 's', 'w', 'u', 'd']; // in LSB bit order
const ledBaseFunctionLetters = ['c', 'f', 'a', 'l', 's', 'g', 'r']; // in LSB bit const ledBaseFunctionLetters = ['c', 'f', 'a', 'l', 's', 'g', 'r']; // in LSB bit
let ledOverlayLetters = ['t', 'o', 'b', 'v', 'i', 'w']; // in LSB bit let ledOverlayLetters = ['t', 'y', 'o', 'b', 'v', 'i', 'w']; // in LSB bit
function MspHelper() { function MspHelper() {
const self = this; const self = this;
@ -1167,50 +1167,102 @@ MspHelper.prototype.process_data = function(dataHandler) {
case MSPCodes.MSP_LED_STRIP_CONFIG: case MSPCodes.MSP_LED_STRIP_CONFIG:
FC.LED_STRIP = []; FC.LED_STRIP = [];
let ledCount = (data.byteLength - 2) / 4;
// The 32 bit config of each LED contains these in LSB:
// +--------------------+--------------------+------------------+------------------+----------------------+-----------+-----------+
// | Parameters - 3 bit | Directions - 6 bit | Color ID - 4 bit | Overlays - 7 bit | Function ID - 4 bit | X - 4 bit | Y - 4 bit |
// +--------------------+--------------------+------------------+------------------+----------------------+-----------+-----------+
// According to betaflight/src/main/msp/msp.c // According to betaflight/src/main/msp/msp.c
// API 1.41 - add indicator for advanced profile support and the current profile selection // API 1.41 - add indicator for advanced profile support and the current profile selection
// 0 = basic ledstrip available // 0 = basic ledstrip available
// 1 = advanced ledstrip available // 1 = advanced ledstrip available
// Following byte is the current LED profile // Following byte is the current LED profile
let ledCount = (data.byteLength - 2) / 4;
for (let i = 0; i < ledCount; i++) { //Before API_VERSION_1_46 Parameters were 4 bit and Overlays 6 bit
const mask = data.readU32(); if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
const functionId = (mask >> 8) & 0xF; for (let i = 0; i < ledCount; i++) {
const functions = [];
for (let baseFunctionLetterIndex = 0; baseFunctionLetterIndex < ledBaseFunctionLetters.length; baseFunctionLetterIndex++) { const mask = data.readU32();
if (functionId == baseFunctionLetterIndex) {
functions.push(ledBaseFunctionLetters[baseFunctionLetterIndex]); const functionId = (mask >> 8) & 0xF;
break; const functions = [];
for (let baseFunctionLetterIndex = 0; baseFunctionLetterIndex < ledBaseFunctionLetters.length; baseFunctionLetterIndex++) {
if (functionId == baseFunctionLetterIndex) {
functions.push(ledBaseFunctionLetters[baseFunctionLetterIndex]);
break;
}
} }
}
const overlayMask = (mask >> 12) & 0x3F; const overlayMask = (mask >> 12) & 0x7F;
for (let overlayLetterIndex = 0; overlayLetterIndex < ledOverlayLetters.length; overlayLetterIndex++) { for (let overlayLetterIndex = 0; overlayLetterIndex < ledOverlayLetters.length; overlayLetterIndex++) {
if (bit_check(overlayMask, overlayLetterIndex)) { if (bit_check(overlayMask, overlayLetterIndex)) {
functions.push(ledOverlayLetters[overlayLetterIndex]); functions.push(ledOverlayLetters[overlayLetterIndex]);
}
} }
}
const directionMask = (mask >> 22) & 0x3F; const directionMask = (mask >> 23) & 0x3F;
const directions = []; const directions = [];
for (let directionLetterIndex = 0; directionLetterIndex < ledDirectionLetters.length; directionLetterIndex++) { for (let directionLetterIndex = 0; directionLetterIndex < ledDirectionLetters.length; directionLetterIndex++) {
if (bit_check(directionMask, directionLetterIndex)) { if (bit_check(directionMask, directionLetterIndex)) {
directions.push(ledDirectionLetters[directionLetterIndex]); directions.push(ledDirectionLetters[directionLetterIndex]);
}
} }
} const led = {
const led = { y: (mask) & 0xF,
y: (mask) & 0xF, x: (mask >> 4) & 0xF,
x: (mask >> 4) & 0xF, functions: functions,
functions: functions, color: (mask >> 19) & 0xF,
color: (mask >> 18) & 0xF, directions: directions,
directions: directions, parameters: (mask >>> 29) & 0x7,
parameters: (mask >> 28) & 0xF, };
};
FC.LED_STRIP.push(led); FC.LED_STRIP.push(led);
}
}
else {
ledOverlayLetters = ledOverlayLetters.filter(x => x !== 'y');
for (let i = 0; i < ledCount; i++) {
const mask = data.readU32();
const functionId = (mask >> 8) & 0xF;
const functions = [];
for (let baseFunctionLetterIndex = 0; baseFunctionLetterIndex < ledBaseFunctionLetters.length; baseFunctionLetterIndex++) {
if (functionId == baseFunctionLetterIndex) {
functions.push(ledBaseFunctionLetters[baseFunctionLetterIndex]);
break;
}
}
const overlayMask = (mask >> 12) & 0x3F;
for (let overlayLetterIndex = 0; overlayLetterIndex < ledOverlayLetters.length; overlayLetterIndex++) {
if (bit_check(overlayMask, overlayLetterIndex)) {
functions.push(ledOverlayLetters[overlayLetterIndex]);
}
}
const directionMask = (mask >> 22) & 0x3F;
const directions = [];
for (let directionLetterIndex = 0; directionLetterIndex < ledDirectionLetters.length; directionLetterIndex++) {
if (bit_check(directionMask, directionLetterIndex)) {
directions.push(ledDirectionLetters[directionLetterIndex]);
}
}
const led = {
y: (mask) & 0xF,
x: (mask >> 4) & 0xF,
functions: functions,
color: (mask >> 18) & 0xF,
directions: directions,
parameters: (mask >> 28) & 0xF,
};
FC.LED_STRIP.push(led);
}
} }
break; break;
case MSPCodes.MSP_SET_LED_STRIP_CONFIG: case MSPCodes.MSP_SET_LED_STRIP_CONFIG:
@ -2491,25 +2543,49 @@ MspHelper.prototype.sendLedStripConfig = function(onCompleteCallback) {
} }
} }
for (let overlayLetterIndex = 0; overlayLetterIndex < led.functions.length; overlayLetterIndex++) { if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
const bitIndex = ledOverlayLetters.indexOf(led.functions[overlayLetterIndex]);
if (bitIndex >= 0) { for (let overlayLetterIndex = 0; overlayLetterIndex < led.functions.length; overlayLetterIndex++) {
mask |= bit_set(mask, bitIndex + 12); const bitIndex = ledOverlayLetters.indexOf(led.functions[overlayLetterIndex]);
if (bitIndex >= 0) {
mask |= bit_set(mask, bitIndex + 12);
}
} }
}
mask |= (led.color << 18); mask |= (led.color << 19);
for (let directionLetterIndex = 0; directionLetterIndex < led.directions.length; directionLetterIndex++) { for (let directionLetterIndex = 0; directionLetterIndex < led.directions.length; directionLetterIndex++) {
const bitIndex = ledDirectionLetters.indexOf(led.directions[directionLetterIndex]); const bitIndex = ledDirectionLetters.indexOf(led.directions[directionLetterIndex]);
if (bitIndex >= 0) { if (bitIndex >= 0) {
mask |= bit_set(mask, bitIndex + 22); mask |= bit_set(mask, bitIndex + 23);
}
} }
mask |= (0 << 29); // parameters
buffer.push32(mask);
} }
else {
for (let overlayLetterIndex = 0; overlayLetterIndex < led.functions.length; overlayLetterIndex++) {
const bitIndex = ledOverlayLetters.indexOf(led.functions[overlayLetterIndex]);
if (bitIndex >= 0) {
mask |= bit_set(mask, bitIndex + 12);
}
}
mask |= (0 << 28); // parameters mask |= (led.color << 18);
buffer.push32(mask); for (let directionLetterIndex = 0; directionLetterIndex < led.directions.length; directionLetterIndex++) {
const bitIndex = ledDirectionLetters.indexOf(led.directions[directionLetterIndex]);
if (bitIndex >= 0) {
mask |= bit_set(mask, bitIndex + 22);
}
}
mask |= (0 << 28); // parameters
buffer.push32(mask);
}
// prepare for next iteration // prepare for next iteration
ledIndex++; ledIndex++;

View File

@ -2,8 +2,10 @@ import { i18n } from "../localization";
import GUI, { TABS } from '../gui'; import GUI, { TABS } from '../gui';
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; import FC from "../fc";
import semver from 'semver';
import MSP from "../msp"; import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes"; import MSPCodes from "../msp/MSPCodes";
import { API_VERSION_1_46 } from '../data_storage';
import { gui_log } from "../gui_log"; import { gui_log } from "../gui_log";
const led_strip = { const led_strip = {
@ -16,9 +18,13 @@ led_strip.initialize = function (callback, scrollPosition) {
let selectedModeColor = null; let selectedModeColor = null;
const functionTag = '.function-'; const functionTag = '.function-';
TABS.led_strip.functions = ['i', 'w', 'f', 'a', 't', 'r', 'c', 'g', 's', 'b', 'l', 'o', 'n']; TABS.led_strip.functions = ['i', 'w', 'f', 'a', 't', 'r', 'c', 'g', 's', 'b', 'l', 'o', 'y'];
TABS.led_strip.baseFuncs = ['c', 'f', 'a', 'l', 's', 'g', 'r']; TABS.led_strip.baseFuncs = ['c', 'f', 'a', 'l', 's', 'g', 'r'];
TABS.led_strip.overlays = ['t', 'o', 'b', 'v', 'i', 'w']; TABS.led_strip.overlays = ['t', 'y', 'o', 'b', 'v', 'i', 'w'];
if (semver.lt(FC.CONFIG.apiVersion,API_VERSION_1_46)) {
TABS.led_strip.overlays = TABS.led_strip.overlays.filter(x => x !== 'y');
}
TABS.led_strip.wireMode = false; TABS.led_strip.wireMode = false;
@ -64,12 +70,12 @@ led_strip.initialize = function (callback, scrollPosition) {
const theHTML = []; const theHTML = [];
let theHTMLlength = 0; let theHTMLlength = 0;
for (let i = 0; i < 256; i++) { for (let i = 0; i < 256; i++) {
theHTML[theHTMLlength++] = ('<div class="gPoint"><div class="indicators"><span class="north"></span><span class="south"></span><span class="west"></span><span class="east"></span><span class="up">U</span><span class="down">D</span></div><span class="wire"></span><span class="overlay-t"> </span><span class="overlay-o"> </span><span class="overlay-b"> </span><span class="overlay-v"> </span><span class="overlay-i"> </span><span class="overlay-w"> </span><span class="overlay-color"> </span></div>'); theHTML[theHTMLlength++] = ('<div class="gPoint"><div class="indicators"><span class="north"></span><span class="south"></span><span class="west"></span><span class="east"></span><span class="up">U</span><span class="down">D</span></div><span class="wire"></span><span class="overlay-t"> </span><span class="overlay-y"> </span><span class="overlay-o"> </span><span class="overlay-b"> </span><span class="overlay-v"> </span><span class="overlay-i"> </span><span class="overlay-w"> </span><span class="overlay-color"> </span></div>');
} }
$('.mainGrid').html(theHTML.join('')); $('.mainGrid').html(theHTML.join(''));
$('.tempOutput').click(function() { $('.tempOutput').on('click', function() {
$(this).select(); $(this).trigger('select');
}); });
// Aux channel drop-down // Aux channel drop-down
@ -85,11 +91,10 @@ led_strip.initialize = function (callback, scrollPosition) {
setModeColor(AuxMode, AuxDir, $('.auxSelect').val()); setModeColor(AuxMode, AuxDir, $('.auxSelect').val());
}); });
$('.landingBlinkOverlay').css("visibility", "hidden");
$('.vtxOverlay').show(); $('.vtxOverlay').show();
// Clear button // Clear button
$('.funcClear').click(function() { $('.funcClear').on('click', function() {
$('.gPoint').each(function() { $('.gPoint').each(function() {
if ($(this).is('.ui-selected')) { if ($(this).is('.ui-selected')) {
removeFunctionsAndDirections(this); removeFunctionsAndDirections(this);
@ -102,7 +107,7 @@ led_strip.initialize = function (callback, scrollPosition) {
}); });
// Clear All button // Clear All button
$('.funcClearAll').click(function() { $('.funcClearAll').on('click', function() {
$('.gPoint').each(function() { $('.gPoint').each(function() {
removeFunctionsAndDirections(this); removeFunctionsAndDirections(this);
}); });
@ -263,13 +268,13 @@ led_strip.initialize = function (callback, scrollPosition) {
}, },
}); });
$('.funcWire').click(function() { $('.funcWire').on('click', function() {
$(this).toggleClass('btnOn'); $(this).toggleClass('btnOn');
TABS.led_strip.wireMode = $(this).hasClass('btnOn'); TABS.led_strip.wireMode = $(this).hasClass('btnOn');
$('.mainGrid').toggleClass('gridWire'); $('.mainGrid').toggleClass('gridWire');
}); });
$('.funcWireClearSelect').click(function() { $('.funcWireClearSelect').on('click', function() {
$('.ui-selected').each(function() { $('.ui-selected').each(function() {
const thisWire = $(this).find('.wire'); const thisWire = $(this).find('.wire');
if (thisWire.html() !== '') { if (thisWire.html() !== '') {
@ -279,7 +284,7 @@ led_strip.initialize = function (callback, scrollPosition) {
}); });
}); });
$('.funcWireClear').click(function() { $('.funcWireClear').on('click', function() {
$('.gPoint .wire').html(''); $('.gPoint .wire').html('');
updateBulkCmd(); updateBulkCmd();
}); });
@ -444,16 +449,13 @@ led_strip.initialize = function (callback, scrollPosition) {
switch (letter) { switch (letter) {
case 't': case 't':
case 'y':
case 'o': case 'o':
case 's': case 's':
if (areModifiersActive(`function-${f}`)) if (areModifiersActive(`function-${f}`))
p.addClass(`function-${letter}`); p.addClass(`function-${letter}`);
break; break;
case 'b': case 'b':
case 'n':
if (areBlinkersActive(`function-${f}`))
p.addClass(`function-${letter}`);
break;
case 'i': case 'i':
if (areOverlaysActive(`function-${f}`)) if (areOverlaysActive(`function-${f}`))
p.addClass(`function-${letter}`); p.addClass(`function-${letter}`);
@ -503,25 +505,9 @@ led_strip.initialize = function (callback, scrollPosition) {
} }
if ($('.ui-selected').length > 0) { if ($('.ui-selected').length > 0) {
TABS.led_strip.overlays.forEach(function(letter) { TABS.led_strip.overlays.forEach(function(letter) {
if ($(that).is(functionTag + letter)) { if ($(that).is(functionTag + letter)) {
const ret = toggleSwitch(that, letter); toggleSwitch(that, letter);
const cbn = $('.checkbox .function-n'); // blink on landing
const cbb = $('.checkbox .function-b'); // blink
if (ret) {
if (letter == 'b' && cbn.is(':checked')) {
cbn.prop('checked', false);
cbn.trigger('change');
toggleSwitch(cbn, 'n');
} else if (letter == 'n' && cbb.is(':checked')) {
cbb.prop('checked', false);
cbb.trigger('change');
toggleSwitch(cbb, 'b');
}
}
} }
}); });
@ -736,7 +722,9 @@ led_strip.initialize = function (callback, scrollPosition) {
case "function-s": case "function-s":
case "function-l": case "function-l":
case "function-r": case "function-r":
case "function-y":
case "function-o": case "function-o":
case "function-b":
case "function-g": case "function-g":
return true; return true;
default: default:
@ -745,14 +733,16 @@ led_strip.initialize = function (callback, scrollPosition) {
return false; return false;
} }
function areBlinkersActive(activeFunction) { function isRainbowActive(activeFunction) {
switch (activeFunction) { if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
case "function-c": switch (activeFunction) {
case "function-a": case "function-c":
case "function-f": case "function-a":
return true; case "function-f":
default: return true;
break; default:
break;
}
} }
return false; return false;
} }
@ -799,7 +789,7 @@ led_strip.initialize = function (callback, scrollPosition) {
$('.modifiers').toggle(areModifiersActive(activeFunction)); $('.modifiers').toggle(areModifiersActive(activeFunction));
$('.blinkers').toggle(areBlinkersActive(activeFunction)); $('.rainbowOverlay').toggle(isRainbowActive(activeFunction));
$('.warningOverlay').toggle(isWarningActive(activeFunction)); $('.warningOverlay').toggle(isWarningActive(activeFunction));
@ -881,18 +871,18 @@ led_strip.initialize = function (callback, scrollPosition) {
function unselectOverlays(letter) { function unselectOverlays(letter) {
// MSP 1.20 // MSP 1.20
if (letter == 'r' || letter == '') { if (letter == 'r' || letter == '') {
unselectOverlay(letter, 'y');
unselectOverlay(letter, 'o'); unselectOverlay(letter, 'o');
unselectOverlay(letter, 'b'); unselectOverlay(letter, 'b');
unselectOverlay(letter, 'n');
unselectOverlay(letter, 't'); unselectOverlay(letter, 't');
} }
if (letter == 'l' || letter == 'g' || letter == 's') { if (letter == 'l' || letter == 'g' || letter == 's') {
unselectOverlay(letter, 'w'); unselectOverlay(letter, 'w');
unselectOverlay(letter, 'v'); unselectOverlay(letter, 'v');
unselectOverlay(letter, 't'); unselectOverlay(letter, 't');
unselectOverlay(letter, 'y');
unselectOverlay(letter, 'o'); unselectOverlay(letter, 'o');
unselectOverlay(letter, 'b'); unselectOverlay(letter, 'b');
unselectOverlay(letter, 'n');
} }
} }

View File

@ -47,6 +47,7 @@ export function checkChromeRuntimeError() {
} }
const majorFirmwareVersions = { const majorFirmwareVersions = {
"1.46": "4.5.*",
"1.45": "4.4.*", "1.45": "4.4.*",
"1.44": "4.3.*", "1.44": "4.3.*",
"1.43": "4.2.*", "1.43": "4.2.*",

View File

@ -77,19 +77,17 @@
<div class="checkbox extra_functions20"> <div class="checkbox extra_functions20">
<input type="checkbox" name="LarsonScanner" class="toggle function-o" /> <input type="checkbox" name="LarsonScanner" class="toggle function-o" />
<label> <span i18n="ledStripVtxFunction"></span></label> <label> <span i18n="ledStripLarsonOverlay"></span></label>
</div> </div>
</div>
<div class="checkbox extra_functions20">
<div class="blinkers extra_functions20">
<span class="color_section" i18n="ledStripBlinkTitle"></span>
<div class="checkbox blinkOverlay">
<input type="checkbox" name="blink" class="toggle function-b" /> <input type="checkbox" name="blink" class="toggle function-b" />
<label> <span i18n="ledStripBlinkAlwaysOverlay"></span></label> <label> <span i18n="ledStripBlinkAlwaysOverlay"></span></label>
</div> </div>
<div class="checkbox landingBlinkOverlay">
<input type="checkbox" name="landingBlink" class="toggle function-n" /> <div class="checkbox extra_functions20 rainbowOverlay">
<label> <span i18n="ledStripBlinkLandingOverlay"></span></label> <input type="checkbox" name="Rainbow" class="toggle function-y" />
<label> <span i18n="ledStripRainbowOverlay"></span></label>
</div> </div>
</div> </div>