Merge branch '0_14_1' into power-supply
This commit is contained in:
commit
4f5816f42e
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.0",
|
"version": "0.14.1-a1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.14.0",
|
"version": "0.14.1-a1",
|
||||||
"description": "Tools for WLED project",
|
"description": "Tools for WLED project",
|
||||||
"main": "tools/cdata.js",
|
"main": "tools/cdata.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
@ -217,7 +217,7 @@ build_flags =
|
|||||||
; restrict to minimal mime-types
|
; restrict to minimal mime-types
|
||||||
-DMIMETYPE_MINIMAL
|
-DMIMETYPE_MINIMAL
|
||||||
; other special-purpose framework flags (see https://docs.platformio.org/en/latest/platforms/espressif8266.html)
|
; other special-purpose framework flags (see https://docs.platformio.org/en/latest/platforms/espressif8266.html)
|
||||||
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;; in case of linker errors like "section `.text1' will not fit in region `iram1_0_seg'"
|
-D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 ;; in case of linker errors like "section `.text1' will not fit in region `iram1_0_seg'"
|
||||||
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown
|
; -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED ;; (experimental) adds some extra heap, but may cause slowdown
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
@ -52,9 +52,15 @@ class PWMFanUsermod : public Usermod {
|
|||||||
uint8_t tachoUpdateSec = 30;
|
uint8_t tachoUpdateSec = 30;
|
||||||
float targetTemperature = 35.0;
|
float targetTemperature = 35.0;
|
||||||
uint8_t minPWMValuePct = 0;
|
uint8_t minPWMValuePct = 0;
|
||||||
|
uint8_t maxPWMValuePct = 100;
|
||||||
uint8_t numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
|
uint8_t numberOfInterrupsInOneSingleRotation = 2; // Number of interrupts ESP32 sees on tacho signal on a single fan rotation. All the fans I've seen trigger two interrups.
|
||||||
uint8_t pwmValuePct = 0;
|
uint8_t pwmValuePct = 0;
|
||||||
|
|
||||||
|
// constant values
|
||||||
|
static const uint8_t _pwmMaxValue = 255;
|
||||||
|
static const uint8_t _pwmMaxStepCount = 7;
|
||||||
|
float _pwmTempStepSize = 0.5f;
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
static const char _name[];
|
static const char _name[];
|
||||||
static const char _enabled[];
|
static const char _enabled[];
|
||||||
@ -63,6 +69,7 @@ class PWMFanUsermod : public Usermod {
|
|||||||
static const char _temperature[];
|
static const char _temperature[];
|
||||||
static const char _tachoUpdateSec[];
|
static const char _tachoUpdateSec[];
|
||||||
static const char _minPWMValuePct[];
|
static const char _minPWMValuePct[];
|
||||||
|
static const char _maxPWMValuePct[];
|
||||||
static const char _IRQperRotation[];
|
static const char _IRQperRotation[];
|
||||||
static const char _speed[];
|
static const char _speed[];
|
||||||
static const char _lock[];
|
static const char _lock[];
|
||||||
@ -156,31 +163,25 @@ class PWMFanUsermod : public Usermod {
|
|||||||
|
|
||||||
void setFanPWMbasedOnTemperature(void) {
|
void setFanPWMbasedOnTemperature(void) {
|
||||||
float temp = getActualTemperature();
|
float temp = getActualTemperature();
|
||||||
float difftemp = temp - targetTemperature;
|
// dividing minPercent and maxPercent into equal pwmvalue sizes
|
||||||
// Default to run fan at full speed.
|
int pwmStepSize = ((maxPWMValuePct - minPWMValuePct) * _pwmMaxValue) / (_pwmMaxStepCount*100);
|
||||||
int newPWMvalue = 255;
|
int pwmStep = calculatePwmStep(temp - targetTemperature);
|
||||||
int pwmStep = ((100 - minPWMValuePct) * newPWMvalue) / (7*100);
|
// minimum based on full speed - not entered MaxPercent
|
||||||
int pwmMinimumValue = (minPWMValuePct * newPWMvalue) / 100;
|
int pwmMinimumValue = (minPWMValuePct * _pwmMaxValue) / 100;
|
||||||
|
updateFanSpeed(pwmMinimumValue + pwmStep*pwmStepSize);
|
||||||
if ((temp == NAN) || (temp <= -100.0)) {
|
|
||||||
DEBUG_PRINTLN(F("WARNING: no temperature value available. Cannot do temperature control. Will set PWM fan to 255."));
|
|
||||||
} else if (difftemp <= 0.0) {
|
|
||||||
// Temperature is below target temperature. Run fan at minimum speed.
|
|
||||||
newPWMvalue = pwmMinimumValue;
|
|
||||||
} else if (difftemp <= 0.5) {
|
|
||||||
newPWMvalue = pwmMinimumValue + pwmStep;
|
|
||||||
} else if (difftemp <= 1.0) {
|
|
||||||
newPWMvalue = pwmMinimumValue + 2*pwmStep;
|
|
||||||
} else if (difftemp <= 1.5) {
|
|
||||||
newPWMvalue = pwmMinimumValue + 3*pwmStep;
|
|
||||||
} else if (difftemp <= 2.0) {
|
|
||||||
newPWMvalue = pwmMinimumValue + 4*pwmStep;
|
|
||||||
} else if (difftemp <= 2.5) {
|
|
||||||
newPWMvalue = pwmMinimumValue + 5*pwmStep;
|
|
||||||
} else if (difftemp <= 3.0) {
|
|
||||||
newPWMvalue = pwmMinimumValue + 6*pwmStep;
|
|
||||||
}
|
}
|
||||||
updateFanSpeed(newPWMvalue);
|
|
||||||
|
uint8_t calculatePwmStep(float diffTemp){
|
||||||
|
if ((diffTemp == NAN) || (diffTemp <= -100.0)) {
|
||||||
|
DEBUG_PRINTLN(F("WARNING: no temperature value available. Cannot do temperature control. Will set PWM fan to 255."));
|
||||||
|
return _pwmMaxStepCount;
|
||||||
|
}
|
||||||
|
if(diffTemp <=0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int calculatedStep = (diffTemp / _pwmTempStepSize)+1;
|
||||||
|
// anything greater than max stepcount gets max
|
||||||
|
return (uint8_t)min((int)_pwmMaxStepCount,calculatedStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -312,6 +313,7 @@ class PWMFanUsermod : public Usermod {
|
|||||||
top[FPSTR(_tachoUpdateSec)] = tachoUpdateSec;
|
top[FPSTR(_tachoUpdateSec)] = tachoUpdateSec;
|
||||||
top[FPSTR(_temperature)] = targetTemperature;
|
top[FPSTR(_temperature)] = targetTemperature;
|
||||||
top[FPSTR(_minPWMValuePct)] = minPWMValuePct;
|
top[FPSTR(_minPWMValuePct)] = minPWMValuePct;
|
||||||
|
top[FPSTR(_maxPWMValuePct)] = maxPWMValuePct;
|
||||||
top[FPSTR(_IRQperRotation)] = numberOfInterrupsInOneSingleRotation;
|
top[FPSTR(_IRQperRotation)] = numberOfInterrupsInOneSingleRotation;
|
||||||
DEBUG_PRINTLN(F("Autosave config saved."));
|
DEBUG_PRINTLN(F("Autosave config saved."));
|
||||||
}
|
}
|
||||||
@ -345,6 +347,8 @@ class PWMFanUsermod : public Usermod {
|
|||||||
targetTemperature = top[FPSTR(_temperature)] | targetTemperature;
|
targetTemperature = top[FPSTR(_temperature)] | targetTemperature;
|
||||||
minPWMValuePct = top[FPSTR(_minPWMValuePct)] | minPWMValuePct;
|
minPWMValuePct = top[FPSTR(_minPWMValuePct)] | minPWMValuePct;
|
||||||
minPWMValuePct = (uint8_t) min(100,max(0,(int)minPWMValuePct)); // bounds checking
|
minPWMValuePct = (uint8_t) min(100,max(0,(int)minPWMValuePct)); // bounds checking
|
||||||
|
maxPWMValuePct = top[FPSTR(_maxPWMValuePct)] | maxPWMValuePct;
|
||||||
|
maxPWMValuePct = (uint8_t) min(100,max((int)minPWMValuePct,(int)maxPWMValuePct)); // bounds checking
|
||||||
numberOfInterrupsInOneSingleRotation = top[FPSTR(_IRQperRotation)] | numberOfInterrupsInOneSingleRotation;
|
numberOfInterrupsInOneSingleRotation = top[FPSTR(_IRQperRotation)] | numberOfInterrupsInOneSingleRotation;
|
||||||
numberOfInterrupsInOneSingleRotation = (uint8_t) max(1,(int)numberOfInterrupsInOneSingleRotation); // bounds checking
|
numberOfInterrupsInOneSingleRotation = (uint8_t) max(1,(int)numberOfInterrupsInOneSingleRotation); // bounds checking
|
||||||
|
|
||||||
@ -389,6 +393,7 @@ const char PWMFanUsermod::_pwmPin[] PROGMEM = "PWM-pin";
|
|||||||
const char PWMFanUsermod::_temperature[] PROGMEM = "target-temp-C";
|
const char PWMFanUsermod::_temperature[] PROGMEM = "target-temp-C";
|
||||||
const char PWMFanUsermod::_tachoUpdateSec[] PROGMEM = "tacho-update-s";
|
const char PWMFanUsermod::_tachoUpdateSec[] PROGMEM = "tacho-update-s";
|
||||||
const char PWMFanUsermod::_minPWMValuePct[] PROGMEM = "min-PWM-percent";
|
const char PWMFanUsermod::_minPWMValuePct[] PROGMEM = "min-PWM-percent";
|
||||||
|
const char PWMFanUsermod::_maxPWMValuePct[] PROGMEM = "max-PWM-percent";
|
||||||
const char PWMFanUsermod::_IRQperRotation[] PROGMEM = "IRQs-per-rotation";
|
const char PWMFanUsermod::_IRQperRotation[] PROGMEM = "IRQs-per-rotation";
|
||||||
const char PWMFanUsermod::_speed[] PROGMEM = "speed";
|
const char PWMFanUsermod::_speed[] PROGMEM = "speed";
|
||||||
const char PWMFanUsermod::_lock[] PROGMEM = "lock";
|
const char PWMFanUsermod::_lock[] PROGMEM = "lock";
|
||||||
|
@ -24,6 +24,9 @@ Enables the inverted mode in which the background should be enabled and the digi
|
|||||||
### Colon-blinking
|
### Colon-blinking
|
||||||
Enables the blinking colon(s) if they are defined
|
Enables the blinking colon(s) if they are defined
|
||||||
|
|
||||||
|
### Leading-Zero
|
||||||
|
Shows the leading zero of the hour if it exists (i.e. shows `07` instead of `7`)
|
||||||
|
|
||||||
### enable-auto-brightness
|
### enable-auto-brightness
|
||||||
Enables the auto brightness feature. Can be used only when the usermod SN_Photoresistor is installed.
|
Enables the auto brightness feature. Can be used only when the usermod SN_Photoresistor is installed.
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ private:
|
|||||||
bool umSSDRDisplayTime = false;
|
bool umSSDRDisplayTime = false;
|
||||||
bool umSSDRInverted = false;
|
bool umSSDRInverted = false;
|
||||||
bool umSSDRColonblink = true;
|
bool umSSDRColonblink = true;
|
||||||
|
bool umSSDRLeadingZero = false;
|
||||||
bool umSSDREnableLDR = false;
|
bool umSSDREnableLDR = false;
|
||||||
String umSSDRHours = "";
|
String umSSDRHours = "";
|
||||||
String umSSDRMinutes = "";
|
String umSSDRMinutes = "";
|
||||||
@ -79,6 +80,7 @@ private:
|
|||||||
static const char _str_timeEnabled[];
|
static const char _str_timeEnabled[];
|
||||||
static const char _str_inverted[];
|
static const char _str_inverted[];
|
||||||
static const char _str_colonblink[];
|
static const char _str_colonblink[];
|
||||||
|
static const char _str_leadingZero[];
|
||||||
static const char _str_displayMask[];
|
static const char _str_displayMask[];
|
||||||
static const char _str_hours[];
|
static const char _str_hours[];
|
||||||
static const char _str_minutes[];
|
static const char _str_minutes[];
|
||||||
@ -105,15 +107,15 @@ private:
|
|||||||
switch (umSSDRDisplayMask[index]) {
|
switch (umSSDRDisplayMask[index]) {
|
||||||
case 'h':
|
case 'h':
|
||||||
timeVar = hourFormat12(localTime);
|
timeVar = hourFormat12(localTime);
|
||||||
_showElements(&umSSDRHours, timeVar, 0, 1);
|
_showElements(&umSSDRHours, timeVar, 0, !umSSDRLeadingZero);
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
timeVar = hour(localTime);
|
timeVar = hour(localTime);
|
||||||
_showElements(&umSSDRHours, timeVar, 0, 1);
|
_showElements(&umSSDRHours, timeVar, 0, !umSSDRLeadingZero);
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
timeVar = hour(localTime) + 1;
|
timeVar = hour(localTime) + 1;
|
||||||
_showElements(&umSSDRHours, timeVar, 0, 0);
|
_showElements(&umSSDRHours, timeVar, 0, !umSSDRLeadingZero);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
timeVar = minute(localTime);
|
timeVar = minute(localTime);
|
||||||
@ -309,6 +311,9 @@ private:
|
|||||||
if (_cmpIntSetting_P(topic, payload, _str_colonblink, &umSSDRColonblink)) {
|
if (_cmpIntSetting_P(topic, payload, _str_colonblink, &umSSDRColonblink)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (_cmpIntSetting_P(topic, payload, _str_leadingZero, &umSSDRLeadingZero)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (strcmp_P(topic, _str_displayMask) == 0) {
|
if (strcmp_P(topic, _str_displayMask) == 0) {
|
||||||
umSSDRDisplayMask = String(payload);
|
umSSDRDisplayMask = String(payload);
|
||||||
_publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask);
|
_publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask);
|
||||||
@ -323,6 +328,7 @@ private:
|
|||||||
_publishMQTTint_P(_str_ldrEnabled, umSSDREnableLDR);
|
_publishMQTTint_P(_str_ldrEnabled, umSSDREnableLDR);
|
||||||
_publishMQTTint_P(_str_inverted, umSSDRInverted);
|
_publishMQTTint_P(_str_inverted, umSSDRInverted);
|
||||||
_publishMQTTint_P(_str_colonblink, umSSDRColonblink);
|
_publishMQTTint_P(_str_colonblink, umSSDRColonblink);
|
||||||
|
_publishMQTTint_P(_str_leadingZero, umSSDRLeadingZero);
|
||||||
|
|
||||||
_publishMQTTstr_P(_str_hours, umSSDRHours);
|
_publishMQTTstr_P(_str_hours, umSSDRHours);
|
||||||
_publishMQTTstr_P(_str_minutes, umSSDRMinutes);
|
_publishMQTTstr_P(_str_minutes, umSSDRMinutes);
|
||||||
@ -347,6 +353,7 @@ private:
|
|||||||
ssdrObj[FPSTR(_str_ldrEnabled)] = umSSDREnableLDR;
|
ssdrObj[FPSTR(_str_ldrEnabled)] = umSSDREnableLDR;
|
||||||
ssdrObj[FPSTR(_str_inverted)] = umSSDRInverted;
|
ssdrObj[FPSTR(_str_inverted)] = umSSDRInverted;
|
||||||
ssdrObj[FPSTR(_str_colonblink)] = umSSDRColonblink;
|
ssdrObj[FPSTR(_str_colonblink)] = umSSDRColonblink;
|
||||||
|
ssdrObj[FPSTR(_str_leadingZero)] = umSSDRLeadingZero;
|
||||||
ssdrObj[FPSTR(_str_displayMask)] = umSSDRDisplayMask;
|
ssdrObj[FPSTR(_str_displayMask)] = umSSDRDisplayMask;
|
||||||
ssdrObj[FPSTR(_str_hours)] = umSSDRHours;
|
ssdrObj[FPSTR(_str_hours)] = umSSDRHours;
|
||||||
ssdrObj[FPSTR(_str_minutes)] = umSSDRMinutes;
|
ssdrObj[FPSTR(_str_minutes)] = umSSDRMinutes;
|
||||||
@ -425,6 +432,8 @@ public:
|
|||||||
invert.add(umSSDRInverted);
|
invert.add(umSSDRInverted);
|
||||||
JsonArray blink = user.createNestedArray("Blinking colon");
|
JsonArray blink = user.createNestedArray("Blinking colon");
|
||||||
blink.add(umSSDRColonblink);
|
blink.add(umSSDRColonblink);
|
||||||
|
JsonArray zero = user.createNestedArray("Show the hour leading zero");
|
||||||
|
zero.add(umSSDRLeadingZero);
|
||||||
JsonArray ldrEnable = user.createNestedArray("Auto Brightness enabled");
|
JsonArray ldrEnable = user.createNestedArray("Auto Brightness enabled");
|
||||||
ldrEnable.add(umSSDREnableLDR);
|
ldrEnable.add(umSSDREnableLDR);
|
||||||
|
|
||||||
@ -454,6 +463,7 @@ public:
|
|||||||
umSSDREnableLDR = ssdrObj[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR;
|
umSSDREnableLDR = ssdrObj[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR;
|
||||||
umSSDRInverted = ssdrObj[FPSTR(_str_inverted)] | umSSDRInverted;
|
umSSDRInverted = ssdrObj[FPSTR(_str_inverted)] | umSSDRInverted;
|
||||||
umSSDRColonblink = ssdrObj[FPSTR(_str_colonblink)] | umSSDRColonblink;
|
umSSDRColonblink = ssdrObj[FPSTR(_str_colonblink)] | umSSDRColonblink;
|
||||||
|
umSSDRLeadingZero = ssdrObj[FPSTR(_str_leadingZero)] | umSSDRLeadingZero;
|
||||||
umSSDRDisplayMask = ssdrObj[FPSTR(_str_displayMask)] | umSSDRDisplayMask;
|
umSSDRDisplayMask = ssdrObj[FPSTR(_str_displayMask)] | umSSDRDisplayMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,6 +526,7 @@ public:
|
|||||||
umSSDREnableLDR = (top[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR);
|
umSSDREnableLDR = (top[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR);
|
||||||
umSSDRInverted = (top[FPSTR(_str_inverted)] | umSSDRInverted);
|
umSSDRInverted = (top[FPSTR(_str_inverted)] | umSSDRInverted);
|
||||||
umSSDRColonblink = (top[FPSTR(_str_colonblink)] | umSSDRColonblink);
|
umSSDRColonblink = (top[FPSTR(_str_colonblink)] | umSSDRColonblink);
|
||||||
|
umSSDRLeadingZero = (top[FPSTR(_str_leadingZero)] | umSSDRLeadingZero);
|
||||||
|
|
||||||
umSSDRDisplayMask = top[FPSTR(_str_displayMask)] | umSSDRDisplayMask;
|
umSSDRDisplayMask = top[FPSTR(_str_displayMask)] | umSSDRDisplayMask;
|
||||||
umSSDRHours = top[FPSTR(_str_hours)] | umSSDRHours;
|
umSSDRHours = top[FPSTR(_str_hours)] | umSSDRHours;
|
||||||
@ -546,6 +557,7 @@ const char UsermodSSDR::_str_name[] PROGMEM = "UsermodSSDR";
|
|||||||
const char UsermodSSDR::_str_timeEnabled[] PROGMEM = "enabled";
|
const char UsermodSSDR::_str_timeEnabled[] PROGMEM = "enabled";
|
||||||
const char UsermodSSDR::_str_inverted[] PROGMEM = "inverted";
|
const char UsermodSSDR::_str_inverted[] PROGMEM = "inverted";
|
||||||
const char UsermodSSDR::_str_colonblink[] PROGMEM = "Colon-blinking";
|
const char UsermodSSDR::_str_colonblink[] PROGMEM = "Colon-blinking";
|
||||||
|
const char UsermodSSDR::_str_leadingZero[] PROGMEM = "Leading-Zero";
|
||||||
const char UsermodSSDR::_str_displayMask[] PROGMEM = "Display-Mask";
|
const char UsermodSSDR::_str_displayMask[] PROGMEM = "Display-Mask";
|
||||||
const char UsermodSSDR::_str_hours[] PROGMEM = "LED-Numbers-Hours";
|
const char UsermodSSDR::_str_hours[] PROGMEM = "LED-Numbers-Hours";
|
||||||
const char UsermodSSDR::_str_minutes[] PROGMEM = "LED-Numbers-Minutes";
|
const char UsermodSSDR::_str_minutes[] PROGMEM = "LED-Numbers-Minutes";
|
||||||
|
@ -177,11 +177,11 @@ uint16_t color_wipe(bool rev, bool useRandomColors) {
|
|||||||
SEGENV.step = 3;
|
SEGENV.step = 3;
|
||||||
}
|
}
|
||||||
if (SEGENV.step == 1) { //if flag set, change to new random color
|
if (SEGENV.step == 1) { //if flag set, change to new random color
|
||||||
SEGENV.aux1 = SEGMENT.get_random_wheel_index(SEGENV.aux0);
|
SEGENV.aux1 = get_random_wheel_index(SEGENV.aux0);
|
||||||
SEGENV.step = 2;
|
SEGENV.step = 2;
|
||||||
}
|
}
|
||||||
if (SEGENV.step == 3) {
|
if (SEGENV.step == 3) {
|
||||||
SEGENV.aux0 = SEGMENT.get_random_wheel_index(SEGENV.aux1);
|
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux1);
|
||||||
SEGENV.step = 0;
|
SEGENV.step = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ uint16_t mode_random_color(void) {
|
|||||||
if (it != SEGENV.step) //new color
|
if (it != SEGENV.step) //new color
|
||||||
{
|
{
|
||||||
SEGENV.aux1 = SEGENV.aux0;
|
SEGENV.aux1 = SEGENV.aux0;
|
||||||
SEGENV.aux0 = SEGMENT.get_random_wheel_index(SEGENV.aux0); //aux0 will store our random color wheel index
|
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0); //aux0 will store our random color wheel index
|
||||||
SEGENV.step = it;
|
SEGENV.step = it;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,7 +816,7 @@ uint16_t chase(uint32_t color1, uint32_t color2, uint32_t color3, bool do_palett
|
|||||||
if (a < SEGENV.step) //we hit the start again, choose new color for Chase random
|
if (a < SEGENV.step) //we hit the start again, choose new color for Chase random
|
||||||
{
|
{
|
||||||
SEGENV.aux1 = SEGENV.aux0; //store previous random color
|
SEGENV.aux1 = SEGENV.aux0; //store previous random color
|
||||||
SEGENV.aux0 = SEGMENT.get_random_wheel_index(SEGENV.aux0);
|
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0);
|
||||||
}
|
}
|
||||||
color1 = SEGMENT.color_wheel(SEGENV.aux0);
|
color1 = SEGMENT.color_wheel(SEGENV.aux0);
|
||||||
}
|
}
|
||||||
@ -1056,7 +1056,7 @@ uint16_t mode_chase_flash_random(void) {
|
|||||||
SEGENV.aux1 = (SEGENV.aux1 + 1) % SEGLEN;
|
SEGENV.aux1 = (SEGENV.aux1 + 1) % SEGLEN;
|
||||||
|
|
||||||
if (SEGENV.aux1 == 0) {
|
if (SEGENV.aux1 == 0) {
|
||||||
SEGENV.aux0 = SEGMENT.get_random_wheel_index(SEGENV.aux0);
|
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return delay;
|
return delay;
|
||||||
@ -2590,14 +2590,14 @@ uint16_t mode_twinklefox()
|
|||||||
{
|
{
|
||||||
return twinklefox_base(false);
|
return twinklefox_base(false);
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate,,,,Cool;;!";
|
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate,,,,Cool;!,!;!";
|
||||||
|
|
||||||
|
|
||||||
uint16_t mode_twinklecat()
|
uint16_t mode_twinklecat()
|
||||||
{
|
{
|
||||||
return twinklefox_base(true);
|
return twinklefox_base(true);
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate,,,,Cool;;!";
|
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate,,,,Cool;!,!;!";
|
||||||
|
|
||||||
|
|
||||||
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
||||||
@ -5946,6 +5946,8 @@ uint16_t mode_2Dscrollingtext(void) {
|
|||||||
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d") :PSTR("%d/%d"), month(localTime), day(localTime));
|
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d") :PSTR("%d/%d"), month(localTime), day(localTime));
|
||||||
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s") :PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s") :PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
||||||
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d") :PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d") :PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
||||||
|
else if (!strncmp_P(text,PSTR("#HH"),3)) sprintf_P(text, zero?PSTR("%02d") :PSTR("%d"), AmPmHour);
|
||||||
|
else if (!strncmp_P(text,PSTR("#MM"),3)) sprintf_P(text, zero?PSTR("%02d") :PSTR("%d"), minute(localTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int numberOfLetters = strlen(text);
|
const int numberOfLetters = strlen(text);
|
||||||
|
51
wled00/FX.h
51
wled00/FX.h
@ -109,20 +109,15 @@
|
|||||||
#define PINK (uint32_t)0xFF1493
|
#define PINK (uint32_t)0xFF1493
|
||||||
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
|
#define ULTRAWHITE (uint32_t)0xFFFFFFFF
|
||||||
#define DARKSLATEGRAY (uint32_t)0x2F4F4F
|
#define DARKSLATEGRAY (uint32_t)0x2F4F4F
|
||||||
#define DARKSLATEGREY (uint32_t)0x2F4F4F
|
#define DARKSLATEGREY DARKSLATEGRAY
|
||||||
|
|
||||||
// options
|
// segment options
|
||||||
// bit 7: segment is in transition mode
|
|
||||||
// bits 4-6: TBD
|
|
||||||
// bit 3: mirror effect within segment
|
|
||||||
// bit 2: segment is on
|
|
||||||
// bit 1: reverse segment
|
|
||||||
// bit 0: segment is selected
|
|
||||||
#define NO_OPTIONS (uint16_t)0x0000
|
#define NO_OPTIONS (uint16_t)0x0000
|
||||||
#define TRANSPOSED (uint16_t)0x0400 // rotated 90deg & reversed
|
#define TRANSPOSED (uint16_t)0x0100 // rotated 90deg & reversed
|
||||||
#define REVERSE_Y_2D (uint16_t)0x0200
|
#define MIRROR_Y_2D (uint16_t)0x0080
|
||||||
#define MIRROR_Y_2D (uint16_t)0x0100
|
#define REVERSE_Y_2D (uint16_t)0x0040
|
||||||
#define TRANSITIONAL (uint16_t)0x0080
|
#define RESET_REQ (uint16_t)0x0020
|
||||||
|
#define FROZEN (uint16_t)0x0010
|
||||||
#define MIRROR (uint16_t)0x0008
|
#define MIRROR (uint16_t)0x0008
|
||||||
#define SEGMENT_ON (uint16_t)0x0004
|
#define SEGMENT_ON (uint16_t)0x0004
|
||||||
#define REVERSE (uint16_t)0x0002
|
#define REVERSE (uint16_t)0x0002
|
||||||
@ -348,12 +343,11 @@ typedef struct Segment {
|
|||||||
bool mirror : 1; // 3 : mirrored
|
bool mirror : 1; // 3 : mirrored
|
||||||
bool freeze : 1; // 4 : paused/frozen
|
bool freeze : 1; // 4 : paused/frozen
|
||||||
bool reset : 1; // 5 : indicates that Segment runtime requires reset
|
bool reset : 1; // 5 : indicates that Segment runtime requires reset
|
||||||
bool transitional: 1; // 6 : transitional (there is transition occuring)
|
bool reverse_y : 1; // 6 : reversed Y (2D)
|
||||||
bool reverse_y : 1; // 7 : reversed Y (2D)
|
bool mirror_y : 1; // 7 : mirrored Y (2D)
|
||||||
bool mirror_y : 1; // 8 : mirrored Y (2D)
|
bool transpose : 1; // 8 : transposed (2D, swapped X & Y)
|
||||||
bool transpose : 1; // 9 : transposed (2D, swapped X & Y)
|
uint8_t map1D2D : 3; // 9-11 : mapping for 1D effect on 2D (0-use as strip, 1-expand vertically, 2-circular/arc, 3-rectangular/corner, ...)
|
||||||
uint8_t map1D2D : 3; // 10-12 : mapping for 1D effect on 2D (0-use as strip, 1-expand vertically, 2-circular/arc, 3-rectangular/corner, ...)
|
uint8_t soundSim : 2; // 12-13 : 0-3 sound simulation types ("soft" & "hard" or "on"/"off")
|
||||||
uint8_t soundSim : 1; // 13 : 0-1 sound simulation types ("soft" & "hard" or "on"/"off")
|
|
||||||
uint8_t set : 2; // 14-15 : 0-3 UI segment sets/groups
|
uint8_t set : 2; // 14-15 : 0-3 UI segment sets/groups
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -484,7 +478,6 @@ typedef struct Segment {
|
|||||||
_dataLen(0),
|
_dataLen(0),
|
||||||
_t(nullptr)
|
_t(nullptr)
|
||||||
{
|
{
|
||||||
//refreshLightCapabilities();
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
//Serial.printf("-- Creating segment: %p\n", this);
|
//Serial.printf("-- Creating segment: %p\n", this);
|
||||||
#endif
|
#endif
|
||||||
@ -519,6 +512,7 @@ typedef struct Segment {
|
|||||||
|
|
||||||
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
|
inline bool getOption(uint8_t n) const { return ((options >> n) & 0x01); }
|
||||||
inline bool isSelected(void) const { return selected; }
|
inline bool isSelected(void) const { return selected; }
|
||||||
|
inline bool isInTransition(void) const { return _t != nullptr; }
|
||||||
inline bool isActive(void) const { return stop > start; }
|
inline bool isActive(void) const { return stop > start; }
|
||||||
inline bool is2D(void) const { return (width()>1 && height()>1); }
|
inline bool is2D(void) const { return (width()>1 && height()>1); }
|
||||||
inline bool hasRGB(void) const { return _isRGB; }
|
inline bool hasRGB(void) const { return _isRGB; }
|
||||||
@ -569,15 +563,16 @@ typedef struct Segment {
|
|||||||
void restoreSegenv(tmpsegd_t &tmpSegD);
|
void restoreSegenv(tmpsegd_t &tmpSegD);
|
||||||
#endif
|
#endif
|
||||||
uint16_t progress(void); //transition progression between 0-65535
|
uint16_t progress(void); //transition progression between 0-65535
|
||||||
uint8_t currentBri(uint8_t briNew, bool useCct = false);
|
uint8_t currentBri(bool useCct = false);
|
||||||
uint8_t currentMode(uint8_t modeNew);
|
uint8_t currentMode(void);
|
||||||
uint32_t currentColor(uint8_t slot, uint32_t colorNew);
|
uint32_t currentColor(uint8_t slot);
|
||||||
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
|
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
|
||||||
CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID);
|
CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID);
|
||||||
|
|
||||||
// 1D strip
|
// 1D strip
|
||||||
uint16_t virtualLength(void) const;
|
uint16_t virtualLength(void) const;
|
||||||
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
|
void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color
|
||||||
|
void setPixelColor(unsigned n, uint32_t c) { setPixelColor(int(n), c); }
|
||||||
void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline
|
void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline
|
||||||
void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
|
void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
|
||||||
void setPixelColor(float i, uint32_t c, bool aa = true);
|
void setPixelColor(float i, uint32_t c, bool aa = true);
|
||||||
@ -595,7 +590,6 @@ typedef struct Segment {
|
|||||||
void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
|
void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
|
||||||
void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
|
void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
|
||||||
void fadePixelColor(uint16_t n, uint8_t fade);
|
void fadePixelColor(uint16_t n, uint8_t fade);
|
||||||
uint8_t get_random_wheel_index(uint8_t pos);
|
|
||||||
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
|
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
|
||||||
uint32_t color_wheel(uint8_t pos);
|
uint32_t color_wheel(uint8_t pos);
|
||||||
|
|
||||||
@ -606,6 +600,7 @@ typedef struct Segment {
|
|||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment
|
uint16_t XY(uint16_t x, uint16_t y); // support function to get relative index within segment
|
||||||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
||||||
|
void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
|
||||||
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
|
void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
|
||||||
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
|
void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } // automatically inline
|
||||||
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
|
void setPixelColorXY(float x, float y, uint32_t c, bool aa = true);
|
||||||
@ -881,16 +876,14 @@ class WS2812FX { // 96 bytes
|
|||||||
std::vector<Panel> panel;
|
std::vector<Panel> panel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void setUpMatrix();
|
||||||
setUpMatrix(),
|
|
||||||
setPixelColorXY(int x, int y, uint32_t c);
|
|
||||||
|
|
||||||
// outsmart the compiler :) by correctly overloading
|
// outsmart the compiler :) by correctly overloading
|
||||||
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline
|
inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(y * Segment::maxWidth + x, c); }
|
||||||
|
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
|
||||||
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||||
|
|
||||||
uint32_t
|
inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(isMatrix ? y * Segment::maxWidth + x : x);}
|
||||||
getPixelColorXY(uint16_t, uint16_t);
|
|
||||||
|
|
||||||
// end 2D support
|
// end 2D support
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ void WS2812FX::setUpMatrix() {
|
|||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
DEBUG_PRINT(F("Matrix ledmap:"));
|
DEBUG_PRINT(F("Matrix ledmap:"));
|
||||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
for (unsigned i=0; i<customMappingSize; i++) {
|
||||||
if (!(i%Segment::maxWidth)) DEBUG_PRINTLN();
|
if (!(i%Segment::maxWidth)) DEBUG_PRINTLN();
|
||||||
DEBUG_PRINTF("%4d,", customMappingTable[i]);
|
DEBUG_PRINTF("%4d,", customMappingTable[i]);
|
||||||
}
|
}
|
||||||
@ -155,31 +155,6 @@ void WS2812FX::setUpMatrix() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// absolute matrix version of setPixelColor()
|
|
||||||
void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
|
||||||
{
|
|
||||||
#ifndef WLED_DISABLE_2D
|
|
||||||
if (!isMatrix) return; // not a matrix set-up
|
|
||||||
uint16_t index = y * Segment::maxWidth + x;
|
|
||||||
#else
|
|
||||||
uint16_t index = x;
|
|
||||||
#endif
|
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
if (index >= _length) return;
|
|
||||||
busses.setPixelColor(index, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
|
||||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
|
||||||
#ifndef WLED_DISABLE_2D
|
|
||||||
uint16_t index = (y * Segment::maxWidth + x);
|
|
||||||
#else
|
|
||||||
uint16_t index = x;
|
|
||||||
#endif
|
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
if (index >= _length) return 0;
|
|
||||||
return busses.getPixelColor(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Segment:: routines
|
// Segment:: routines
|
||||||
@ -188,18 +163,19 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
|||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
|
|
||||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||||
uint16_t /*IRAM_ATTR*/ Segment::XY(uint16_t x, uint16_t y) {
|
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y)
|
||||||
|
{
|
||||||
uint16_t width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
|
uint16_t width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
|
||||||
uint16_t height = virtualHeight(); // segment height in logical pixels (is always >= 1)
|
uint16_t height = virtualHeight(); // segment height in logical pixels (is always >= 1)
|
||||||
return isActive() ? (x%width) + (y%height) * width : 0;
|
return isActive() ? (x%width) + (y%height) * width : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||||
{
|
{
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||||
|
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri();
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
byte g = scale8(G(col), _bri_t);
|
||||||
@ -310,32 +286,17 @@ void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t
|
|||||||
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
void Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||||
uint32_t col = getPixelColorXY(x,y);
|
setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color, fast));
|
||||||
uint8_t r = R(col);
|
|
||||||
uint8_t g = G(col);
|
|
||||||
uint8_t b = B(col);
|
|
||||||
uint8_t w = W(col);
|
|
||||||
if (fast) {
|
|
||||||
r = qadd8(r, R(color));
|
|
||||||
g = qadd8(g, G(color));
|
|
||||||
b = qadd8(b, B(color));
|
|
||||||
w = qadd8(w, W(color));
|
|
||||||
col = RGBW32(r,g,b,w);
|
|
||||||
} else {
|
|
||||||
col = color_add(col, color);
|
|
||||||
}
|
|
||||||
setPixelColorXY(x, y, col);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade);
|
setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true));
|
||||||
setPixelColorXY(x, y, pix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@ -344,7 +305,7 @@ void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
|||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint_fast16_t x = 0; x < cols; x++) {
|
for (unsigned x = 0; x < cols; x++) {
|
||||||
CRGB cur = getPixelColorXY(x, row);
|
CRGB cur = getPixelColorXY(x, row);
|
||||||
CRGB before = cur; // remember color before blur
|
CRGB before = cur; // remember color before blur
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
@ -363,7 +324,7 @@ void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
|||||||
|
|
||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
@ -372,7 +333,7 @@ void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
|||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint_fast16_t y = 0; y < rows; y++) {
|
for (unsigned y = 0; y < rows; y++) {
|
||||||
CRGB cur = getPixelColorXY(col, y);
|
CRGB cur = getPixelColorXY(col, y);
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
CRGB before = cur; // remember color before blur
|
CRGB before = cur; // remember color before blur
|
||||||
@ -391,7 +352,7 @@ void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
|||||||
|
|
||||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||||
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
const uint16_t dim1 = vertical ? rows : cols;
|
const uint16_t dim1 = vertical ? rows : cols;
|
||||||
@ -401,7 +362,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
const float keep = 3.f - 2.f*seep;
|
const float keep = 3.f - 2.f*seep;
|
||||||
// 1D box blur
|
// 1D box blur
|
||||||
CRGB tmp[dim1];
|
CRGB tmp[dim1];
|
||||||
for (uint16_t j = 0; j < dim1; j++) {
|
for (int j = 0; j < dim1; j++) {
|
||||||
uint16_t x = vertical ? i : j;
|
uint16_t x = vertical ? i : j;
|
||||||
uint16_t y = vertical ? j : i;
|
uint16_t y = vertical ? j : i;
|
||||||
int16_t xp = vertical ? x : x-1; // "signed" to prevent underflow
|
int16_t xp = vertical ? x : x-1; // "signed" to prevent underflow
|
||||||
@ -417,7 +378,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
b = (curr.b*keep + (prev.b + next.b)*seep) / 3;
|
b = (curr.b*keep + (prev.b + next.b)*seep) / 3;
|
||||||
tmp[j] = CRGB(r,g,b);
|
tmp[j] = CRGB(r,g,b);
|
||||||
}
|
}
|
||||||
for (uint16_t j = 0; j < dim1; j++) {
|
for (int j = 0; j < dim1; j++) {
|
||||||
uint16_t x = vertical ? i : j;
|
uint16_t x = vertical ? i : j;
|
||||||
uint16_t y = vertical ? j : i;
|
uint16_t y = vertical ? j : i;
|
||||||
setPixelColorXY(x, y, tmp[j]);
|
setPixelColorXY(x, y, tmp[j]);
|
||||||
@ -440,7 +401,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
|
|
||||||
void Segment::blur1d(fract8 blur_amount) {
|
void Segment::blur1d(fract8 blur_amount) {
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
for (uint16_t y = 0; y < rows; y++) blurRow(y, blur_amount);
|
for (unsigned y = 0; y < rows; y++) blurRow(y, blur_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::moveX(int8_t delta, bool wrap) {
|
void Segment::moveX(int8_t delta, bool wrap) {
|
||||||
@ -498,7 +459,7 @@ void Segment::move(uint8_t dir, uint8_t delta, bool wrap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || radius == 0) return; // not active
|
||||||
// Bresenham’s Algorithm
|
// Bresenham’s Algorithm
|
||||||
int d = 3 - (2*radius);
|
int d = 3 - (2*radius);
|
||||||
int y = radius, x = 0;
|
int y = radius, x = 0;
|
||||||
@ -523,7 +484,7 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
|
|
||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || radius == 0) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
for (int16_t y = -radius; y <= radius; y++) {
|
for (int16_t y = -radius; y <= radius; y++) {
|
||||||
@ -540,7 +501,7 @@ void Segment::nscale8(uint8_t scale) {
|
|||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,25 +89,19 @@ bool Segment::_modeBlend = false;
|
|||||||
Segment::Segment(const Segment &orig) {
|
Segment::Segment(const Segment &orig) {
|
||||||
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
transitional = false; // copied segment cannot be in transition
|
_t = nullptr; // copied segment cannot be in transition
|
||||||
name = nullptr;
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } else { name = nullptr; }
|
||||||
data = nullptr;
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } else { data = nullptr; _dataLen = 0; }
|
||||||
_dataLen = 0;
|
|
||||||
_t = nullptr;
|
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
|
||||||
//if (orig._t) { _t = new Transition(orig._t->_dur); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
Segment::Segment(Segment &&orig) noexcept {
|
Segment::Segment(Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.transitional = false; // old segment cannot be in transition any more
|
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
orig._t = nullptr;
|
orig._t = nullptr; // old segment cannot be in transition any more
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy assignment
|
// copy assignment
|
||||||
@ -115,27 +109,23 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
//DEBUG_PRINTF("-- Copying segment: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Copying segment: %p -> %p\n", &orig, this);
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
// clean destination
|
// clean destination
|
||||||
transitional = false; // copied segment cannot be in transition
|
if (name) { delete[] name; name = nullptr; }
|
||||||
if (name) delete[] name;
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
if (_t) {
|
if (_t) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
||||||
#endif
|
#endif
|
||||||
delete _t;
|
delete _t;
|
||||||
|
_t = nullptr; // copied segment cannot be in transition
|
||||||
}
|
}
|
||||||
deallocateData();
|
deallocateData();
|
||||||
// copy source
|
// copy source
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
transitional = false;
|
|
||||||
// erase pointers to allocated data
|
// erase pointers to allocated data
|
||||||
name = nullptr;
|
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
_t = nullptr;
|
|
||||||
// copy source data
|
// copy source data
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
//if (orig._t) { _t = new Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); }
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -144,9 +134,7 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
Segment& Segment::operator= (Segment &&orig) noexcept {
|
Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
transitional = false; // just temporary
|
|
||||||
if (name) { delete[] name; name = nullptr; } // free old name
|
if (name) { delete[] name; name = nullptr; } // free old name
|
||||||
deallocateData(); // free old runtime data
|
|
||||||
if (_t) {
|
if (_t) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
||||||
@ -154,12 +142,12 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
|||||||
delete _t;
|
delete _t;
|
||||||
_t = nullptr;
|
_t = nullptr;
|
||||||
}
|
}
|
||||||
|
deallocateData(); // free old runtime data
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.transitional = false; // old segment cannot be in transition
|
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
orig._t = nullptr;
|
orig._t = nullptr; // old segment cannot be in transition
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -237,7 +225,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
|||||||
switch (pal) {
|
switch (pal) {
|
||||||
case 0: //default palette. Exceptions for specific effects above
|
case 0: //default palette. Exceptions for specific effects above
|
||||||
targetPalette = PartyColors_p; break;
|
targetPalette = PartyColors_p; break;
|
||||||
case 1: {//periodically replace palette with a random one. Transition palette change in 500ms
|
case 1: {//periodically replace palette with a random one
|
||||||
unsigned long timeSinceLastChange = millis() - _lastPaletteChange;
|
unsigned long timeSinceLastChange = millis() - _lastPaletteChange;
|
||||||
if (timeSinceLastChange > randomPaletteChangeTime * 1000U) {
|
if (timeSinceLastChange > randomPaletteChangeTime * 1000U) {
|
||||||
_randomPalette = _newRandomPalette;
|
_randomPalette = _newRandomPalette;
|
||||||
@ -301,26 +289,24 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::startTransition(uint16_t dur) {
|
void Segment::startTransition(uint16_t dur) {
|
||||||
if (!dur) {
|
if (dur == 0) {
|
||||||
if (_t) _t->_dur = dur; // this will stop transition in next handleTransisiton()
|
if (isInTransition()) _t->_dur = dur; // this will stop transition in next handleTransisiton()
|
||||||
else transitional = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (transitional && _t) return; // already in transition no need to store anything
|
if (isInTransition()) return; // already in transition no need to store anything
|
||||||
|
|
||||||
// starting a transition has to occur before change so we get current values 1st
|
// starting a transition has to occur before change so we get current values 1st
|
||||||
_t = new Transition(dur); // no previous transition running
|
_t = new Transition(dur); // no previous transition running
|
||||||
if (!_t) return; // failed to allocate data
|
if (!_t) return; // failed to allocate data
|
||||||
|
|
||||||
//DEBUG_PRINTF("-- Started transition: %p\n", this);
|
//DEBUG_PRINTF("-- Started transition: %p\n", this);
|
||||||
CRGBPalette16 _palT = CRGBPalette16(DEFAULT_COLOR); loadPalette(_palT, palette);
|
loadPalette(_t->_palT, palette);
|
||||||
_t->_palT = _palT;
|
|
||||||
_t->_briT = on ? opacity : 0;
|
_t->_briT = on ? opacity : 0;
|
||||||
_t->_cctT = cct;
|
_t->_cctT = cct;
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
|
if (modeBlending) {
|
||||||
swapSegenv(_t->_segT);
|
swapSegenv(_t->_segT);
|
||||||
_t->_modeT = mode;
|
_t->_modeT = mode;
|
||||||
_t->_segT._optionsT |= 0b0000000001000000; // mark old segment transitional
|
|
||||||
_t->_segT._dataLenT = 0;
|
_t->_segT._dataLenT = 0;
|
||||||
_t->_segT._dataT = nullptr;
|
_t->_segT._dataT = nullptr;
|
||||||
if (_dataLen > 0 && data) {
|
if (_dataLen > 0 && data) {
|
||||||
@ -331,17 +317,17 @@ void Segment::startTransition(uint16_t dur) {
|
|||||||
_t->_segT._dataLenT = _dataLen;
|
_t->_segT._dataLenT = _dataLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (size_t i=0; i<NUM_COLORS; i++) _t->_segT._colorT[i] = colors[i];
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = colors[i];
|
for (size_t i=0; i<NUM_COLORS; i++) _t->_colorT[i] = colors[i];
|
||||||
#endif
|
#endif
|
||||||
transitional = true; // setOption(SEG_OPTION_TRANSITIONAL, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::stopTransition() {
|
void Segment::stopTransition() {
|
||||||
if (!transitional) return;
|
|
||||||
transitional = false; // finish transitioning segment
|
|
||||||
//DEBUG_PRINTF("-- Stopping transition: %p\n", this);
|
//DEBUG_PRINTF("-- Stopping transition: %p\n", this);
|
||||||
if (_t) {
|
if (isInTransition()) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
||||||
//DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT);
|
//DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT);
|
||||||
@ -356,14 +342,13 @@ void Segment::stopTransition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::handleTransition() {
|
void Segment::handleTransition() {
|
||||||
if (!transitional) return;
|
|
||||||
uint16_t _progress = progress();
|
uint16_t _progress = progress();
|
||||||
if (_progress == 0xFFFFU) stopTransition();
|
if (_progress == 0xFFFFU) stopTransition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// transition progression between 0-65535
|
// transition progression between 0-65535
|
||||||
uint16_t Segment::progress() {
|
uint16_t Segment::progress() {
|
||||||
if (transitional && _t) {
|
if (isInTransition()) {
|
||||||
unsigned long timeNow = millis();
|
unsigned long timeNow = millis();
|
||||||
if (_t->_dur > 0 && timeNow - _t->_start < _t->_dur) return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
if (_t->_dur > 0 && timeNow - _t->_start < _t->_dur) return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||||
}
|
}
|
||||||
@ -420,8 +405,8 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
|
|||||||
_t->_segT._stepT = step;
|
_t->_segT._stepT = step;
|
||||||
_t->_segT._callT = call;
|
_t->_segT._callT = call;
|
||||||
//if (_t->_segT._dataT != data) DEBUG_PRINTF("--- data re-allocated: (%p) %p -> %p\n", this, _t->_segT._dataT, data);
|
//if (_t->_segT._dataT != data) DEBUG_PRINTF("--- data re-allocated: (%p) %p -> %p\n", this, _t->_segT._dataT, data);
|
||||||
_t->_segT._dataT = data; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
_t->_segT._dataT = data;
|
||||||
_t->_segT._dataLenT = _dataLen; // sometimes memory gets re-allocated (!! INVESTIGATE WHY !!)
|
_t->_segT._dataLenT = _dataLen;
|
||||||
}
|
}
|
||||||
options = tmpSeg._optionsT;
|
options = tmpSeg._optionsT;
|
||||||
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg._colorT[i];
|
for (size_t i=0; i<NUM_COLORS; i++) colors[i] = tmpSeg._colorT[i];
|
||||||
@ -443,39 +428,40 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t Segment::currentBri(uint8_t briNew, bool useCct) {
|
uint8_t Segment::currentBri(bool useCct) {
|
||||||
uint32_t prog = progress();
|
uint32_t prog = progress();
|
||||||
if (prog < 0xFFFFU) {
|
if (prog < 0xFFFFU) {
|
||||||
if (useCct) return ((briNew * prog) + _t->_cctT * (0xFFFFU - prog)) >> 16;
|
uint32_t curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
|
||||||
else return ((briNew * prog) + _t->_briT * (0xFFFFU - prog)) >> 16;
|
curBri += (useCct ? _t->_cctT : (on ? _t->_briT : 0)) * (0xFFFFU - prog);
|
||||||
|
return curBri / 0xFFFFU;
|
||||||
}
|
}
|
||||||
return briNew;
|
return (useCct ? cct : (on ? opacity : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Segment::currentMode(uint8_t newMode) {
|
uint8_t Segment::currentMode() {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
uint16_t prog = progress(); // implicit check for transitional & _t in progress()
|
uint16_t prog = progress();
|
||||||
if (prog < 0xFFFFU) return _t->_modeT;
|
if (modeBlending && prog < 0xFFFFU) return _t->_modeT;
|
||||||
#endif
|
#endif
|
||||||
return newMode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Segment::currentColor(uint8_t slot, uint32_t colorNew) {
|
uint32_t Segment::currentColor(uint8_t slot) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
return transitional && _t ? color_blend(_t->_segT._colorT[slot], colorNew, progress(), true) : colorNew;
|
return isInTransition() ? color_blend(_t->_segT._colorT[slot], colors[slot], progress(), true) : colors[slot];
|
||||||
#else
|
#else
|
||||||
return transitional && _t ? color_blend(_t->_colorT[slot], colorNew, progress(), true) : colorNew;
|
return isInTransition() ? color_blend(_t->_colorT[slot], colors[slot], progress(), true) : colors[slot];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
CRGBPalette16 &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||||
loadPalette(targetPalette, pal);
|
loadPalette(targetPalette, pal);
|
||||||
if (progress() < 0xFFFFU) {
|
uint16_t prog = progress();
|
||||||
|
if (strip.paletteFade && prog < 0xFFFFU) {
|
||||||
// blend palettes
|
// blend palettes
|
||||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||||
// minimum blend time is 100ms maximum is 65535ms
|
// minimum blend time is 100ms maximum is 65535ms
|
||||||
unsigned long timeMS = millis() - _t->_start;
|
uint16_t noOfBlends = ((255U * prog) / 0xFFFFU) - _t->_prevPaletteBlends;
|
||||||
uint16_t noOfBlends = (255U * timeMS / _t->_dur) - _t->_prevPaletteBlends;
|
|
||||||
for (int i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
for (int i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
||||||
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
||||||
}
|
}
|
||||||
@ -500,6 +486,8 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
|
|||||||
&& (!grp || (grouping == grp && spacing == spc))
|
&& (!grp || (grouping == grp && spacing == spc))
|
||||||
&& (ofs == UINT16_MAX || ofs == offset)) return;
|
&& (ofs == UINT16_MAX || ofs == offset)) return;
|
||||||
|
|
||||||
|
stateChanged = true; // send UDP/WS broadcast
|
||||||
|
|
||||||
if (stop) fill(BLACK); // turn old segment range off (clears pixels if changing spacing)
|
if (stop) fill(BLACK); // turn old segment range off (clears pixels if changing spacing)
|
||||||
if (grp) { // prevent assignment of 0
|
if (grp) { // prevent assignment of 0
|
||||||
grouping = grp;
|
grouping = grp;
|
||||||
@ -510,6 +498,10 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t
|
|||||||
}
|
}
|
||||||
if (ofs < UINT16_MAX) offset = ofs;
|
if (ofs < UINT16_MAX) offset = ofs;
|
||||||
|
|
||||||
|
DEBUG_PRINT(F("setUp segment: ")); DEBUG_PRINT(i1);
|
||||||
|
DEBUG_PRINT(','); DEBUG_PRINT(i2);
|
||||||
|
DEBUG_PRINT(F(" -> ")); DEBUG_PRINT(i1Y);
|
||||||
|
DEBUG_PRINT(','); DEBUG_PRINTLN(i2Y);
|
||||||
markForReset();
|
markForReset();
|
||||||
if (boundsUnchanged) return;
|
if (boundsUnchanged) return;
|
||||||
|
|
||||||
@ -564,7 +556,6 @@ void Segment::setCCT(uint16_t k) {
|
|||||||
void Segment::setOpacity(uint8_t o) {
|
void Segment::setOpacity(uint8_t o) {
|
||||||
if (opacity == o) return;
|
if (opacity == o) return;
|
||||||
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
||||||
DEBUG_PRINT(F("-- Setting opacity: ")); DEBUG_PRINTLN(o);
|
|
||||||
opacity = o;
|
opacity = o;
|
||||||
stateChanged = true; // send UDP/WS broadcast
|
stateChanged = true; // send UDP/WS broadcast
|
||||||
}
|
}
|
||||||
@ -574,14 +565,16 @@ void Segment::setOption(uint8_t n, bool val) {
|
|||||||
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
|
if (fadeTransition && n == SEG_OPTION_ON && val != prevOn) startTransition(strip.getTransition()); // start transition prior to change
|
||||||
if (val) options |= 0x01 << n;
|
if (val) options |= 0x01 << n;
|
||||||
else options &= ~(0x01 << n);
|
else options &= ~(0x01 << n);
|
||||||
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET || n == SEG_OPTION_TRANSITIONAL)) stateChanged = true; // send UDP/WS broadcast
|
if (!(n == SEG_OPTION_SELECTED || n == SEG_OPTION_RESET)) stateChanged = true; // send UDP/WS broadcast
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
||||||
// if we have a valid mode & is not reserved
|
// if we have a valid mode & is not reserved
|
||||||
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
if (fx < strip.getModeCount() && strncmp_P("RSVD", strip.getModeData(fx), 4)) {
|
||||||
if (fx != mode) {
|
if (fx != mode) {
|
||||||
if (fadeTransition) startTransition(strip.getTransition()); // set effect transitions
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
|
if (modeBlending) startTransition(strip.getTransition()); // set effect transitions
|
||||||
|
#endif
|
||||||
mode = fx;
|
mode = fx;
|
||||||
// load default values from effect string
|
// load default values from effect string
|
||||||
if (loadDefaults) {
|
if (loadDefaults) {
|
||||||
@ -743,7 +736,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t len = length();
|
uint16_t len = length();
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri();
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
byte g = scale8(G(col), _bri_t);
|
||||||
@ -877,10 +870,11 @@ uint8_t Segment::differs(Segment& b) const {
|
|||||||
if (startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
|
if (startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
|
||||||
if (stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
|
if (stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
|
||||||
//bit pattern: (msb first) set:2, sound:1, mapping:3, transposed, mirrorY, reverseY, [transitional, reset,] paused, mirrored, on, reverse, [selected]
|
//bit pattern: (msb first)
|
||||||
if ((options & 0b1111111110011110U) != (b.options & 0b1111111110011110U)) d |= SEG_DIFFERS_OPT;
|
// set:2, sound:2, mapping:3, transposed, mirrorY, reverseY, [reset,] paused, mirrored, on, reverse, [selected]
|
||||||
|
if ((options & 0b1111111111011110U) != (b.options & 0b1111111111011110U)) d |= SEG_DIFFERS_OPT;
|
||||||
if ((options & 0x0001U) != (b.options & 0x0001U)) d |= SEG_DIFFERS_SEL;
|
if ((options & 0x0001U) != (b.options & 0x0001U)) d |= SEG_DIFFERS_SEL;
|
||||||
for (uint8_t i = 0; i < NUM_COLORS; i++) if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
for (unsigned i = 0; i < NUM_COLORS; i++) if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@ -912,7 +906,7 @@ void Segment::refreshLightCapabilities() {
|
|||||||
segStopIdx = stop;
|
segStopIdx = stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
if (!bus->isOk()) continue;
|
if (!bus->isOk()) continue;
|
||||||
@ -942,7 +936,7 @@ void Segment::fill(uint32_t c) {
|
|||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
if (is2D()) setPixelColorXY(x, y, c);
|
if (is2D()) setPixelColorXY(x, y, c);
|
||||||
else setPixelColor(x, c);
|
else setPixelColor(x, c);
|
||||||
}
|
}
|
||||||
@ -956,27 +950,12 @@ void Segment::blendPixelColor(int n, uint32_t color, uint8_t blend) {
|
|||||||
// Adds the specified color with the existing pixel color perserving color balance.
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
void Segment::addPixelColor(int n, uint32_t color, bool fast) {
|
void Segment::addPixelColor(int n, uint32_t color, bool fast) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
uint32_t col = getPixelColor(n);
|
setPixelColor(n, color_add(getPixelColor(n), color, fast));
|
||||||
uint8_t r = R(col);
|
|
||||||
uint8_t g = G(col);
|
|
||||||
uint8_t b = B(col);
|
|
||||||
uint8_t w = W(col);
|
|
||||||
if (fast) {
|
|
||||||
r = qadd8(r, R(color));
|
|
||||||
g = qadd8(g, G(color));
|
|
||||||
b = qadd8(b, B(color));
|
|
||||||
w = qadd8(w, W(color));
|
|
||||||
col = RGBW32(r,g,b,w);
|
|
||||||
} else {
|
|
||||||
col = color_add(col, color);
|
|
||||||
}
|
|
||||||
setPixelColor(n, col);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
CRGB pix = CRGB(getPixelColor(n)).nscale8_video(fade);
|
setPixelColor(n, color_fade(getPixelColor(n), fade, true));
|
||||||
setPixelColor(n, pix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -996,7 +975,7 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
int g2 = G(color);
|
int g2 = G(color);
|
||||||
int b2 = B(color);
|
int b2 = B(color);
|
||||||
|
|
||||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
||||||
int w1 = W(color);
|
int w1 = W(color);
|
||||||
int r1 = R(color);
|
int r1 = R(color);
|
||||||
@ -1025,9 +1004,9 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
if (is2D()) setPixelColorXY(x, y, CRGB(getPixelColorXY(x,y)).nscale8(255-fadeBy));
|
if (is2D()) setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), 255-fadeBy));
|
||||||
else setPixelColor(x, CRGB(getPixelColor(x)).nscale8(255-fadeBy));
|
else setPixelColor(x, color_fade(getPixelColor(x), 255-fadeBy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,34 +1019,26 @@ void Segment::blur(uint8_t blur_amount)
|
|||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
// compatibility with 2D
|
// compatibility with 2D
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
for (uint_fast16_t i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
|
for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
|
||||||
for (uint_fast16_t k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
uint32_t carryover = BLACK;
|
||||||
uint_fast16_t vlength = virtualLength();
|
unsigned vlength = virtualLength();
|
||||||
for(uint_fast16_t i = 0; i < vlength; i++)
|
for (unsigned i = 0; i < vlength; i++) {
|
||||||
{
|
uint32_t cur = getPixelColor(i);
|
||||||
CRGB cur = CRGB(getPixelColor(i));
|
uint32_t part = color_fade(cur, seep);
|
||||||
CRGB part = cur;
|
cur = color_add(color_fade(cur, keep), carryover, true);
|
||||||
CRGB before = cur; // remember color before blur
|
if (i > 0) {
|
||||||
part.nscale8(seep);
|
|
||||||
cur.nscale8(keep);
|
|
||||||
cur += carryover;
|
|
||||||
if(i > 0) {
|
|
||||||
uint32_t c = getPixelColor(i-1);
|
uint32_t c = getPixelColor(i-1);
|
||||||
uint8_t r = R(c);
|
setPixelColor(i-1, color_add(c, part, true));
|
||||||
uint8_t g = G(c);
|
|
||||||
uint8_t b = B(c);
|
|
||||||
setPixelColor((uint16_t)(i-1), qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
|
|
||||||
}
|
}
|
||||||
if (before != cur) // optimization: only set pixel if color has changed
|
setPixelColor(i, cur);
|
||||||
setPixelColor((uint16_t)i,cur.red, cur.green, cur.blue);
|
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1080,7 +1051,7 @@ void Segment::blur(uint8_t blur_amount)
|
|||||||
uint32_t Segment::color_wheel(uint8_t pos) {
|
uint32_t Segment::color_wheel(uint8_t pos) {
|
||||||
if (palette) return color_from_palette(pos, false, true, 0);
|
if (palette) return color_from_palette(pos, false, true, 0);
|
||||||
pos = 255 - pos;
|
pos = 255 - pos;
|
||||||
if(pos < 85) {
|
if (pos < 85) {
|
||||||
return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
|
return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
|
||||||
} else if(pos < 170) {
|
} else if(pos < 170) {
|
||||||
pos -= 85;
|
pos -= 85;
|
||||||
@ -1091,21 +1062,6 @@ uint32_t Segment::color_wheel(uint8_t pos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
|
||||||
*/
|
|
||||||
uint8_t Segment::get_random_wheel_index(uint8_t pos) {
|
|
||||||
uint8_t r = 0, x = 0, y = 0, d = 0;
|
|
||||||
|
|
||||||
while(d < 42) {
|
|
||||||
r = random8();
|
|
||||||
x = abs(pos - r);
|
|
||||||
y = 255 - x;
|
|
||||||
d = MIN(x, y);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets a single color from the currently selected palette.
|
* Gets a single color from the currently selected palette.
|
||||||
* @param i Palette Index (if mapping is true, the full palette will be _virtualSegmentLength long, if false, 255). Will wrap around automatically.
|
* @param i Palette Index (if mapping is true, the full palette will be _virtualSegmentLength long, if false, 255). Will wrap around automatically.
|
||||||
@ -1119,20 +1075,20 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
|
|||||||
{
|
{
|
||||||
// default palette or no RGB support on segment
|
// default palette or no RGB support on segment
|
||||||
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
||||||
uint32_t color = currentColor(mcol, colors[mcol]);
|
uint32_t color = currentColor(mcol);
|
||||||
color = gamma32(color);
|
color = gamma32(color);
|
||||||
if (pbri == 255) return color;
|
if (pbri == 255) return color;
|
||||||
return RGBW32(scale8_video(R(color),pbri), scale8_video(G(color),pbri), scale8_video(B(color),pbri), scale8_video(W(color),pbri));
|
return color_fade(color, pbri, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t paletteIndex = i;
|
uint8_t paletteIndex = i;
|
||||||
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
|
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
|
||||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||||
CRGB fastled_col;
|
|
||||||
CRGBPalette16 curPal;
|
CRGBPalette16 curPal;
|
||||||
if (transitional && _t) curPal = _t->_palT;
|
curPal = currentPalette(curPal, palette);
|
||||||
else loadPalette(curPal, palette);
|
//if (isInTransition()) curPal = _t->_palT;
|
||||||
fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global
|
//else loadPalette(curPal, palette);
|
||||||
|
CRGB fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global
|
||||||
|
|
||||||
return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0);
|
return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0);
|
||||||
}
|
}
|
||||||
@ -1166,7 +1122,7 @@ void WS2812FX::finalizeInit(void)
|
|||||||
const uint8_t defNumBusses = ((sizeof defDataPins) / (sizeof defDataPins[0]));
|
const uint8_t defNumBusses = ((sizeof defDataPins) / (sizeof defDataPins[0]));
|
||||||
const uint8_t defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0]));
|
const uint8_t defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0]));
|
||||||
uint16_t prevLen = 0;
|
uint16_t prevLen = 0;
|
||||||
for (uint8_t i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
for (int i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) {
|
||||||
uint8_t defPin[] = {defDataPins[i]};
|
uint8_t defPin[] = {defDataPins[i]};
|
||||||
uint16_t start = prevLen;
|
uint16_t start = prevLen;
|
||||||
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
uint16_t count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
|
||||||
@ -1177,7 +1133,7 @@ void WS2812FX::finalizeInit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_length = 0;
|
_length = 0;
|
||||||
for (uint8_t i=0; i<busses.getNumBusses(); i++) {
|
for (int i=0; i<busses.getNumBusses(); i++) {
|
||||||
Bus *bus = busses.getBus(i);
|
Bus *bus = busses.getBus(i);
|
||||||
if (bus == nullptr) continue;
|
if (bus == nullptr) continue;
|
||||||
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
||||||
@ -1234,24 +1190,24 @@ void WS2812FX::service() {
|
|||||||
|
|
||||||
if (!seg.freeze) { //only run effect function if not frozen
|
if (!seg.freeze) { //only run effect function if not frozen
|
||||||
_virtualSegmentLength = seg.virtualLength();
|
_virtualSegmentLength = seg.virtualLength();
|
||||||
_colors_t[0] = seg.currentColor(0, seg.colors[0]);
|
_colors_t[0] = seg.currentColor(0);
|
||||||
_colors_t[1] = seg.currentColor(1, seg.colors[1]);
|
_colors_t[1] = seg.currentColor(1);
|
||||||
_colors_t[2] = seg.currentColor(2, seg.colors[2]);
|
_colors_t[2] = seg.currentColor(2);
|
||||||
seg.currentPalette(_currentPalette, seg.palette);
|
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
||||||
|
|
||||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(true), correctWB);
|
||||||
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
for (int c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
||||||
|
|
||||||
// Effect blending
|
// Effect blending
|
||||||
// When two effects are being blended, each may have different segment data, this
|
// When two effects are being blended, each may have different segment data, this
|
||||||
// data needs to be saved first and then restored before running previous/transitional mode.
|
// data needs to be saved first and then restored before running previous mode.
|
||||||
// The blending will largely depend on the effect behaviour since actual output (LEDs) may be
|
// The blending will largely depend on the effect behaviour since actual output (LEDs) may be
|
||||||
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
|
// overwritten by later effect. To enable seamless blending for every effect, additional LED buffer
|
||||||
// would need to be allocated for each effect and then blended together for each pixel.
|
// would need to be allocated for each effect and then blended together for each pixel.
|
||||||
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(seg.mode); // this will return old mode while in transition
|
[[maybe_unused]] uint8_t tmpMode = seg.currentMode(); // this will return old mode while in transition
|
||||||
delay = (*_mode[seg.mode])(); // run new/current mode
|
delay = (*_mode[seg.mode])(); // run new/current mode
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
if (seg.mode != tmpMode) {
|
if (modeBlending && seg.mode != tmpMode) {
|
||||||
Segment::tmpsegd_t _tmpSegData;
|
Segment::tmpsegd_t _tmpSegData;
|
||||||
Segment::modeBlend(true); // set semaphore
|
Segment::modeBlend(true); // set semaphore
|
||||||
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
||||||
@ -1262,7 +1218,7 @@ void WS2812FX::service() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||||
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
if (seg.isInTransition() && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
||||||
}
|
}
|
||||||
|
|
||||||
seg.next_time = nowUp + delay;
|
seg.next_time = nowUp + delay;
|
||||||
@ -1399,12 +1355,12 @@ void WS2812FX::show(void) {
|
|||||||
// or async show has a separate buffer (ESP32 RMT and I2S are ok)
|
// or async show has a separate buffer (ESP32 RMT and I2S are ok)
|
||||||
if (newBri < _brightness) busses.setBrightness(_brightness);
|
if (newBri < _brightness) busses.setBrightness(_brightness);
|
||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long showNow = millis();
|
||||||
size_t diff = now - _lastShow;
|
size_t diff = showNow - _lastShow;
|
||||||
size_t fpsCurr = 200;
|
size_t fpsCurr = 200;
|
||||||
if (diff > 0) fpsCurr = 1000 / diff;
|
if (diff > 0) fpsCurr = 1000 / diff;
|
||||||
_cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
|
_cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
|
||||||
_lastShow = now;
|
_lastShow = showNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1597,10 +1553,12 @@ void WS2812FX::setSegment(uint8_t segId, uint16_t i1, uint16_t i2, uint8_t group
|
|||||||
_qStart = i1; _qStop = i2; _qStartY = startY; _qStopY = stopY;
|
_qStart = i1; _qStop = i2; _qStartY = startY; _qStopY = stopY;
|
||||||
_qGrouping = grouping; _qSpacing = spacing; _qOffset = offset;
|
_qGrouping = grouping; _qSpacing = spacing; _qOffset = offset;
|
||||||
_queuedChangesSegId = segId;
|
_queuedChangesSegId = segId;
|
||||||
|
DEBUG_PRINT(F("Segment queued: ")); DEBUG_PRINTLN(segId);
|
||||||
return; // queued changes are applied immediately after effect function returns
|
return; // queued changes are applied immediately after effect function returns
|
||||||
}
|
}
|
||||||
|
|
||||||
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
_segments[segId].setUp(i1, i2, grouping, spacing, offset, startY, stopY);
|
||||||
|
if (segId > 0 && segId == getSegmentsNum()-1 && i2 <= i1) _segments.pop_back(); // if last segment was deleted remove it from vector
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::setUpSegmentFromQueuedChanges() {
|
void WS2812FX::setUpSegmentFromQueuedChanges() {
|
||||||
@ -1729,7 +1687,7 @@ void WS2812FX::fixInvalidSegments() {
|
|||||||
bool WS2812FX::checkSegmentAlignment() {
|
bool WS2812FX::checkSegmentAlignment() {
|
||||||
bool aligned = false;
|
bool aligned = false;
|
||||||
for (segment &seg : _segments) {
|
for (segment &seg : _segments) {
|
||||||
for (uint8_t b = 0; b<busses.getNumBusses(); b++) {
|
for (unsigned b = 0; b<busses.getNumBusses(); b++) {
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true;
|
if (seg.start == bus->getStart() && seg.stop == bus->getStart() + bus->getLength()) aligned = true;
|
||||||
}
|
}
|
||||||
@ -1752,13 +1710,8 @@ uint8_t WS2812FX::setPixelSegment(uint8_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
|
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
|
||||||
if (i2 >= i)
|
if (i2 < i) std::swap(i,i2);
|
||||||
{
|
for (unsigned x = i; x <= i2; x++) setPixelColor(x, col);
|
||||||
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
for (uint16_t x = i2; x <= i; x++) setPixelColor(x, col);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::setTransitionMode(bool t) {
|
void WS2812FX::setTransitionMode(bool t) {
|
||||||
@ -1793,7 +1746,7 @@ void WS2812FX::loadCustomPalettes() {
|
|||||||
|
|
||||||
if (readObjectFromFile(fileName, nullptr, &pDoc)) {
|
if (readObjectFromFile(fileName, nullptr, &pDoc)) {
|
||||||
JsonArray pal = pDoc[F("palette")];
|
JsonArray pal = pDoc[F("palette")];
|
||||||
if (!pal.isNull() && pal.size()>4) { // not an empty palette (at least 2 entries)
|
if (!pal.isNull() && pal.size()>3) { // not an empty palette (at least 2 entries)
|
||||||
if (pal[0].is<int>() && pal[1].is<const char *>()) {
|
if (pal[0].is<int>() && pal[1].is<const char *>()) {
|
||||||
// we have an array of index & hex strings
|
// we have an array of index & hex strings
|
||||||
size_t palSize = MIN(pal.size(), 36);
|
size_t palSize = MIN(pal.size(), 36);
|
||||||
@ -1802,7 +1755,7 @@ void WS2812FX::loadCustomPalettes() {
|
|||||||
uint8_t rgbw[] = {0,0,0,0};
|
uint8_t rgbw[] = {0,0,0,0};
|
||||||
tcp[ j ] = (uint8_t) pal[ i ].as<int>(); // index
|
tcp[ j ] = (uint8_t) pal[ i ].as<int>(); // index
|
||||||
colorFromHexString(rgbw, pal[i+1].as<const char *>()); // will catch non-string entires
|
colorFromHexString(rgbw, pal[i+1].as<const char *>()); // will catch non-string entires
|
||||||
for (size_t c=0; c<3; c++) tcp[j+1+c] = rgbw[c]; // only use RGB component
|
for (size_t c=0; c<3; c++) tcp[j+1+c] = gamma8(rgbw[c]); // only use RGB component
|
||||||
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[j]), int(tcp[j+1]), int(tcp[j+2]), int(tcp[j+3]));
|
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[j]), int(tcp[j+1]), int(tcp[j+2]), int(tcp[j+3]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1810,13 +1763,15 @@ void WS2812FX::loadCustomPalettes() {
|
|||||||
palSize -= palSize % 4; // make sure size is multiple of 4
|
palSize -= palSize % 4; // make sure size is multiple of 4
|
||||||
for (size_t i=0; i<palSize && pal[i].as<int>()<256; i+=4) {
|
for (size_t i=0; i<palSize && pal[i].as<int>()<256; i+=4) {
|
||||||
tcp[ i ] = (uint8_t) pal[ i ].as<int>(); // index
|
tcp[ i ] = (uint8_t) pal[ i ].as<int>(); // index
|
||||||
tcp[i+1] = (uint8_t) pal[i+1].as<int>(); // R
|
tcp[i+1] = gamma8((uint8_t) pal[i+1].as<int>()); // R
|
||||||
tcp[i+2] = (uint8_t) pal[i+2].as<int>(); // G
|
tcp[i+2] = gamma8((uint8_t) pal[i+2].as<int>()); // G
|
||||||
tcp[i+3] = (uint8_t) pal[i+3].as<int>(); // B
|
tcp[i+3] = gamma8((uint8_t) pal[i+3].as<int>()); // B
|
||||||
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[i]), int(tcp[i+1]), int(tcp[i+2]), int(tcp[i+3]));
|
DEBUG_PRINTF("%d(%d) : %d %d %d\n", i, int(tcp[i]), int(tcp[i+1]), int(tcp[i+2]), int(tcp[i+3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customPalettes.push_back(targetPalette.loadDynamicGradientPalette(tcp));
|
customPalettes.push_back(targetPalette.loadDynamicGradientPalette(tcp));
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTLN(F("Wrong palette format."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1832,7 +1787,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
|||||||
char fileName[32];
|
char fileName[32];
|
||||||
strcpy_P(fileName, PSTR("/ledmap"));
|
strcpy_P(fileName, PSTR("/ledmap"));
|
||||||
if (n) sprintf(fileName +7, "%d", n);
|
if (n) sprintf(fileName +7, "%d", n);
|
||||||
strcat(fileName, ".json");
|
strcat_P(fileName, PSTR(".json"));
|
||||||
bool isFile = WLED_FS.exists(fileName);
|
bool isFile = WLED_FS.exists(fileName);
|
||||||
|
|
||||||
if (!isFile) {
|
if (!isFile) {
|
||||||
@ -1866,7 +1821,7 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
|||||||
if (!map.isNull() && map.size()) { // not an empty map
|
if (!map.isNull() && map.size()) { // not an empty map
|
||||||
customMappingSize = map.size();
|
customMappingSize = map.size();
|
||||||
customMappingTable = new uint16_t[customMappingSize];
|
customMappingTable = new uint16_t[customMappingSize];
|
||||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
for (unsigned i=0; i<customMappingSize; i++) {
|
||||||
customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
|
customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[s]) < 0))
|
if (((buttonType[s] == BTN_TYPE_ANALOG) || (buttonType[s] == BTN_TYPE_ANALOG_INVERTED)) && (digitalPinToAnalogChannel(btnPin[s]) < 0))
|
||||||
{
|
{
|
||||||
// not an ADC analog pin
|
// not an ADC analog pin
|
||||||
DEBUG_PRINTF("PIN ALLOC error: GPIO%d for analog button #%d is not an analog pin!\n", btnPin[s], s);
|
DEBUG_PRINT(F("PIN ALLOC error: GPIO")); DEBUG_PRINT(btnPin[s]);
|
||||||
|
DEBUG_PRINT(F("for analog button #")); DEBUG_PRINT(s);
|
||||||
|
DEBUG_PRINTLN(F(" is not an analog pin!"));
|
||||||
btnPin[s] = -1;
|
btnPin[s] = -1;
|
||||||
pinManager.deallocatePin(pin,PinOwner::Button);
|
pinManager.deallocatePin(pin,PinOwner::Button);
|
||||||
}
|
}
|
||||||
@ -357,6 +359,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
|
|
||||||
JsonObject light_tr = light["tr"];
|
JsonObject light_tr = light["tr"];
|
||||||
CJSON(fadeTransition, light_tr["mode"]);
|
CJSON(fadeTransition, light_tr["mode"]);
|
||||||
|
CJSON(modeBlending, light_tr["fx"]);
|
||||||
int tdd = light_tr["dur"] | -1;
|
int tdd = light_tr["dur"] | -1;
|
||||||
if (tdd >= 0) transitionDelay = transitionDelayDefault = tdd * 100;
|
if (tdd >= 0) transitionDelay = transitionDelayDefault = tdd * 100;
|
||||||
CJSON(strip.paletteFade, light_tr["pal"]);
|
CJSON(strip.paletteFade, light_tr["pal"]);
|
||||||
@ -827,6 +830,7 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject light_tr = light.createNestedObject("tr");
|
JsonObject light_tr = light.createNestedObject("tr");
|
||||||
light_tr["mode"] = fadeTransition;
|
light_tr["mode"] = fadeTransition;
|
||||||
|
light_tr["fx"] = modeBlending;
|
||||||
light_tr["dur"] = transitionDelayDefault / 100;
|
light_tr["dur"] = transitionDelayDefault / 100;
|
||||||
light_tr["pal"] = strip.paletteFade;
|
light_tr["pal"] = strip.paletteFade;
|
||||||
light_tr[F("rpc")] = randomPaletteChangeTime;
|
light_tr[F("rpc")] = randomPaletteChangeTime;
|
||||||
@ -888,6 +892,7 @@ void serializeConfig() {
|
|||||||
if_live[F("no-gc")] = arlsDisableGammaCorrection;
|
if_live[F("no-gc")] = arlsDisableGammaCorrection;
|
||||||
if_live[F("offset")] = arlsOffset;
|
if_live[F("offset")] = arlsOffset;
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
JsonObject if_va = interfaces.createNestedObject("va");
|
JsonObject if_va = interfaces.createNestedObject("va");
|
||||||
if_va[F("alexa")] = alexaEnabled;
|
if_va[F("alexa")] = alexaEnabled;
|
||||||
|
|
||||||
@ -896,6 +901,7 @@ void serializeConfig() {
|
|||||||
if_va_macros.add(macroAlexaOff);
|
if_va_macros.add(macroAlexaOff);
|
||||||
|
|
||||||
if_va["p"] = alexaNumPresets;
|
if_va["p"] = alexaNumPresets;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||||
@ -1033,7 +1039,7 @@ bool deserializeConfigSec() {
|
|||||||
JsonObject ap = doc["ap"];
|
JsonObject ap = doc["ap"];
|
||||||
getStringFromJson(apPass, ap["psk"] , 65);
|
getStringFromJson(apPass, ap["psk"] , 65);
|
||||||
|
|
||||||
JsonObject interfaces = doc["if"];
|
[[maybe_unused]] JsonObject interfaces = doc["if"];
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
JsonObject if_mqtt = interfaces["mqtt"];
|
JsonObject if_mqtt = interfaces["mqtt"];
|
||||||
@ -1072,7 +1078,7 @@ void serializeConfigSec() {
|
|||||||
JsonObject ap = doc.createNestedObject("ap");
|
JsonObject ap = doc.createNestedObject("ap");
|
||||||
ap["psk"] = apPass;
|
ap["psk"] = apPass;
|
||||||
|
|
||||||
JsonObject interfaces = doc.createNestedObject("if");
|
[[maybe_unused]] JsonObject interfaces = doc.createNestedObject("if");
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||||
if_mqtt["psk"] = mqttPass;
|
if_mqtt["psk"] = mqttPass;
|
||||||
|
@ -35,8 +35,19 @@ uint32_t color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16)
|
|||||||
* color add function that preserves ratio
|
* color add function that preserves ratio
|
||||||
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
|
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
|
||||||
*/
|
*/
|
||||||
uint32_t color_add(uint32_t c1, uint32_t c2)
|
uint32_t color_add(uint32_t c1, uint32_t c2, bool fast)
|
||||||
{
|
{
|
||||||
|
if (fast) {
|
||||||
|
uint8_t r = R(c1);
|
||||||
|
uint8_t g = G(c1);
|
||||||
|
uint8_t b = B(c1);
|
||||||
|
uint8_t w = W(c1);
|
||||||
|
r = qadd8(r, R(c2));
|
||||||
|
g = qadd8(g, G(c2));
|
||||||
|
b = qadd8(b, B(c2));
|
||||||
|
w = qadd8(w, W(c2));
|
||||||
|
return RGBW32(r,g,b,w);
|
||||||
|
} else {
|
||||||
uint32_t r = R(c1) + R(c2);
|
uint32_t r = R(c1) + R(c2);
|
||||||
uint32_t g = G(c1) + G(c2);
|
uint32_t g = G(c1) + G(c2);
|
||||||
uint32_t b = B(c1) + B(c2);
|
uint32_t b = B(c1) + B(c2);
|
||||||
@ -47,11 +58,36 @@ uint32_t color_add(uint32_t c1, uint32_t c2)
|
|||||||
if (w > max) max = w;
|
if (w > max) max = w;
|
||||||
if (max < 256) return RGBW32(r, g, b, w);
|
if (max < 256) return RGBW32(r, g, b, w);
|
||||||
else return RGBW32(r * 255 / max, g * 255 / max, b * 255 / max, w * 255 / max);
|
else return RGBW32(r * 255 / max, g * 255 / max, b * 255 / max, w * 255 / max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fades color toward black
|
||||||
|
* if using "video" method the resulting color will never become black unless it is already black
|
||||||
|
*/
|
||||||
|
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
||||||
|
{
|
||||||
|
uint8_t r = R(c1);
|
||||||
|
uint8_t g = G(c1);
|
||||||
|
uint8_t b = B(c1);
|
||||||
|
uint8_t w = W(c1);
|
||||||
|
if (video) {
|
||||||
|
r = scale8_video(r, amount);
|
||||||
|
g = scale8_video(g, amount);
|
||||||
|
b = scale8_video(b, amount);
|
||||||
|
w = scale8_video(w, amount);
|
||||||
|
} else {
|
||||||
|
r = scale8(r, amount);
|
||||||
|
g = scale8(g, amount);
|
||||||
|
b = scale8(b, amount);
|
||||||
|
w = scale8(w, amount);
|
||||||
|
}
|
||||||
|
return RGBW32(r, g, b, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRandomColor(byte* rgb)
|
void setRandomColor(byte* rgb)
|
||||||
{
|
{
|
||||||
lastRandomIndex = strip.getMainSegment().get_random_wheel_index(lastRandomIndex);
|
lastRandomIndex = get_random_wheel_index(lastRandomIndex);
|
||||||
colorHStoRGB(lastRandomIndex*256,255,rgb);
|
colorHStoRGB(lastRandomIndex*256,255,rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@
|
|||||||
#define CALL_MODE_NO_NOTIFY 5
|
#define CALL_MODE_NO_NOTIFY 5
|
||||||
#define CALL_MODE_FX_CHANGED 6 //no longer used
|
#define CALL_MODE_FX_CHANGED 6 //no longer used
|
||||||
#define CALL_MODE_HUE 7
|
#define CALL_MODE_HUE 7
|
||||||
#define CALL_MODE_PRESET_CYCLE 8
|
#define CALL_MODE_PRESET_CYCLE 8 //no longer used
|
||||||
#define CALL_MODE_BLYNK 9 //no longer used
|
#define CALL_MODE_BLYNK 9 //no longer used
|
||||||
#define CALL_MODE_ALEXA 10
|
#define CALL_MODE_ALEXA 10
|
||||||
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
||||||
@ -313,10 +313,9 @@
|
|||||||
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
|
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
|
||||||
#define SEG_OPTION_FREEZE 4 //Segment contents will not be refreshed
|
#define SEG_OPTION_FREEZE 4 //Segment contents will not be refreshed
|
||||||
#define SEG_OPTION_RESET 5 //Segment runtime requires reset
|
#define SEG_OPTION_RESET 5 //Segment runtime requires reset
|
||||||
#define SEG_OPTION_TRANSITIONAL 6
|
#define SEG_OPTION_REVERSED_Y 6
|
||||||
#define SEG_OPTION_REVERSED_Y 7
|
#define SEG_OPTION_MIRROR_Y 7
|
||||||
#define SEG_OPTION_MIRROR_Y 8
|
#define SEG_OPTION_TRANSPOSED 8
|
||||||
#define SEG_OPTION_TRANSPOSED 9
|
|
||||||
|
|
||||||
//Segment differs return byte
|
//Segment differs return byte
|
||||||
#define SEG_DIFFERS_BRI 0x01 // opacity
|
#define SEG_DIFFERS_BRI 0x01 // opacity
|
||||||
@ -345,6 +344,7 @@
|
|||||||
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
|
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
|
||||||
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
|
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
|
||||||
#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist
|
#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist
|
||||||
|
#define ERR_FS_RMLOAD 14 // It was attempted to load an remote JSON cmd, but the "remote.json" file does not exist
|
||||||
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
|
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
|
||||||
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
|
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
|
||||||
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
|
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
|
||||||
|
@ -198,12 +198,13 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-bottom: 10px;">
|
</div>
|
||||||
|
<div style="padding-block: 10px;">
|
||||||
|
<button class="btn btn-xs" type="button" onclick="togglePixelMagicTool()"><i class="icons btn-icon"></i></button>
|
||||||
<button class="btn btn-xs" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon"></i></button>
|
||||||
<button class="btn btn-xs" type="button" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" type="button" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="Effects" class="tabcontent">
|
<div id="Effects" class="tabcontent">
|
||||||
<div id="fx">
|
<div id="fx">
|
||||||
@ -392,6 +393,7 @@
|
|||||||
<button class="btn" onclick="setLor(2)">Override until reboot</button><br>
|
<button class="btn" onclick="setLor(2)">Override until reboot</button><br>
|
||||||
<span class="h">For best performance, it is recommended to turn off the streaming source when not in use.</span>
|
<span class="h">For best performance, it is recommended to turn off the streaming source when not in use.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<i id="roverstar" class="icons huge" onclick="setLor(0)"></i><br>
|
<i id="roverstar" class="icons huge" onclick="setLor(0)"></i><br>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -33,10 +33,9 @@ var hol = [
|
|||||||
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
||||||
[0,2,17,1,"https://images.alphacoders.com/491/491123.jpg"], // st. Patrick's day
|
[0,2,17,1,"https://images.alphacoders.com/491/491123.jpg"], // st. Patrick's day
|
||||||
[2025,3,20,2,"https://aircoookie.github.io/easter.png"],
|
[2025,3,20,2,"https://aircoookie.github.io/easter.png"],
|
||||||
[2023,3,9,2,"https://aircoookie.github.io/easter.png"],
|
|
||||||
[2024,2,31,2,"https://aircoookie.github.io/easter.png"],
|
[2024,2,31,2,"https://aircoookie.github.io/easter.png"],
|
||||||
[0,6,4,1,"https://initiate.alphacoders.com/download/wallpaper/516792/images/jpg/510921363292536"], // 4th of July
|
[0,6,4,1,"https://images.alphacoders.com/516/516792.jpg"], // 4th of July
|
||||||
[0,0,1,1,"https://initiate.alphacoders.com/download/wallpaper/1198800/images/jpg/2522807481585600"] // new year
|
[0,0,1,1,"https://images.alphacoders.com/119/1198800.jpg"] // new year
|
||||||
];
|
];
|
||||||
|
|
||||||
function handleVisibilityChange() {if (!d.hidden && new Date () - lastUpdate > 3000) requestJson();}
|
function handleVisibilityChange() {if (!d.hidden && new Date () - lastUpdate > 3000) requestJson();}
|
||||||
@ -1514,12 +1513,15 @@ function setEffectParameters(idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the bottom position of selected effect (sticky) as the top of sliders div
|
// set the bottom position of selected effect (sticky) as the top of sliders div
|
||||||
setInterval(()=>{
|
function setSelectedEffectPosition() {
|
||||||
let top = parseInt(getComputedStyle(gId("sliders")).height);
|
let top = parseInt(getComputedStyle(gId("sliders")).height);
|
||||||
top += 5;
|
top += 5;
|
||||||
let sel = d.querySelector('#fxlist .selected');
|
let sel = d.querySelector('#fxlist .selected');
|
||||||
if (sel) sel.style.bottom = top + "px"; // we will need to remove this when unselected (in setFX())
|
if (sel) sel.style.bottom = top + "px"; // we will need to remove this when unselected (in setFX())
|
||||||
},750);
|
}
|
||||||
|
|
||||||
|
setSelectedEffectPosition();
|
||||||
|
setInterval(setSelectedEffectPosition,750);
|
||||||
// set html color items on/off
|
// set html color items on/off
|
||||||
var cslLabel = '';
|
var cslLabel = '';
|
||||||
var sep = '';
|
var sep = '';
|
||||||
|
@ -7,13 +7,10 @@
|
|||||||
|
|
||||||
<title>Pixel Magic Tool</title>
|
<title>Pixel Magic Tool</title>
|
||||||
|
|
||||||
<!-- <link
|
|
||||||
rel="shortcut icon"
|
|
||||||
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAK9JREFUeNqUUssNwyAMJZWVUw4dhRHakZA6RqWMFEbwKDnk1FNBekEWxOBYQggL/D68yXXq+M7PtHkcefn89vrOw/UrP96w/NUFGiDLRz71GyY0QJa1Yn+nFa0ShqUNYCAF0QvoceOB4naEZif6UTNRapYaTyauRi4DEspr4Hbs5YKsbmtMyeJ0LxeESV4gB+hlSy4oO2txWysyus0a0+lO6vBjxcTMlG4mt2H6F2AAhU5NWu4dorQAAAAASUVORK5CYII=
|
|
||||||
" /> -->
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
|
--s-thumb: #0006;
|
||||||
|
--s-background: #0003;
|
||||||
--overlay: rgba(0, 0, 0, 0.5);
|
--overlay: rgba(0, 0, 0, 0.5);
|
||||||
--background: #111;
|
--background: #111;
|
||||||
--text: #bbb;
|
--text: #bbb;
|
||||||
@ -34,6 +31,24 @@
|
|||||||
--warning-light: #f48c06;
|
--warning-light: #f48c06;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--s-thumb);
|
||||||
|
opacity: 0.2;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--s-background);
|
||||||
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: var(--blue-light);
|
background: var(--blue-light);
|
||||||
}
|
}
|
||||||
@ -65,7 +80,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin: 2px 0 5px;
|
margin: 2px 0 5px;
|
||||||
color: var(--text);
|
color: var(--gray-light);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,10 +98,19 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(a:hover, a:focus, a:active) {
|
a:is(:hover, :focus, :active) {
|
||||||
color: var(--blue-medium);
|
color: var(--blue-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#wledEdit {
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: var(--blue-light);
|
||||||
|
margin-left: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--gray-light);
|
||||||
|
}
|
||||||
|
|
||||||
.m-zero {
|
.m-zero {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
@ -108,8 +132,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: calc(100% - 40px);
|
width: min(768px, calc(100% - 40px));
|
||||||
max-width: 768px;
|
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,26 +140,43 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 20px 0 0;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
flex-basis: calc(50% - 10px);
|
flex-basis: calc(50% - 10px);
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 5px;
|
padding-inline: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-full {
|
.column-full {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 5px;
|
padding-inline: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .brand {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 200px;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: flex;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
@ -157,7 +197,7 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0px 1px;
|
padding-inline: 1px;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,18 +212,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-group .input-description {
|
.input-group .input-description {
|
||||||
width: 38px;
|
width: 100%;
|
||||||
|
max-width: 38px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
padding: 10px 0;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
color: var(--gray-dark);
|
color: var(--gray-dark);
|
||||||
background: var(--gray-light);
|
background: var(--gray-light);
|
||||||
border-radius: 0px 5px 5px 0;
|
border-radius: 0px 8px 8px 0;
|
||||||
border: 1px solid var(--gray-light);
|
border: 1px solid var(--gray-light);
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
text-align: center;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
font-weight: 600;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group .square {
|
.input-group .square {
|
||||||
@ -191,10 +232,19 @@
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-group .square input {
|
||||||
|
text-align: center;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
color: var(--gray-dark);
|
||||||
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
resize: vertical;
|
resize: none;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-select {
|
.custom-select {
|
||||||
@ -231,7 +281,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 10px;
|
padding: 40px 10px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 20px 0 0;
|
margin-top: 20px;
|
||||||
transition: all 0.5s ease-in-out;
|
transition: all 0.5s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,14 +303,15 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
outline: none;
|
outline: none;
|
||||||
margin: 16px 0;
|
margin-block: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-slider::-webkit-slider-thumb {
|
.range-slider::-webkit-slider-thumb,
|
||||||
|
.range-slider::-moz-range-thumb {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
background-color: var(--gray-dark);
|
background-color: var(--blue-light);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -326,7 +377,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
width: auto;
|
width: auto;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
margin: 10px 0 0;
|
margin-top: 10px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transform: translateY(30px);
|
transform: translateY(30px);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@ -334,7 +385,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toast .toast-body {
|
.toast .toast-body {
|
||||||
padding: 8px 0;
|
padding-block: 8px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
@ -360,7 +411,7 @@
|
|||||||
height: 3px;
|
height: 3px;
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
transform-origin: left;
|
transform-origin: left;
|
||||||
border-radius: inherit;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast.success .toast-progress {
|
.toast.success .toast-progress {
|
||||||
@ -387,22 +438,6 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .brand {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 200px;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
outline: none;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel {
|
.carousel {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -410,18 +445,6 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel img {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin-right: 20px;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel img:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -429,7 +452,7 @@
|
|||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0 0 10px;
|
margin-bottom: 10px;
|
||||||
background: var(--gray-medium);
|
background: var(--gray-medium);
|
||||||
border: 1px solid var(--gray-dark);
|
border: 1px solid var(--gray-dark);
|
||||||
transition: all 0.5s ease-in-out;
|
transition: all 0.5s ease-in-out;
|
||||||
@ -477,7 +500,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#recreatedImage {
|
#recreatedImage {
|
||||||
margin: 20px 0;
|
margin-block: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid {
|
.invalid {
|
||||||
@ -487,16 +510,12 @@
|
|||||||
.error-message {
|
.error-message {
|
||||||
display: block;
|
display: block;
|
||||||
color: var(--error-dark);
|
color: var(--error-dark);
|
||||||
padding: 4px 0;
|
padding-block: 4px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.header {
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -506,7 +525,7 @@
|
|||||||
.column,
|
.column,
|
||||||
.column-full {
|
.column-full {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
margin: 20px 0 0;
|
margin-top: 20px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,68 +561,7 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<form id="formGenerate" novalidate>
|
<form id="formGenerate" novalidate>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<svg
|
<img src=" data:image/png;base64,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" alt="Pixel Magic Tool" class="brand">
|
||||||
class="brand"
|
|
||||||
version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
x="0px"
|
|
||||||
y="0px"
|
|
||||||
width="200px"
|
|
||||||
height="130px"
|
|
||||||
viewBox="0 0 200 130"
|
|
||||||
enable-background="new 0 0 200 130"
|
|
||||||
xml:space="preserve">
|
|
||||||
<image
|
|
||||||
width="200"
|
|
||||||
height="130"
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACCCAQAAACpkk8fAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
|
|
||||||
AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElN
|
|
||||||
RQfnBg4TByTFKGw2AAAIWElEQVR42u2d+5GjOBCHf3t1AVBKYAiBDBZHMg7hHMEwETiEsyMxkwEh
|
|
||||||
cAl0OQPfH+IhgQQIBDRefVu1ZWMhHj20+iUBBN4LSulFL3pRuveZvAd/7X0CAZ0gEGb8WrIzvbpb
|
|
||||||
xKL+AuEJYcffWxyk/yRVnES+9w0AAMrwBfB4vpcJ5AQgwRUAcEGx98W8A4sEInKA6i8Fj7/2o+Ms
|
|
||||||
EEoQAXiKYlLr1+DPD0JXUVCKBwDgW2RrXnhzHGa4PyFXpABynKrvRfWp2PtS3oPFg7p4Ivd1MpQC
|
|
||||||
SKovH5QCKMRz+5uyJw52BaVIAXwiBlDiDiDXxw06y9/ErdmSAYC0YSpy/OA30nZDq7IMCm41O4xi
|
|
||||||
nAF84Gw6k0NAWRW1av9lnRYPetGLerq5u4/ek6XdJhGyJhLXOZP92MQPGUbe9GCjSTwJhM74RK3/
|
|
||||||
E3oAuLeKq8cNOYDPSl3IJ+oXdL/mhjv+QFPBQSAiQwbQQ1pZ4qT9GCujQoQUwM9ATyXK+snQtueK
|
|
||||||
X/Pfn/nMMFBZLlSjViluzWfJTZQj+4y244G7QArl/5YSOYDKaUQBYO6F136NeX9pr+W4oWu72Y83
|
|
||||||
tR0LnAUiLsatN9wadVZ01Jlb/x79miPCVGVVXgJwE2Xl/wzzSSkUhdQ1yDvtAAAiA0P8CuSOH8xX
|
|
||||||
Vipxo5xKpJrSaRC/lIjUuWkt+bL0e1Y+Z16v3RNeBTJg6AYmwkplKT5+NNhwwNOhaxMN83deigJd
|
|
||||||
+x6wEoh5rBCq/yPpezptzCtR2nW8pToz6IyqQFcm5NSZoTwh1kDeYAicIpuKsHvaVaAlrr5a2+ln
|
|
||||||
AUB/hr5o3t87UOA5tSk90CrQKz2BJUb9OKrKsmXQToO3LLHuZw9mx1r4vblAzW7qIP0fTxHZi0NY
|
|
||||||
RjlT/6NTn6CymLHPoF7O9sblfqnWVwkMqSDtqZLKaqC18Yi1WnZQdXPZRSAy0DJrzxPQucV3kTl0
|
|
||||||
4KKsmiM2atR5b3eCymIGLz9kFMOgLm2todz7t/K5nHXYsuqj2duSFfLAwQQyB5Et7qHcLu51GIFU
|
|
||||||
BXpuRJQCKH0GPChGjNozWaH/wwikKtCT5UdAp4DHgvSRvuf9fVvU0lkJvyzq38xxBCIpRXXxlE4Q
|
|
||||||
yAE5gEA0JWEjIcAW5PnoBYVG6iHXVktDHEAgmpJokZZPrbhk6dAJOS6IoIeBzr1n6TTimA6pJVnC
|
|
||||||
JIP8BS7wk5BrOIJAjEjLp6+4ZFU+OffncNwSoCcA4OnfUTyaQGLKoFUPvxtbCkTWIpZOrQvoSkKm
|
|
||||||
ivJe6EXO3yqa79IyevT6kxSAcf+2bXtEs1q6VAVP3tlSIG61iE1rTUnY6Mzfkt/I2N/4/uNqadp0
|
|
||||||
pTlMEci1uRlFXZWlZK6jtU7tz0RJIim1TL8tlVCNk6RluLUWbaZbZAg4ozwhIqs/UTahNM3MT9tL
|
|
||||||
YA4h/M6MIBBmBIEwg4VjqKWdZiV9ZpfAadSTPq1z2CdPQZ00C944Ez88IcwIAmFGEAgzgkCYsfGg
|
|
||||||
PmEhgEhpM5IW0mILO1Els7okE3ZVEmetsbC1lTVue6i1wmPZaptlZaowtBVJ5EMTuCdwnm3fqYmz
|
|
||||||
JoTFwuz1jqHC0Bp9YxbsCWMIM4JAmBEEwgy3MSTlsYTR/ijTU2O/PW89qJvjVCxXPxwktWzvrs2q
|
|
||||||
23YTqi03Fog5OLde0c7ss5y7tlx3bVbt25RqyzCGMCMIhBnmadEfs/szhgOY9HYIpkyLdsEYDmDS
|
|
||||||
m0refCr7P1rn3m+waO2UQb3Kk3WycvVWDytEKwvFesn8TTjicFbSNvd+rEjbDWPG8D1jWYnBbov2
|
|
||||||
PqlpvKdArnufwHyClcWMrRNU2UiD3RJNXNhaZfkdstuh+dPiA8vJBFwotTnzuanJoceQ1jexpoZX
|
|
||||||
mOO04HwnzHcPYwgzgkCYcWiVNYHIrMw4KTKdDQTix/tWUmMub6ey+dxsX93i/HYEj5gsoOTITp0P
|
|
||||||
9lRZBguIW6pqe8KgzowgEGa8u5VlQQnh5F4trvbtCzNXm+AmEPXtIS5LluXGrb+t1SFfo/tOPZ5e
|
|
||||||
bH1WWtzm3ABmAhFFG5+yVuOa9stNt3XB9O6x47Vn6TmlFsYQZgSBMCMIhBl7jiEJmcIahZiRwTAX
|
|
||||||
YExCeceC13fhmq/OQjsm7SmQaK0ht+FmtKC2Cc/MvDpmVpZf5LpXXXiHZ8IYwowgEGYcWmVxmBbt
|
|
||||||
m0MLZJuy022xCcQlKzeyn1ASW9YpcaOGqleT1COTrs7hOsIYwowgEGYEgTAjCIQZ6qA+WndqZEK9
|
|
||||||
quUYei997guXhfGDWhtTzLw6B5jaLtOYZ7PZ53wZ11xc4cVfQwSVxYwgEGYc21O3kQxGdJO9T2+I
|
|
||||||
9xTIavkO5a0QKvf5L5ihBFcuCarFeJlObQoSqZZjqf2SGNNOS6zBTiLr0AJZC/NMJ4vQc/zMm71u
|
|
||||||
LnMKAlmK5zUbg0Cm02boZVZe6v1ydn8XRH2PKAhkMnWGnjK5OM/SmmBRmPL77yKQfMM9V02LHTp0
|
|
||||||
sg91wKafalKNYj3gQmd8Nl8UI7nf17s8ITxIrLVYsfLLoJEcnhBnzE+IySiWLYzBzHpxq15fIZbF
|
|
||||||
jKCyfJE3n7qLwap+/6hBEFSWMxaVFSPGUxSaijrhKQq5YKCuonCRC8raDYTAZOgl/3W2ZvSS9e4U
|
|
||||||
UUr/Vq0eAKVta0rpH3X/fl9BZXmAYpzb2knxRN4u6FG7kdVv+VipdxCID+KBscHRjQxWFjOCQJgR
|
|
||||||
BOKDEt/IAaT06q0q+S3nq9dD/hhBIB4QpciagMgHpZS2A7nIcK8+RpRSOpbRD4O6b9Tl0U/a2+LU
|
|
||||||
tbsutqK7IJAVGciYFHzXtDsc9KKXeeFAelSOXu9XylpHcbivMIYEAkP8DyhqAZcAHYDzAAAAJXRF
|
|
||||||
WHRkYXRlOmNyZWF0ZQAyMDIzLTA2LTE0VDE5OjA3OjM2KzAwOjAw7raFWwAAACV0RVh0ZGF0ZTpt
|
|
||||||
b2RpZnkAMjAyMy0wNi0xNFQxOTowNzozNiswMDowMJ/rPecAAAAodEVYdGRhdGU6dGltZXN0YW1w
|
|
||||||
ADIwMjMtMDYtMTRUMTk6MDc6MzYrMDA6MDDI/hw4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFn
|
|
||||||
ZVJlYWR5ccllPAAAAABJRU5ErkJggg==" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="column" validate>
|
<div class="column" validate>
|
||||||
@ -626,11 +584,11 @@
|
|||||||
<label for="pattern">Pattern</label>
|
<label for="pattern">Pattern</label>
|
||||||
<select name="pattern" id="pattern" required>
|
<select name="pattern" id="pattern" required>
|
||||||
<option value="">Select a choice</option>
|
<option value="">Select a choice</option>
|
||||||
<option value="1" title="['ffffff']" selected>
|
<option value="1" title="['ffffff']">Individual</option>
|
||||||
Individual
|
|
||||||
</option>
|
|
||||||
<option value="2" title="[0, 'ffffff']">Index</option>
|
<option value="2" title="[0, 'ffffff']">Index</option>
|
||||||
<option value="3" title="[0, 5, 'ffffff']">Range</option>
|
<option value="3" title="[0, 5, 'ffffff']" selected>
|
||||||
|
Range
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -686,19 +644,25 @@
|
|||||||
max="255"
|
max="255"
|
||||||
value="128"
|
value="128"
|
||||||
class="range-slider" />
|
class="range-slider" />
|
||||||
|
<div class="input-description square">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
name="brightnessValue"
|
||||||
id="brightnessValue"
|
id="brightnessValue"
|
||||||
class="input-description square"
|
|
||||||
value="128" />
|
value="128" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="column" validate>
|
<div class="column" validate>
|
||||||
<label for="animation">Animation</label>
|
<label for="animation">Animation</label>
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
<input type="checkbox" name="animation" id="animation" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="animation"
|
||||||
|
id="animation"
|
||||||
|
data-parent="animation" />
|
||||||
<span class="switch-slider"></span>
|
<span class="switch-slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@ -708,19 +672,25 @@
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="transparentImage"
|
name="transparentImage"
|
||||||
id="transparentImage" />
|
id="transparentImage"
|
||||||
|
data-parent="transparentImage" />
|
||||||
<span class="switch-slider"></span>
|
<span class="switch-slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="column" validate>
|
<div class="column" validate>
|
||||||
<label for="resizeImage">Resize Image</label>
|
<label for="resizeImage">Resize Image</label>
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
<input type="checkbox" name="resizeImage" id="resizeImage" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="resizeImage"
|
||||||
|
id="resizeImage"
|
||||||
|
data-parent="resizeImage"
|
||||||
|
checked />
|
||||||
<span class="switch-slider"></span>
|
<span class="switch-slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row resizeImage" style="display: none">
|
<div class="row resizeImage">
|
||||||
<div class="column" validate>
|
<div class="column" validate>
|
||||||
<label for="width">Width</label>
|
<label for="width">Width</label>
|
||||||
<input type="number" name="width" id="width" value="16" />
|
<input type="number" name="width" id="width" value="16" />
|
||||||
@ -747,7 +717,9 @@
|
|||||||
min="0"
|
min="0"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
inputmode="numeric" />
|
inputmode="numeric" />
|
||||||
<div class="input-description">sec</div>
|
<div class="input-description">
|
||||||
|
<span>sec</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column" validate>
|
<div class="column" validate>
|
||||||
@ -762,7 +734,9 @@
|
|||||||
min="0"
|
min="0"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
inputmode="numeric" />
|
inputmode="numeric" />
|
||||||
<div class="input-description">sec</div>
|
<div class="input-description">
|
||||||
|
<span>sec</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -773,30 +747,27 @@
|
|||||||
Color that will replace the
|
Color that will replace the
|
||||||
<strong>transparent pixels</strong> in the image
|
<strong>transparent pixels</strong> in the image
|
||||||
</small>
|
</small>
|
||||||
<input type="color" name="color" id="color" value="#eeeeee" />
|
<input type="color" name="color" id="color" value="#00BFFF" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="column-full" validate>
|
<div class="column-full" validate>
|
||||||
<div class="custom-select">
|
<div class="custom-select">
|
||||||
<label for="images">Images</label>
|
<label for="images">
|
||||||
<select name="images" id="images" required>
|
<span>Images upload to WLED</span>
|
||||||
<option value="">Select a choice</option>
|
<a id="wledEdit" href="http://[wled-ip]/edit" target="_blank">
|
||||||
<option value="upload">Upload</option>
|
upload
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
|
<select name="images" id="images">
|
||||||
|
<option value="">Select image</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<small>
|
|
||||||
Images uploaded to
|
|
||||||
<a id="wledEdit" href="http://[wled-ip]/edit" target="_blank">
|
|
||||||
<strong>WLED</strong>
|
|
||||||
</a>
|
|
||||||
or upload image
|
|
||||||
</small>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="dropzone" class="dropzone" validate style="display: none">
|
<div id="dropzone" class="dropzone" validate>
|
||||||
<p id="dropzoneLabel">
|
<p id="dropzoneLabel">
|
||||||
Drag and drop a file here or click to select a file
|
Drag and drop a file here or click to select a local file
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
@ -868,7 +839,7 @@
|
|||||||
const hostname = element("hostname");
|
const hostname = element("hostname");
|
||||||
hostname.value = host;
|
hostname.value = host;
|
||||||
|
|
||||||
hostname.addEventListener("change", async () => {
|
hostname.addEventListener("blur", async () => {
|
||||||
WLED_URL = `${protocol}//${hostname.value}`;
|
WLED_URL = `${protocol}//${hostname.value}`;
|
||||||
|
|
||||||
await segments();
|
await segments();
|
||||||
@ -893,7 +864,7 @@
|
|||||||
|
|
||||||
function hostnameLabel() {
|
function hostnameLabel() {
|
||||||
const link = element("wledEdit");
|
const link = element("wledEdit");
|
||||||
link.href = link.href.replace("[wled-ip]", hostname.value);
|
link.href = WLED_URL + "/edit";
|
||||||
}
|
}
|
||||||
|
|
||||||
async function playlist() {
|
async function playlist() {
|
||||||
@ -999,6 +970,7 @@
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
toast(`Preset "${item.n}" save successfully`);
|
toast(`Preset "${item.n}" save successfully`);
|
||||||
|
window.parent.postMessage("loadPresets", WLED_URL);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast(`Error saving preset: ${error}`, "error");
|
toast(`Error saving preset: ${error}`, "error");
|
||||||
@ -1047,12 +1019,9 @@
|
|||||||
return mimeTypes.includes(mimetype);
|
return mimeTypes.includes(mimetype);
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = [
|
const options = [{ text: "Select image", value: "" }];
|
||||||
{ text: "Select a choice", value: "" },
|
|
||||||
{ text: "Upload", value: "upload" },
|
|
||||||
];
|
|
||||||
|
|
||||||
if (images) {
|
if (images.length > 0) {
|
||||||
options.push(
|
options.push(
|
||||||
...images.map(({ name }) => ({
|
...images.map(({ name }) => ({
|
||||||
text: name,
|
text: name,
|
||||||
@ -1064,6 +1033,11 @@
|
|||||||
|
|
||||||
options.forEach(({ text, value }) => {
|
options.forEach(({ text, value }) => {
|
||||||
const option = new Option(text, value);
|
const option = new Option(text, value);
|
||||||
|
|
||||||
|
if (index === 0) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1076,7 +1050,6 @@
|
|||||||
|
|
||||||
async function segments() {
|
async function segments() {
|
||||||
const select = element("segments");
|
const select = element("segments");
|
||||||
const pattern = element("pattern");
|
|
||||||
const width = element("width");
|
const width = element("width");
|
||||||
const height = element("height");
|
const height = element("height");
|
||||||
|
|
||||||
@ -1114,7 +1087,6 @@
|
|||||||
option.selected = true;
|
option.selected = true;
|
||||||
width.value = w;
|
width.value = w;
|
||||||
height.value = h;
|
height.value = h;
|
||||||
pattern.value = w * h > 512 ? 3 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select.add(option);
|
select.add(option);
|
||||||
@ -1278,12 +1250,12 @@
|
|||||||
const dropzone = element("dropzone");
|
const dropzone = element("dropzone");
|
||||||
const { value } = e.target.selectedOptions[0];
|
const { value } = e.target.selectedOptions[0];
|
||||||
|
|
||||||
if (value === "upload") {
|
if (!value) {
|
||||||
const dropzoneLabel = element("dropzoneLabel");
|
const dropzoneLabel = element("dropzoneLabel");
|
||||||
const source = element("source");
|
const source = element("source");
|
||||||
|
|
||||||
dropzoneLabel.textContent =
|
dropzoneLabel.textContent =
|
||||||
"Drag and drop a file here or click to select a file";
|
"Drag and drop a file here or click to select a local file";
|
||||||
source.value = "";
|
source.value = "";
|
||||||
|
|
||||||
dropzone.style.display = "block";
|
dropzone.style.display = "block";
|
||||||
@ -1293,43 +1265,35 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
element("transparentImage").addEventListener("change", (e) => {
|
element("transparentImage").addEventListener("change", (e) => {
|
||||||
const transparentImage = d.getElementsByClassName("transparentImage");
|
const transparentImage = d.getElementsByClassName("transparentImage")[0];
|
||||||
const { checked } = e.target;
|
const { checked } = e.target;
|
||||||
|
|
||||||
Array.from(transparentImage).forEach(function (element) {
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
element.style.display = "flex";
|
transparentImage.style.display = "flex";
|
||||||
} else {
|
} else {
|
||||||
element.style.display = "none";
|
transparentImage.style.display = "none";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
element("resizeImage").addEventListener("change", (e) => {
|
element("resizeImage").addEventListener("change", (e) => {
|
||||||
const resizeImage = d.getElementsByClassName("resizeImage");
|
const resizeImage = d.getElementsByClassName("resizeImage")[0];
|
||||||
const pattern = element("pattern");
|
const pattern = element("pattern");
|
||||||
const { checked } = e.target;
|
const { checked } = e.target;
|
||||||
|
|
||||||
Array.from(resizeImage).forEach(function (element) {
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
pattern.value = 3;
|
resizeImage.style.display = "flex";
|
||||||
element.style.display = "flex";
|
|
||||||
} else {
|
} else {
|
||||||
pattern.value = 1;
|
resizeImage.style.display = "none";
|
||||||
element.style.display = "none";
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
element("animation").addEventListener("change", (e) => {
|
element("animation").addEventListener("change", (e) => {
|
||||||
const animation = d.getElementsByClassName("animation");
|
const animation = d.getElementsByClassName("animation")[0];
|
||||||
|
|
||||||
const pattern = element("pattern");
|
const pattern = element("pattern");
|
||||||
const source = element("source");
|
const source = element("source");
|
||||||
|
|
||||||
const { checked } = e.target;
|
const { checked } = e.target;
|
||||||
|
|
||||||
Array.from(animation).forEach(function (element) {
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
toast(
|
toast(
|
||||||
'If you want all frames in the image, set it to "0"',
|
'If you want all frames in the image, set it to "0"',
|
||||||
@ -1338,18 +1302,15 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
source.setAttribute("accept", "image/gif");
|
source.setAttribute("accept", "image/gif");
|
||||||
element.style.display = "flex";
|
animation.style.display = "flex";
|
||||||
pattern.value = 3;
|
|
||||||
} else {
|
} else {
|
||||||
source.setAttribute(
|
source.setAttribute(
|
||||||
"accept",
|
"accept",
|
||||||
"image/jpg,image/jpeg,image/png,image/gif"
|
"image/jpg,image/jpeg,image/png,image/gif"
|
||||||
);
|
);
|
||||||
element.style.display = "none";
|
animation.style.display = "none";
|
||||||
pattern.value = 1;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
element("btnGenerate").addEventListener("click", async (event) => {
|
element("btnGenerate").addEventListener("click", async (event) => {
|
||||||
const { checked } = element("animation");
|
const { checked } = element("animation");
|
||||||
@ -1402,8 +1363,7 @@
|
|||||||
const response = element("response");
|
const response = element("response");
|
||||||
const recreatedImage = element("recreatedImage");
|
const recreatedImage = element("recreatedImage");
|
||||||
|
|
||||||
const urlImage =
|
const urlImage = !images ? URL.createObjectURL(file) : images;
|
||||||
images === "upload" ? URL.createObjectURL(file) : images;
|
|
||||||
|
|
||||||
const image = await loadImage(urlImage);
|
const image = await loadImage(urlImage);
|
||||||
const { canvas, bri, id, i } = recreate(image);
|
const { canvas, bri, id, i } = recreate(image);
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
<button type=submit id="b" onclick="window.location=getURL('/')">Back</button>
|
<button type=submit id="b" onclick="window.location=getURL('/')">Back</button>
|
||||||
<button type="submit" onclick="window.location=getURL('/settings/wifi')">WiFi Setup</button>
|
<button type="submit" onclick="window.location=getURL('/settings/wifi')">WiFi Setup</button>
|
||||||
<button type="submit" onclick="window.location=getURL('/settings/leds')">LED Preferences</button>
|
<button type="submit" onclick="window.location=getURL('/settings/leds')">LED Preferences</button>
|
||||||
<button id="2dbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/2D')">2D Configuration</button>
|
<button id="2dbtn" type="submit" onclick="window.location=getURL('/settings/2D')">2D Configuration</button>
|
||||||
<button type="submit" onclick="window.location=getURL('/settings/ui')">User Interface</button>
|
<button type="submit" onclick="window.location=getURL('/settings/ui')">User Interface</button>
|
||||||
<button id="dmxbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/dmx')">DMX Output</button>
|
<button id="dmxbtn" style="display:none;" type="submit" onclick="window.location=getURL('/settings/dmx')">DMX Output</button>
|
||||||
<button type="submit" onclick="window.location=getURL('/settings/sync')">Sync Interfaces</button>
|
<button type="submit" onclick="window.location=getURL('/settings/sync')">Sync Interfaces</button>
|
||||||
|
@ -773,6 +773,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
Brightness factor: <input name="BF" type="number" class="m" min="1" max="255" required> %
|
Brightness factor: <input name="BF" type="number" class="m" min="1" max="255" required> %
|
||||||
<h3>Transitions</h3>
|
<h3>Transitions</h3>
|
||||||
Crossfade: <input type="checkbox" name="TF"><br>
|
Crossfade: <input type="checkbox" name="TF"><br>
|
||||||
|
Effect blending: <input type="checkbox" name="EB"><br>
|
||||||
Transition Time: <input name="TD" type="number" class="xl" min="0" max="65500"> ms<br>
|
Transition Time: <input name="TD" type="number" class="xl" min="0" max="65500"> ms<br>
|
||||||
Enable Palette transitions: <input type="checkbox" name="PF"><br>
|
Enable Palette transitions: <input type="checkbox" name="PF"><br>
|
||||||
<i>Random Cycle</i> Palette Time: <input name="TP" type="number" class="m" min="1" max="255"> s<br>
|
<i>Random Cycle</i> Palette Time: <input name="TP" type="number" class="m" min="1" max="255"> s<br>
|
||||||
|
@ -63,7 +63,8 @@ class NeoGammaWLEDMethod {
|
|||||||
#define gamma32(c) NeoGammaWLEDMethod::Correct32(c)
|
#define gamma32(c) NeoGammaWLEDMethod::Correct32(c)
|
||||||
#define gamma8(c) NeoGammaWLEDMethod::rawGamma8(c)
|
#define gamma8(c) NeoGammaWLEDMethod::rawGamma8(c)
|
||||||
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
|
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
|
||||||
uint32_t color_add(uint32_t,uint32_t);
|
uint32_t color_add(uint32_t,uint32_t, bool fast=false);
|
||||||
|
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false);
|
||||||
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
||||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
||||||
void colorKtoRGB(uint16_t kelvin, byte* rgb);
|
void colorKtoRGB(uint16_t kelvin, byte* rgb);
|
||||||
@ -353,6 +354,7 @@ void checkSettingsPIN(const char *pin);
|
|||||||
uint16_t crc16(const unsigned char* data_p, size_t length);
|
uint16_t crc16(const unsigned char* data_p, size_t length);
|
||||||
um_data_t* simulateSound(uint8_t simulationId);
|
um_data_t* simulateSound(uint8_t simulationId);
|
||||||
void enumerateLedmaps();
|
void enumerateLedmaps();
|
||||||
|
uint8_t get_random_wheel_index(uint8_t pos);
|
||||||
|
|
||||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||||
//wled_eeprom.cpp
|
//wled_eeprom.cpp
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// Autogenerated from wled00/data/cpal/cpal.htm, do not edit!!
|
// Autogenerated from wled00/data/cpal/cpal.htm, do not edit!!
|
||||||
const uint16_t PAGE_cpal_L = 4721;
|
const uint16_t PAGE_cpal_L = 4721;
|
||||||
const uint8_t PAGE_cpal[] PROGMEM = {
|
const uint8_t PAGE_cpal[] PROGMEM = {
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6,
|
||||||
0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2,
|
0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2,
|
||||||
0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d,
|
0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d,
|
||||||
0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91,
|
0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91,
|
||||||
|
1564
wled00/html_other.h
1564
wled00/html_other.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2262
wled00/html_simple.h
2262
wled00/html_simple.h
File diff suppressed because it is too large
Load Diff
3999
wled00/html_ui.h
3999
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
|
|||||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||||
char vString[20];
|
char vString[20];
|
||||||
sprintf_P(vString, PSTR("0.14.0/%i"), VERSION);
|
sprintf_P(vString, PSTR("0.14.1-a1/%i"), VERSION);
|
||||||
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
|
||||||
|
|
||||||
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);
|
||||||
|
@ -165,6 +165,8 @@ void updateInterfaces(uint8_t callMode)
|
|||||||
|
|
||||||
sendDataWs();
|
sendDataWs();
|
||||||
lastInterfaceUpdate = millis();
|
lastInterfaceUpdate = millis();
|
||||||
|
interfaceUpdateCallMode = 0; //disable
|
||||||
|
|
||||||
if (callMode == CALL_MODE_WS_SEND) return;
|
if (callMode == CALL_MODE_WS_SEND) return;
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_ALEXA
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
@ -174,7 +176,6 @@ void updateInterfaces(uint8_t callMode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
doPublishMqtt = true;
|
doPublishMqtt = true;
|
||||||
interfaceUpdateCallMode = 0; //disable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,6 +247,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fadeTransition = request->hasArg(F("TF"));
|
fadeTransition = request->hasArg(F("TF"));
|
||||||
|
modeBlending = request->hasArg(F("EB"));
|
||||||
t = request->arg(F("TD")).toInt();
|
t = request->arg(F("TD")).toInt();
|
||||||
if (t >= 0) transitionDelayDefault = t;
|
if (t >= 0) transitionDelayDefault = t;
|
||||||
strip.paletteFade = request->hasArg(F("PF"));
|
strip.paletteFade = request->hasArg(F("PF"));
|
||||||
|
@ -382,8 +382,9 @@ void handleNotifications()
|
|||||||
}
|
}
|
||||||
if (version > 11) {
|
if (version > 11) {
|
||||||
// when applying synced options ignore selected as it may be used as indicator of which segments to sync
|
// when applying synced options ignore selected as it may be used as indicator of which segments to sync
|
||||||
// freeze, reset & transitional should never be synced
|
// freeze, reset should never be synced
|
||||||
selseg.options = (selseg.options & 0x0071U) | (udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0x8E); // ignore selected, freeze, reset & transitional
|
// LSB to MSB: select, reverse, on, mirror, freeze, reset, reverse_y, mirror_y, transpose, map1d2d (3), ssim (2), set (2)
|
||||||
|
selseg.options = (selseg.options & 0b0000000000110001U) | (udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0b11001110U); // ignore selected, freeze, reset
|
||||||
if (applyEffects) {
|
if (applyEffects) {
|
||||||
selseg.custom1 = udpIn[29+ofs];
|
selseg.custom1 = udpIn[29+ofs];
|
||||||
selseg.custom2 = udpIn[30+ofs];
|
selseg.custom2 = udpIn[30+ofs];
|
||||||
|
@ -416,9 +416,9 @@ uint16_t crc16(const unsigned char* data_p, size_t length) {
|
|||||||
// (only 2 used as stored in 1 bit in segment options, consider switching to a single global simulation type)
|
// (only 2 used as stored in 1 bit in segment options, consider switching to a single global simulation type)
|
||||||
typedef enum UM_SoundSimulations {
|
typedef enum UM_SoundSimulations {
|
||||||
UMS_BeatSin = 0,
|
UMS_BeatSin = 0,
|
||||||
UMS_WeWillRockYou
|
UMS_WeWillRockYou,
|
||||||
//UMS_10_13,
|
UMS_10_13,
|
||||||
//UMS_14_3
|
UMS_14_3
|
||||||
} um_soundSimulations_t;
|
} um_soundSimulations_t;
|
||||||
|
|
||||||
um_data_t* simulateSound(uint8_t simulationId)
|
um_data_t* simulateSound(uint8_t simulationId)
|
||||||
@ -503,7 +503,7 @@ um_data_t* simulateSound(uint8_t simulationId)
|
|||||||
fftResult[i] = 0;
|
fftResult[i] = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/*case UMS_10_3:
|
case UMS_10_13:
|
||||||
for (int i = 0; i<16; i++)
|
for (int i = 0; i<16; i++)
|
||||||
fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3);
|
fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3);
|
||||||
volumeSmth = fftResult[8];
|
volumeSmth = fftResult[8];
|
||||||
@ -512,7 +512,7 @@ um_data_t* simulateSound(uint8_t simulationId)
|
|||||||
for (int i = 0; i<16; i++)
|
for (int i = 0; i<16; i++)
|
||||||
fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3);
|
fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3);
|
||||||
volumeSmth = fftResult[8];
|
volumeSmth = fftResult[8];
|
||||||
break;*/
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
samplePeak = random8() > 250;
|
samplePeak = random8() > 250;
|
||||||
@ -573,3 +573,17 @@ void enumerateLedmaps() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a new, random color wheel index with a minimum distance of 42 from pos.
|
||||||
|
*/
|
||||||
|
uint8_t get_random_wheel_index(uint8_t pos) {
|
||||||
|
uint8_t r = 0, x = 0, y = 0, d = 0;
|
||||||
|
while (d < 42) {
|
||||||
|
r = random8();
|
||||||
|
x = abs(pos - r);
|
||||||
|
y = 255 - x;
|
||||||
|
d = MIN(x, y);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
@ -351,6 +351,7 @@ WLED_GLOBAL byte nightlightTargetBri _INIT(0); // brightness after nightlig
|
|||||||
WLED_GLOBAL byte nightlightDelayMins _INIT(60);
|
WLED_GLOBAL byte nightlightDelayMins _INIT(60);
|
||||||
WLED_GLOBAL byte nightlightMode _INIT(NL_MODE_FADE); // See const.h for available modes. Was nightlightFade
|
WLED_GLOBAL byte nightlightMode _INIT(NL_MODE_FADE); // See const.h for available modes. Was nightlightFade
|
||||||
WLED_GLOBAL bool fadeTransition _INIT(true); // enable crossfading color transition
|
WLED_GLOBAL bool fadeTransition _INIT(true); // enable crossfading color transition
|
||||||
|
WLED_GLOBAL bool modeBlending _INIT(true); // enable effect blending
|
||||||
WLED_GLOBAL uint16_t transitionDelay _INIT(750); // default crossfade duration in ms
|
WLED_GLOBAL uint16_t transitionDelay _INIT(750); // default crossfade duration in ms
|
||||||
|
|
||||||
WLED_GLOBAL byte briMultiplier _INIT(100); // % of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
|
WLED_GLOBAL byte briMultiplier _INIT(100); // % of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
|
||||||
|
@ -40,7 +40,7 @@ bool isIp(String str) {
|
|||||||
|
|
||||||
void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||||
if (!correctPIN) {
|
if (!correctPIN) {
|
||||||
if (final) request->send(500, "text/plain", FPSTR(s_unlock_cfg));
|
if (final) request->send(401, "text/plain", FPSTR(s_unlock_cfg));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!index) {
|
if (!index) {
|
||||||
@ -86,7 +86,7 @@ void createEditHandler(bool enable) {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
editHandler = &server.on("/edit", HTTP_ANY, [](AsyncWebServerRequest *request){
|
editHandler = &server.on("/edit", HTTP_ANY, [](AsyncWebServerRequest *request){
|
||||||
serveMessage(request, 500, "Access Denied", FPSTR(s_unlock_cfg), 254);
|
serveMessage(request, 401, "Access Denied", FPSTR(s_unlock_cfg), 254);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ void initServer()
|
|||||||
verboseResponse = deserializeState(root);
|
verboseResponse = deserializeState(root);
|
||||||
} else {
|
} else {
|
||||||
if (!correctPIN && strlen(settingsPIN)>0) {
|
if (!correctPIN && strlen(settingsPIN)>0) {
|
||||||
request->send(403, "application/json", F("{\"error\":1}")); // ERR_DENIED
|
request->send(401, "application/json", F("{\"error\":1}")); // ERR_DENIED
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -211,6 +211,8 @@ void initServer()
|
|||||||
|
|
||||||
if (verboseResponse) {
|
if (verboseResponse) {
|
||||||
if (!isConfig) {
|
if (!isConfig) {
|
||||||
|
lastInterfaceUpdate = millis(); // prevent WS update until cooldown
|
||||||
|
interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update
|
||||||
serveJson(request); return; //if JSON contains "v"
|
serveJson(request); return; //if JSON contains "v"
|
||||||
} else {
|
} else {
|
||||||
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
doSerializeConfig = true; //serializeConfig(); //Save new settings to FS
|
||||||
@ -282,7 +284,7 @@ void initServer()
|
|||||||
//init ota page
|
//init ota page
|
||||||
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||||
if (otaLock) {
|
if (otaLock) {
|
||||||
serveMessage(request, 500, "Access Denied", FPSTR(s_unlock_ota), 254);
|
serveMessage(request, 401, "Access Denied", FPSTR(s_unlock_ota), 254);
|
||||||
} else
|
} else
|
||||||
serveSettings(request); // checks for "upd" in URL and handles PIN
|
serveSettings(request); // checks for "upd" in URL and handles PIN
|
||||||
});
|
});
|
||||||
@ -292,7 +294,11 @@ void initServer()
|
|||||||
serveSettings(request, true); // handle PIN page POST request
|
serveSettings(request, true); // handle PIN page POST request
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Update.hasError() || otaLock) {
|
if (otaLock) {
|
||||||
|
serveMessage(request, 401, "Access Denied", FPSTR(s_unlock_ota), 254);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Update.hasError()) {
|
||||||
serveMessage(request, 500, F("Update failed!"), F("Please check your file and retry!"), 254);
|
serveMessage(request, 500, F("Update failed!"), F("Please check your file and retry!"), 254);
|
||||||
} else {
|
} else {
|
||||||
serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131);
|
serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131);
|
||||||
@ -533,7 +539,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) {
|
||||||
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
|
strcpy_P(buf, PSTR("alert('PIN incorrect.');"));
|
||||||
request->send(403, "application/javascript", buf);
|
request->send(401, "application/javascript", buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
strcat_P(buf,PSTR("function GetV(){var d=document;"));
|
||||||
@ -575,7 +581,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
|||||||
// if OTA locked or too frequent PIN entry requests fail hard
|
// if OTA locked or too frequent PIN entry requests fail hard
|
||||||
if ((subPage == SUBPAGE_WIFI && wifiLock && otaLock) || (post && !correctPIN && millis()-lastEditTime < PIN_RETRY_COOLDOWN))
|
if ((subPage == SUBPAGE_WIFI && wifiLock && otaLock) || (post && !correctPIN && millis()-lastEditTime < PIN_RETRY_COOLDOWN))
|
||||||
{
|
{
|
||||||
serveMessage(request, 500, "Access Denied", FPSTR(s_unlock_ota), 254); return;
|
serveMessage(request, 401, "Access Denied", FPSTR(s_unlock_ota), 254); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (post) { //settings/set POST request, saving
|
if (post) { //settings/set POST request, saving
|
||||||
@ -605,7 +611,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
|||||||
if (!s2[0]) strcpy_P(s2, s_redirecting);
|
if (!s2[0]) strcpy_P(s2, s_redirecting);
|
||||||
|
|
||||||
bool redirectAfter9s = (subPage == SUBPAGE_WIFI || ((subPage == SUBPAGE_SEC || subPage == SUBPAGE_UM) && doReboot));
|
bool redirectAfter9s = (subPage == SUBPAGE_WIFI || ((subPage == SUBPAGE_SEC || subPage == SUBPAGE_UM) && doReboot));
|
||||||
serveMessage(request, 200, s, s2, redirectAfter9s ? 129 : (correctPIN ? 1 : 3));
|
serveMessage(request, (correctPIN ? 200 : 401), s, s2, redirectAfter9s ? 129 : (correctPIN ? 1 : 3));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -633,7 +639,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
|||||||
serveMessage(request, 200, strlen(settingsPIN) > 0 ? PSTR("Settings locked") : PSTR("No PIN set"), FPSTR(s_redirecting), 1);
|
serveMessage(request, 200, strlen(settingsPIN) > 0 ? PSTR("Settings locked") : PSTR("No PIN set"), FPSTR(s_redirecting), 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case SUBPAGE_PINREQ : response = request->beginResponse_P(200, "text/html", PAGE_settings_pin, PAGE_settings_pin_length); break;
|
case SUBPAGE_PINREQ : response = request->beginResponse_P(401, "text/html", PAGE_settings_pin, PAGE_settings_pin_length); break;
|
||||||
case SUBPAGE_CSS : response = request->beginResponse_P(200, "text/css", PAGE_settingsCss, PAGE_settingsCss_length); break;
|
case SUBPAGE_CSS : response = request->beginResponse_P(200, "text/css", PAGE_settingsCss, PAGE_settingsCss_length); break;
|
||||||
case SUBPAGE_JS : serveSettingsJS(request); return;
|
case SUBPAGE_JS : serveSettingsJS(request); return;
|
||||||
case SUBPAGE_WELCOME : response = request->beginResponse_P(200, "text/html", PAGE_welcome, PAGE_welcome_length); break;
|
case SUBPAGE_WELCOME : response = request->beginResponse_P(200, "text/html", PAGE_welcome, PAGE_welcome_length); break;
|
||||||
|
@ -238,8 +238,8 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == SUBPAGE_MENU)
|
if (subPage == SUBPAGE_MENU)
|
||||||
{
|
{
|
||||||
#ifndef WLED_DISABLE_2D // include only if 2D is compiled in
|
#ifdef WLED_DISABLE_2D // include only if 2D is not compiled in
|
||||||
oappend(PSTR("gId('2dbtn').style.display='';"));
|
oappend(PSTR("gId('2dbtn').style.display='none';"));
|
||||||
#endif
|
#endif
|
||||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||||
oappend(PSTR("gId('dmxbtn').style.display='';"));
|
oappend(PSTR("gId('dmxbtn').style.display='';"));
|
||||||
@ -441,6 +441,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('c',SET_F("GC"),gammaCorrectCol);
|
sappend('c',SET_F("GC"),gammaCorrectCol);
|
||||||
dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS);
|
dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS);
|
||||||
sappend('c',SET_F("TF"),fadeTransition);
|
sappend('c',SET_F("TF"),fadeTransition);
|
||||||
|
sappend('c',SET_F("EB"),modeBlending);
|
||||||
sappend('v',SET_F("TD"),transitionDelayDefault);
|
sappend('v',SET_F("TD"),transitionDelayDefault);
|
||||||
sappend('c',SET_F("PF"),strip.paletteFade);
|
sappend('c',SET_F("PF"),strip.paletteFade);
|
||||||
sappend('v',SET_F("TP"),randomPaletteChangeTime);
|
sappend('v',SET_F("TP"),randomPaletteChangeTime);
|
||||||
@ -478,7 +479,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == SUBPAGE_SYNC)
|
if (subPage == SUBPAGE_SYNC)
|
||||||
{
|
{
|
||||||
char nS[32];
|
[[maybe_unused]] char nS[32];
|
||||||
sappend('v',SET_F("UP"),udpPort);
|
sappend('v',SET_F("UP"),udpPort);
|
||||||
sappend('v',SET_F("U2"),udpPort2);
|
sappend('v',SET_F("U2"),udpPort2);
|
||||||
sappend('v',SET_F("GS"),syncGroups);
|
sappend('v',SET_F("GS"),syncGroups);
|
||||||
|
Loading…
Reference in New Issue
Block a user