mirror of
https://github.com/wled/WLED.git
synced 2025-07-19 08:46:34 +00:00
Refactoring WS2812FX class.
- effect functions no longer part of class - methods to access private members - separate Segment, Segment_runtime, ColorTransition from WS2812FX
This commit is contained in:
parent
febd7cbca8
commit
64fd207533
@ -103,7 +103,7 @@ class Animated_Staircase : public Usermod {
|
|||||||
|
|
||||||
void updateSegments() {
|
void updateSegments() {
|
||||||
mainSegmentId = strip.getMainSegmentId();
|
mainSegmentId = strip.getMainSegmentId();
|
||||||
WS2812FX::Segment* segments = strip.getSegments();
|
Segment* segments = strip.getSegments();
|
||||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
||||||
if (!segments->isActive()) {
|
if (!segments->isActive()) {
|
||||||
maxSegmentId = i - 1;
|
maxSegmentId = i - 1;
|
||||||
@ -290,7 +290,7 @@ class Animated_Staircase : public Usermod {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Restore segment options
|
// Restore segment options
|
||||||
WS2812FX::Segment* segments = strip.getSegments();
|
Segment* segments = strip.getSegments();
|
||||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
||||||
if (!segments->isActive()) {
|
if (!segments->isActive()) {
|
||||||
maxSegmentId = i - 1;
|
maxSegmentId = i - 1;
|
||||||
|
@ -355,7 +355,7 @@ public:
|
|||||||
// Color in grayscale bitmaps if Segment 1 exists
|
// Color in grayscale bitmaps if Segment 1 exists
|
||||||
// TODO If secondary and tertiary are black, color all in primary,
|
// TODO If secondary and tertiary are black, color all in primary,
|
||||||
// else color first three from Seg 1 color slots and last three from Seg 2 color slots
|
// else color first three from Seg 1 color slots and last three from Seg 2 color slots
|
||||||
WS2812FX::Segment& seg1 = strip.getSegment(tubeSegment);
|
Segment& seg1 = strip.getSegment(tubeSegment);
|
||||||
if (seg1.isActive()) {
|
if (seg1.isActive()) {
|
||||||
digitColor = strip.getPixelColor(seg1.start + digit);
|
digitColor = strip.getPixelColor(seg1.start + digit);
|
||||||
dimming = seg1.opacity;
|
dimming = seg1.opacity;
|
||||||
|
@ -63,7 +63,7 @@ class ElekstubeIPSUsermod : public Usermod {
|
|||||||
if (!toki.isTick()) return;
|
if (!toki.isTick()) return;
|
||||||
updateLocalTime();
|
updateLocalTime();
|
||||||
|
|
||||||
WS2812FX::Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
||||||
if (seg1.isActive()) {
|
if (seg1.isActive()) {
|
||||||
bool update = false;
|
bool update = false;
|
||||||
if (seg1.opacity != lastBri) update = true;
|
if (seg1.opacity != lastBri) update = true;
|
||||||
|
@ -96,7 +96,7 @@ class StairwayWipeUsermod : public Usermod {
|
|||||||
resetTimebase(); //make sure wipe starts from beginning
|
resetTimebase(); //make sure wipe starts from beginning
|
||||||
|
|
||||||
//set wipe direction
|
//set wipe direction
|
||||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
Segment& seg = strip.getSegment(0);
|
||||||
bool doReverse = (userVar0 == 2);
|
bool doReverse = (userVar0 == 2);
|
||||||
seg.setOption(1, doReverse);
|
seg.setOption(1, doReverse);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ void startWipe()
|
|||||||
resetTimebase(); //make sure wipe starts from beginning
|
resetTimebase(); //make sure wipe starts from beginning
|
||||||
|
|
||||||
//set wipe direction
|
//set wipe direction
|
||||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
Segment& seg = strip.getSegment(0);
|
||||||
bool doReverse = (userVar0 == 2);
|
bool doReverse = (userVar0 == 2);
|
||||||
seg.setOption(1, doReverse);
|
seg.setOption(1, doReverse);
|
||||||
|
|
||||||
|
@ -528,12 +528,12 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
strip.setMode(i, effectCurrent);
|
strip.setMode(i, effectCurrent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
//Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -556,12 +556,12 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -584,12 +584,12 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -618,7 +618,7 @@ public:
|
|||||||
default: val = strip.getSegment(id).custom1 = max(min((increase ? strip.getSegment(id).custom1+fadeAmount : strip.getSegment(id).custom1-fadeAmount), 255), 0); break;
|
default: val = strip.getSegment(id).custom1 = max(min((increase ? strip.getSegment(id).custom1+fadeAmount : strip.getSegment(id).custom1-fadeAmount), 255), 0); break;
|
||||||
}
|
}
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || i == id) continue;
|
if (!seg.isActive() || i == id) continue;
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 3: strip.getSegment(i).custom3 = strip.getSegment(id).custom3; break;
|
case 3: strip.getSegment(i).custom3 = strip.getSegment(id).custom3; break;
|
||||||
@ -627,7 +627,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
|
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
|
||||||
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
|
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
|
||||||
@ -657,12 +657,12 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.palette = effectPalette;
|
seg.palette = effectPalette;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.palette = effectPalette;
|
seg.palette = effectPalette;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -686,12 +686,12 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -715,12 +715,12 @@ public:
|
|||||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -775,12 +775,12 @@ public:
|
|||||||
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
||||||
// if (applyToAll) {
|
// if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.setCCT(currentCCT, i);
|
seg.setCCT(currentCCT, i);
|
||||||
}
|
}
|
||||||
// } else {
|
// } else {
|
||||||
// WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
// Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
||||||
// }
|
// }
|
||||||
lampUdated();
|
lampUdated();
|
||||||
|
@ -27,14 +27,14 @@ saveMacro(1, "&FX=0&R=255&G=255&B=255", false);
|
|||||||
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||||
|
|
||||||
//select first two segments (background color + FX settable)
|
//select first two segments (background color + FX settable)
|
||||||
WS2812FX::Segment &seg = strip.getSegment(0);
|
Segment &seg = strip.getSegment(0);
|
||||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
||||||
strip.getSegment(0).setOption(0, false);
|
strip.getSegment(0).setOption(0, false);
|
||||||
strip.getSegment(0).setOption(2, false);
|
strip.getSegment(0).setOption(2, false);
|
||||||
//other segments are text
|
//other segments are text
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment &seg = strip.getSegment(i);
|
Segment &seg = strip.getSegment(i);
|
||||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
||||||
strip.getSegment(i).setOption(0, true);
|
strip.getSegment(i).setOption(0, true);
|
||||||
strip.setBrightness(128);
|
strip.setBrightness(128);
|
||||||
@ -50,7 +50,7 @@ void selectWordSegments(bool state)
|
|||||||
{
|
{
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
{
|
{
|
||||||
//WS2812FX::Segment &seg = strip.getSegment(i);
|
//Segment &seg = strip.getSegment(i);
|
||||||
strip.getSegment(i).setOption(0, state);
|
strip.getSegment(i).setOption(0, state);
|
||||||
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||||
//seg.mode = 12;
|
//seg.mode = 12;
|
||||||
|
2313
wled00/FX.cpp
2313
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
690
wled00/FX.h
690
wled00/FX.h
@ -54,10 +54,15 @@
|
|||||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//colors.cpp (.h does not like including other .h)
|
||||||
|
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16);
|
||||||
|
uint32_t color_add(uint32_t,uint32_t);
|
||||||
|
|
||||||
/* Not used in all effects yet */
|
/* Not used in all effects yet */
|
||||||
#define WLED_FPS 42
|
#define WLED_FPS 42
|
||||||
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
||||||
#define FRAMETIME _frametime
|
//#define FRAMETIME _frametime
|
||||||
|
#define FRAMETIME strip.getFrameTime()
|
||||||
|
|
||||||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
|
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
|
||||||
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
||||||
@ -82,11 +87,14 @@
|
|||||||
#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
|
#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
|
||||||
|
|
||||||
#define NUM_COLORS 3 /* number of colors per segment */
|
#define NUM_COLORS 3 /* number of colors per segment */
|
||||||
#define SEGMENT _segments[_segment_index]
|
//#define SEGMENT _segments[_segment_index]
|
||||||
#define SEGCOLOR(x) _colors_t[x]
|
//#define SEGCOLOR(x) _colors_t[x]
|
||||||
#define SEGENV _segment_runtimes[_segment_index]
|
//#define SEGENV _segment_runtimes[_segment_index]
|
||||||
#define SEGLEN _virtualSegmentLength
|
//#define SEGLEN _virtualSegmentLength
|
||||||
#define SEGACT SEGMENT.stop
|
#define SEGMENT strip.getSegment(strip.getCurrSegmentId())
|
||||||
|
#define SEGENV strip.getSegmentRuntime(strip.getCurrSegmentId())
|
||||||
|
#define SEGCOLOR(x) strip.segColor(x)
|
||||||
|
#define SEGLEN strip.segLen()
|
||||||
#define SPEED_FORMULA_L 5U + (50U*(255U - SEGMENT.speed))/SEGLEN
|
#define SPEED_FORMULA_L 5U + (50U*(255U - SEGMENT.speed))/SEGLEN
|
||||||
|
|
||||||
// some common colors
|
// some common colors
|
||||||
@ -110,15 +118,15 @@
|
|||||||
// bit 2: segment is on
|
// bit 2: segment is on
|
||||||
// bit 1: reverse segment
|
// bit 1: reverse segment
|
||||||
// bit 0: segment is selected
|
// bit 0: segment is selected
|
||||||
#define NO_OPTIONS (uint8_t)0x00
|
#define NO_OPTIONS (uint16_t)0x0000
|
||||||
#define TRANSPOSED (uint8_t)0x400 // rotated 90deg & reversed
|
#define TRANSPOSED (uint16_t)0x0400 // rotated 90deg & reversed
|
||||||
#define REVERSE_Y_2D (uint8_t)0x200
|
#define REVERSE_Y_2D (uint16_t)0x0200
|
||||||
#define MIRROR_Y_2D (uint8_t)0x100
|
#define MIRROR_Y_2D (uint16_t)0x0100
|
||||||
#define TRANSITIONAL (uint8_t)0x080
|
#define TRANSITIONAL (uint16_t)0x0080
|
||||||
#define MIRROR (uint8_t)0x008
|
#define MIRROR (uint16_t)0x0008
|
||||||
#define SEGMENT_ON (uint8_t)0x004
|
#define SEGMENT_ON (uint16_t)0x0004
|
||||||
#define REVERSE (uint8_t)0x002
|
#define REVERSE (uint16_t)0x0002
|
||||||
#define SELECTED (uint8_t)0x001
|
#define SELECTED (uint16_t)0x0001
|
||||||
|
|
||||||
#define FX_MODE_STATIC 0
|
#define FX_MODE_STATIC 0
|
||||||
#define FX_MODE_BLINK 1
|
#define FX_MODE_BLINK 1
|
||||||
@ -359,249 +367,98 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class WS2812FX {
|
// segment parameters
|
||||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
typedef struct Segment { // 35 (36 in memory) bytes
|
||||||
|
uint16_t start; // start index / start X coordinate 2D (left)
|
||||||
|
uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
|
||||||
|
uint16_t offset;
|
||||||
|
uint8_t speed;
|
||||||
|
uint8_t intensity;
|
||||||
|
uint8_t palette;
|
||||||
|
uint8_t mode;
|
||||||
|
uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
|
||||||
|
uint8_t grouping, spacing;
|
||||||
|
uint8_t opacity;
|
||||||
|
uint32_t colors[NUM_COLORS];
|
||||||
|
uint8_t cct; //0==1900K, 255==10091K
|
||||||
|
uint8_t _capabilities;
|
||||||
|
uint8_t custom1, custom2, custom3; // custom FX parameters
|
||||||
|
uint16_t startY; // start Y coodrinate 2D (top)
|
||||||
|
uint16_t stopY; // stop Y coordinate 2D (bottom)
|
||||||
|
char *name;
|
||||||
|
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
|
||||||
|
inline bool isSelected() { return getOption(0); }
|
||||||
|
inline bool isActive() { return stop > start; }
|
||||||
|
inline uint16_t width() { return stop - start; }
|
||||||
|
inline uint16_t height() { return stopY - startY; }
|
||||||
|
inline uint16_t length() { return width(); }
|
||||||
|
inline uint16_t groupLength() { return grouping + spacing; }
|
||||||
|
inline uint8_t getLightCapabilities() { return _capabilities; }
|
||||||
|
bool setColor(uint8_t slot, uint32_t c, uint8_t segn); //returns true if changed
|
||||||
|
void setCCT(uint16_t k, uint8_t segn);
|
||||||
|
void setOpacity(uint8_t o, uint8_t segn);
|
||||||
|
void setOption(uint8_t n, bool val, uint8_t segn = 255);
|
||||||
|
// 2D matrix
|
||||||
|
uint16_t virtualWidth();
|
||||||
|
uint16_t virtualHeight();
|
||||||
|
// 1D strip
|
||||||
|
uint16_t virtualLength();
|
||||||
|
uint8_t differs(Segment& b);
|
||||||
|
void refreshLightCapabilities();
|
||||||
|
} segment;
|
||||||
|
|
||||||
// pre show callback
|
|
||||||
typedef void (*show_callback) (void);
|
// segment runtime parameters
|
||||||
|
typedef struct Segment_runtime { // 28 bytes
|
||||||
|
unsigned long next_time; // millis() of next update
|
||||||
|
uint32_t step; // custom "step" var
|
||||||
|
uint32_t call; // call counter
|
||||||
|
uint16_t aux0; // custom var
|
||||||
|
uint16_t aux1; // custom var
|
||||||
|
byte* data = nullptr;
|
||||||
|
|
||||||
|
bool allocateData(uint16_t len);
|
||||||
|
void deallocateData();
|
||||||
|
void resetIfRequired();
|
||||||
|
/**
|
||||||
|
* Flags that before the next effect is calculated,
|
||||||
|
* the internal segment state should be reset.
|
||||||
|
* Call resetIfRequired before calling the next effect function.
|
||||||
|
* Safe to call from interrupts and network requests.
|
||||||
|
*/
|
||||||
|
inline void markForReset() { _requiresReset = true; }
|
||||||
|
private:
|
||||||
|
uint16_t _dataLen = 0;
|
||||||
|
bool _requiresReset = false;
|
||||||
|
} segment_runtime;
|
||||||
|
|
||||||
|
|
||||||
|
// color transitions
|
||||||
|
typedef struct ColorTransition { // 12 bytes
|
||||||
|
uint32_t colorOld = 0;
|
||||||
|
uint32_t transitionStart;
|
||||||
|
uint16_t transitionDur;
|
||||||
|
uint8_t segment = 0xFF; //lower 6 bits: the segment this transition is for (255 indicates transition not in use/available) upper 2 bits: color channel
|
||||||
|
uint8_t briOld = 0;
|
||||||
|
|
||||||
|
static void startTransition(uint8_t oldBri, uint32_t oldCol, uint8_t segn, uint8_t slot);
|
||||||
|
uint8_t currentBri(bool turningOff = false, uint8_t slot = 0);
|
||||||
|
uint16_t progress(bool allowEnd = false); //transition progression between 0-65535
|
||||||
|
uint32_t currentColor(uint32_t colorNew) {
|
||||||
|
return color_blend(colorOld, colorNew, progress(true), true);
|
||||||
|
}
|
||||||
|
} color_transition;
|
||||||
|
|
||||||
|
|
||||||
|
// main "strip" class
|
||||||
|
class WS2812FX {
|
||||||
|
typedef uint16_t (*mode_ptr)(void); // pointer to mode function
|
||||||
|
typedef void (*show_callback)(void); // pre show callback
|
||||||
|
|
||||||
static WS2812FX* instance;
|
static WS2812FX* instance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// segment parameters
|
|
||||||
typedef struct Segment { // 35 (36 in memory) bytes
|
|
||||||
uint16_t start; // start index / start X coordinate 2D (left)
|
|
||||||
uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
|
|
||||||
uint16_t offset;
|
|
||||||
uint8_t speed;
|
|
||||||
uint8_t intensity;
|
|
||||||
uint8_t palette;
|
|
||||||
uint8_t mode;
|
|
||||||
uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
|
|
||||||
uint8_t grouping, spacing;
|
|
||||||
uint8_t opacity;
|
|
||||||
uint32_t colors[NUM_COLORS];
|
|
||||||
uint8_t cct; //0==1900K, 255==10091K
|
|
||||||
uint8_t _capabilities;
|
|
||||||
uint8_t custom1, custom2, custom3; // custom FX parameters
|
|
||||||
uint16_t startY; // start Y coodrinate 2D (top)
|
|
||||||
uint16_t stopY; // stop Y coordinate 2D (bottom)
|
|
||||||
char *name;
|
|
||||||
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
|
|
||||||
inline bool isSelected() { return getOption(0); }
|
|
||||||
inline bool isActive() { return stop > start; }
|
|
||||||
inline uint16_t width() { return stop - start; }
|
|
||||||
inline uint16_t height() { return stopY - startY; }
|
|
||||||
inline uint16_t length() { return width(); }
|
|
||||||
inline uint16_t groupLength() { return grouping + spacing; }
|
|
||||||
inline uint8_t getLightCapabilities() { return _capabilities; }
|
|
||||||
bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
|
|
||||||
if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;
|
|
||||||
if (c == colors[slot]) return false;
|
|
||||||
uint8_t b = (slot == 1) ? cct : opacity;
|
|
||||||
ColorTransition::startTransition(b, colors[slot], instance->_transitionDur, segn, slot);
|
|
||||||
colors[slot] = c; return true;
|
|
||||||
}
|
|
||||||
void setCCT(uint16_t k, uint8_t segn) {
|
|
||||||
if (segn >= MAX_NUM_SEGMENTS) return;
|
|
||||||
if (k > 255) { //kelvin value, convert to 0-255
|
|
||||||
if (k < 1900) k = 1900;
|
|
||||||
if (k > 10091) k = 10091;
|
|
||||||
k = (k - 1900) >> 5;
|
|
||||||
}
|
|
||||||
if (cct == k) return;
|
|
||||||
ColorTransition::startTransition(cct, colors[1], instance->_transitionDur, segn, 1);
|
|
||||||
cct = k;
|
|
||||||
}
|
|
||||||
void setOpacity(uint8_t o, uint8_t segn) {
|
|
||||||
if (segn >= MAX_NUM_SEGMENTS) return;
|
|
||||||
if (opacity == o) return;
|
|
||||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
|
||||||
opacity = o;
|
|
||||||
}
|
|
||||||
void setOption(uint8_t n, bool val, uint8_t segn = 255) {
|
|
||||||
bool prevOn = false;
|
|
||||||
if (n == SEG_OPTION_ON) {
|
|
||||||
prevOn = getOption(SEG_OPTION_ON);
|
|
||||||
if (!val && prevOn) { //fade off
|
|
||||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val) options |= 0x01 << n;
|
|
||||||
else options &= ~(0x01 << n);
|
|
||||||
if (n == SEG_OPTION_ON && val && !prevOn) { //fade on
|
|
||||||
ColorTransition::startTransition(0, colors[0], instance->_transitionDur, segn, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2D matrix
|
|
||||||
uint16_t virtualWidth() {
|
|
||||||
uint16_t groupLen = groupLength();
|
|
||||||
uint16_t vWidth = ((getOption(SEG_OPTION_TRANSPOSED) ? height() : width()) + groupLen - 1) / groupLen;
|
|
||||||
if (getOption(SEG_OPTION_MIRROR)) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
|
||||||
return vWidth;
|
|
||||||
}
|
|
||||||
uint16_t virtualHeight() {
|
|
||||||
uint16_t groupLen = groupLength();
|
|
||||||
uint16_t vHeight = ((getOption(SEG_OPTION_TRANSPOSED) ? width() : height()) + groupLen - 1) / groupLen;
|
|
||||||
if (getOption(SEG_OPTION_MIRROR_Y)) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
|
||||||
return vHeight;
|
|
||||||
}
|
|
||||||
// 1D strip
|
|
||||||
uint16_t virtualLength() {
|
|
||||||
uint16_t groupLen = groupLength();
|
|
||||||
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
|
||||||
if (getOption(SEG_OPTION_MIRROR)) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
|
||||||
return vLength;
|
|
||||||
}
|
|
||||||
uint8_t differs(Segment& b);
|
|
||||||
void refreshLightCapabilities();
|
|
||||||
} segment;
|
|
||||||
|
|
||||||
// segment runtime parameters
|
|
||||||
typedef struct Segment_runtime { // 28 bytes
|
|
||||||
unsigned long next_time; // millis() of next update
|
|
||||||
uint32_t step; // custom "step" var
|
|
||||||
uint32_t call; // call counter
|
|
||||||
uint16_t aux0; // custom var
|
|
||||||
uint16_t aux1; // custom var
|
|
||||||
byte* data = nullptr;
|
|
||||||
bool allocateData(uint16_t len){
|
|
||||||
if (data && _dataLen == len) return true; //already allocated
|
|
||||||
deallocateData();
|
|
||||||
if (WS2812FX::instance->_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
|
||||||
// if possible use SPI RAM on ESP32
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
|
||||||
if (psramFound())
|
|
||||||
data = (byte*) ps_malloc(len);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
data = (byte*) malloc(len);
|
|
||||||
if (!data) return false; //allocation failed
|
|
||||||
WS2812FX::instance->_usedSegmentData += len;
|
|
||||||
_dataLen = len;
|
|
||||||
memset(data, 0, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void deallocateData(){
|
|
||||||
free(data);
|
|
||||||
data = nullptr;
|
|
||||||
WS2812FX::instance->_usedSegmentData -= _dataLen;
|
|
||||||
_dataLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If reset of this segment was request, clears runtime
|
|
||||||
* settings of this segment.
|
|
||||||
* Must not be called while an effect mode function is running
|
|
||||||
* because it could access the data buffer and this method
|
|
||||||
* may free that data buffer.
|
|
||||||
*/
|
|
||||||
void resetIfRequired() {
|
|
||||||
if (_requiresReset) {
|
|
||||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
|
||||||
deallocateData();
|
|
||||||
_requiresReset = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flags that before the next effect is calculated,
|
|
||||||
* the internal segment state should be reset.
|
|
||||||
* Call resetIfRequired before calling the next effect function.
|
|
||||||
* Safe to call from interrupts and network requests.
|
|
||||||
*/
|
|
||||||
inline void markForReset() { _requiresReset = true; }
|
|
||||||
private:
|
|
||||||
uint16_t _dataLen = 0;
|
|
||||||
bool _requiresReset = false;
|
|
||||||
} segment_runtime;
|
|
||||||
|
|
||||||
typedef struct ColorTransition { // 12 bytes
|
|
||||||
uint32_t colorOld = 0;
|
|
||||||
uint32_t transitionStart;
|
|
||||||
uint16_t transitionDur;
|
|
||||||
uint8_t segment = 0xFF; //lower 6 bits: the segment this transition is for (255 indicates transition not in use/available) upper 2 bits: color channel
|
|
||||||
uint8_t briOld = 0;
|
|
||||||
static void startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot) {
|
|
||||||
if (segn >= MAX_NUM_SEGMENTS || slot >= NUM_COLORS || dur == 0) return;
|
|
||||||
if (instance->_brightness == 0) return; //do not need transitions if master bri is off
|
|
||||||
if (!instance->_segments[segn].getOption(SEG_OPTION_ON)) return; //not if segment is off either
|
|
||||||
uint8_t tIndex = 0xFF; //none found
|
|
||||||
uint16_t tProgression = 0;
|
|
||||||
uint8_t s = segn + (slot << 6); //merge slot and segment into one byte
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) {
|
|
||||||
uint8_t tSeg = instance->transitions[i].segment;
|
|
||||||
//see if this segment + color already has a running transition
|
|
||||||
if (tSeg == s) {
|
|
||||||
tIndex = i; break;
|
|
||||||
}
|
|
||||||
if (tSeg == 0xFF) { //free transition
|
|
||||||
tIndex = i; tProgression = 0xFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tIndex == 0xFF) { //no slot found yet
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) {
|
|
||||||
//find most progressed transition to overwrite
|
|
||||||
uint16_t prog = instance->transitions[i].progress();
|
|
||||||
if (prog > tProgression) {
|
|
||||||
tIndex = i; tProgression = prog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorTransition& t = instance->transitions[tIndex];
|
|
||||||
if (t.segment == s) //this is an active transition on the same segment+color
|
|
||||||
{
|
|
||||||
bool wasTurningOff = (oldBri == 0);
|
|
||||||
t.briOld = t.currentBri(wasTurningOff, slot);
|
|
||||||
t.colorOld = t.currentColor(oldCol);
|
|
||||||
} else {
|
|
||||||
t.briOld = oldBri;
|
|
||||||
t.colorOld = oldCol;
|
|
||||||
uint8_t prevSeg = t.segment & 0x3F;
|
|
||||||
if (prevSeg < MAX_NUM_SEGMENTS) instance->_segments[prevSeg].setOption(SEG_OPTION_TRANSITIONAL, false);
|
|
||||||
}
|
|
||||||
t.transitionDur = dur;
|
|
||||||
t.transitionStart = millis();
|
|
||||||
t.segment = s;
|
|
||||||
instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, true);
|
|
||||||
//refresh immediately, required for Solid mode
|
|
||||||
if (instance->_segment_runtimes[segn].next_time > t.transitionStart + 22) instance->_segment_runtimes[segn].next_time = t.transitionStart;
|
|
||||||
}
|
|
||||||
uint16_t progress(bool allowEnd = false) { //transition progression between 0-65535
|
|
||||||
uint32_t timeNow = millis();
|
|
||||||
if (timeNow - transitionStart > transitionDur) {
|
|
||||||
if (allowEnd) {
|
|
||||||
uint8_t segn = segment & 0x3F;
|
|
||||||
if (segn < MAX_NUM_SEGMENTS) instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, false);
|
|
||||||
segment = 0xFF;
|
|
||||||
}
|
|
||||||
return 0xFFFF;
|
|
||||||
}
|
|
||||||
uint32_t elapsed = timeNow - transitionStart;
|
|
||||||
uint32_t prog = elapsed * 0xFFFF / transitionDur;
|
|
||||||
return (prog > 0xFFFF) ? 0xFFFF : prog;
|
|
||||||
}
|
|
||||||
uint32_t currentColor(uint32_t colorNew) {
|
|
||||||
return instance->color_blend(colorOld, colorNew, progress(true), true);
|
|
||||||
}
|
|
||||||
uint8_t currentBri(bool turningOff = false, uint8_t slot = 0) {
|
|
||||||
uint8_t segn = segment & 0x3F;
|
|
||||||
if (segn >= MAX_NUM_SEGMENTS) return 0;
|
|
||||||
uint8_t briNew = instance->_segments[segn].opacity;
|
|
||||||
if (slot == 0) {
|
|
||||||
if (!instance->_segments[segn].getOption(SEG_OPTION_ON) || turningOff) briNew = 0;
|
|
||||||
} else { //transition slot 1 brightness for CCT transition
|
|
||||||
briNew = instance->_segments[segn].cct;
|
|
||||||
}
|
|
||||||
uint32_t prog = progress() + 1;
|
|
||||||
return ((briNew * prog) + (briOld * (0x10000 - prog))) >> 16;
|
|
||||||
}
|
|
||||||
} color_transition;
|
|
||||||
|
|
||||||
WS2812FX() {
|
WS2812FX() {
|
||||||
WS2812FX::instance = this;
|
WS2812FX::instance = this;
|
||||||
setupEffectData();
|
setupEffectData();
|
||||||
@ -614,6 +471,8 @@ class WS2812FX {
|
|||||||
resetSegments();
|
resetSegments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WS2812FX* getInstance(void) { return instance; }
|
||||||
|
|
||||||
void
|
void
|
||||||
finalizeInit(),
|
finalizeInit(),
|
||||||
service(void),
|
service(void),
|
||||||
@ -627,11 +486,8 @@ class WS2812FX {
|
|||||||
setCCT(uint16_t k),
|
setCCT(uint16_t k),
|
||||||
setBrightness(uint8_t b, bool direct = false),
|
setBrightness(uint8_t b, bool direct = false),
|
||||||
setRange(uint16_t i, uint16_t i2, uint32_t col),
|
setRange(uint16_t i, uint16_t i2, uint32_t col),
|
||||||
setShowCallback(show_callback cb),
|
|
||||||
setTransition(uint16_t t),
|
|
||||||
setTransitionMode(bool t),
|
setTransitionMode(bool t),
|
||||||
calcGammaTable(float),
|
calcGammaTable(float),
|
||||||
trigger(void),
|
|
||||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=0),
|
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=0),
|
||||||
setMainSegmentId(uint8_t n),
|
setMainSegmentId(uint8_t n),
|
||||||
restartRuntime(),
|
restartRuntime(),
|
||||||
@ -640,6 +496,7 @@ class WS2812FX {
|
|||||||
fixInvalidSegments(),
|
fixInvalidSegments(),
|
||||||
setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||||
setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = false),
|
setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = false),
|
||||||
|
blendPixelColor(uint16_t n, uint32_t color, uint8_t blend),
|
||||||
show(void),
|
show(void),
|
||||||
setTargetFps(uint8_t fps),
|
setTargetFps(uint8_t fps),
|
||||||
deserializeMap(uint8_t n=0);
|
deserializeMap(uint8_t n=0);
|
||||||
@ -652,6 +509,9 @@ class WS2812FX {
|
|||||||
inline void setPixelColor(int n, CRGB c) {setPixelColor(n, c.red, c.green, c.blue);}
|
inline void setPixelColor(int n, CRGB c) {setPixelColor(n, c.red, c.green, c.blue);}
|
||||||
inline void setPixelColor(float i, uint32_t c, bool aa=true) {setPixelColor(i, byte(c>>16), byte(c>>8), byte(c), byte(c>>24), aa);}
|
inline void setPixelColor(float i, uint32_t c, bool aa=true) {setPixelColor(i, byte(c>>16), byte(c>>8), byte(c), byte(c>>24), aa);}
|
||||||
inline void setPixelColor(float i, CRGB c, bool aa=true) {setPixelColor(i, c.red, c.green, c.blue, 0, aa);}
|
inline void setPixelColor(float i, CRGB c, bool aa=true) {setPixelColor(i, c.red, c.green, c.blue, 0, aa);}
|
||||||
|
inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments.
|
||||||
|
inline void setShowCallback(show_callback cb) { _callback = cb; }
|
||||||
|
inline void setTransition(uint16_t t) { _transitionDur = t; }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
gammaCorrectBri = false,
|
gammaCorrectBri = false,
|
||||||
@ -662,24 +522,28 @@ class WS2812FX {
|
|||||||
// return true if the strip is being sent pixel updates
|
// return true if the strip is being sent pixel updates
|
||||||
isUpdating(void);
|
isUpdating(void);
|
||||||
|
|
||||||
|
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
||||||
|
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
paletteFade = 0,
|
paletteFade = 0,
|
||||||
paletteBlend = 0,
|
paletteBlend = 0,
|
||||||
milliampsPerLed = 55,
|
milliampsPerLed = 55,
|
||||||
cctBlending = 0,
|
cctBlending = 0,
|
||||||
getBrightness(void),
|
|
||||||
getPaletteCount(void),
|
|
||||||
getMaxSegments(void),
|
|
||||||
getActiveSegmentsNum(void),
|
getActiveSegmentsNum(void),
|
||||||
getFirstSelectedSegId(void),
|
getFirstSelectedSegId(void),
|
||||||
getMainSegmentId(void),
|
|
||||||
getLastActiveSegmentId(void),
|
getLastActiveSegmentId(void),
|
||||||
getTargetFps(void),
|
|
||||||
setPixelSegment(uint8_t n),
|
setPixelSegment(uint8_t n),
|
||||||
gamma8(uint8_t),
|
gamma8(uint8_t),
|
||||||
gamma8_cal(uint8_t, float),
|
gamma8_cal(uint8_t, float),
|
||||||
get_random_wheel_index(uint8_t);
|
get_random_wheel_index(uint8_t);
|
||||||
|
|
||||||
|
inline uint8_t getBrightness(void) { return _brightness; }
|
||||||
|
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; }
|
||||||
|
inline uint8_t getCurrSegmentId(void) { return _segment_index; }
|
||||||
|
inline uint8_t getMainSegmentId(void) { return _mainSegment; }
|
||||||
|
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; }
|
||||||
|
inline uint8_t getTargetFps() { return _targetFps; }
|
||||||
inline uint8_t getModeCount() { return _modeCount; }
|
inline uint8_t getModeCount() { return _modeCount; }
|
||||||
inline uint8_t sin_gap(uint16_t in) {
|
inline uint8_t sin_gap(uint16_t in) {
|
||||||
if (in & 0x100) return 0;
|
if (in & 0x100) return 0;
|
||||||
@ -693,165 +557,39 @@ class WS2812FX {
|
|||||||
ablMilliampsMax,
|
ablMilliampsMax,
|
||||||
currentMilliamps,
|
currentMilliamps,
|
||||||
triwave16(uint16_t),
|
triwave16(uint16_t),
|
||||||
getLengthTotal(void),
|
|
||||||
getLengthPhysical(void),
|
getLengthPhysical(void),
|
||||||
getFps();
|
getFps();
|
||||||
|
|
||||||
inline uint16_t getMinShowDelay() { return MIN_SHOW_DELAY; }
|
inline uint16_t getFrameTime(void) { return _frametime; }
|
||||||
|
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
||||||
|
inline uint16_t getLengthTotal(void) { return _length; }
|
||||||
|
inline uint16_t segLen(void) { return _virtualSegmentLength; }
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
now,
|
now,
|
||||||
timebase,
|
timebase,
|
||||||
color_wheel(uint8_t),
|
color_wheel(uint8_t),
|
||||||
color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
|
color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
|
||||||
color_blend(uint32_t,uint32_t,uint16_t,bool b16=false),
|
|
||||||
color_add(uint32_t,uint32_t),
|
|
||||||
currentColor(uint32_t colorNew, uint8_t tNr),
|
currentColor(uint32_t colorNew, uint8_t tNr),
|
||||||
gamma32(uint32_t),
|
gamma32(uint32_t),
|
||||||
getLastShow(void),
|
|
||||||
getPixelColor(uint16_t);
|
getPixelColor(uint16_t);
|
||||||
|
|
||||||
|
inline uint32_t getLastShow(void) { return _lastShow; }
|
||||||
|
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; }
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
getModeData(uint8_t id = 0) { return id<_modeCount ? _modeData[id] : nullptr; }
|
getModeData(uint8_t id = 0) { return id<_modeCount ? _modeData[id] : nullptr; }
|
||||||
|
|
||||||
const char **
|
const char **
|
||||||
getModeDataSrc(void) { return _modeData; }
|
getModeDataSrc(void) { return _modeData; }
|
||||||
|
|
||||||
WS2812FX::Segment
|
inline Segment& getSegment(uint8_t id) { return _segments[id >= MAX_NUM_SEGMENTS ? getMainSegmentId() : id]; }
|
||||||
&getSegment(uint8_t n),
|
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
|
||||||
&getFirstSelectedSeg(void),
|
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
||||||
&getMainSegment(void);
|
inline Segment* getSegments(void) { return _segments; }
|
||||||
|
inline Segment_runtime& getSegmentRuntime(uint8_t id) { return _segment_runtimes[id >= MAX_NUM_SEGMENTS ? getMainSegmentId() : id]; }
|
||||||
|
|
||||||
WS2812FX::Segment*
|
// 2D support (panels)
|
||||||
getSegments(void);
|
|
||||||
|
|
||||||
// builtin modes
|
|
||||||
uint16_t
|
|
||||||
mode_static(void),
|
|
||||||
mode_blink(void),
|
|
||||||
mode_blink_rainbow(void),
|
|
||||||
mode_strobe(void),
|
|
||||||
mode_strobe_rainbow(void),
|
|
||||||
mode_color_wipe(void),
|
|
||||||
mode_color_sweep(void),
|
|
||||||
mode_color_wipe_random(void),
|
|
||||||
mode_color_sweep_random(void),
|
|
||||||
mode_random_color(void),
|
|
||||||
mode_dynamic(void),
|
|
||||||
mode_breath(void),
|
|
||||||
mode_fade(void),
|
|
||||||
mode_scan(void),
|
|
||||||
mode_dual_scan(void),
|
|
||||||
mode_theater_chase(void),
|
|
||||||
mode_theater_chase_rainbow(void),
|
|
||||||
mode_rainbow(void),
|
|
||||||
mode_rainbow_cycle(void),
|
|
||||||
mode_running_lights(void),
|
|
||||||
mode_saw(void),
|
|
||||||
mode_twinkle(void),
|
|
||||||
mode_dissolve(void),
|
|
||||||
mode_dissolve_random(void),
|
|
||||||
mode_sparkle(void),
|
|
||||||
mode_flash_sparkle(void),
|
|
||||||
mode_hyper_sparkle(void),
|
|
||||||
mode_multi_strobe(void),
|
|
||||||
mode_android(void),
|
|
||||||
mode_chase_color(void),
|
|
||||||
mode_chase_random(void),
|
|
||||||
mode_chase_rainbow(void),
|
|
||||||
mode_chase_flash(void),
|
|
||||||
mode_chase_flash_random(void),
|
|
||||||
mode_chase_rainbow_white(void),
|
|
||||||
mode_colorful(void),
|
|
||||||
mode_traffic_light(void),
|
|
||||||
mode_running_color(void),
|
|
||||||
mode_aurora(void),
|
|
||||||
mode_running_random(void),
|
|
||||||
mode_larson_scanner(void),
|
|
||||||
mode_comet(void),
|
|
||||||
mode_fireworks(void),
|
|
||||||
mode_rain(void),
|
|
||||||
mode_tetrix(void),
|
|
||||||
mode_halloween(void),
|
|
||||||
mode_fire_flicker(void),
|
|
||||||
mode_gradient(void),
|
|
||||||
mode_loading(void),
|
|
||||||
mode_police(void),
|
|
||||||
mode_fairy(void),
|
|
||||||
mode_two_dots(void),
|
|
||||||
mode_fairytwinkle(void),
|
|
||||||
mode_running_dual(void),
|
|
||||||
mode_bicolor_chase(void),
|
|
||||||
mode_tricolor_chase(void),
|
|
||||||
mode_tricolor_wipe(void),
|
|
||||||
mode_tricolor_fade(void),
|
|
||||||
mode_lightning(void),
|
|
||||||
mode_icu(void),
|
|
||||||
mode_multi_comet(void),
|
|
||||||
mode_dual_larson_scanner(void),
|
|
||||||
mode_random_chase(void),
|
|
||||||
mode_oscillate(void),
|
|
||||||
mode_fire_2012(void),
|
|
||||||
mode_pride_2015(void),
|
|
||||||
mode_bpm(void),
|
|
||||||
mode_juggle(void),
|
|
||||||
mode_palette(void),
|
|
||||||
mode_colorwaves(void),
|
|
||||||
mode_fillnoise8(void),
|
|
||||||
mode_noise16_1(void),
|
|
||||||
mode_noise16_2(void),
|
|
||||||
mode_noise16_3(void),
|
|
||||||
mode_noise16_4(void),
|
|
||||||
mode_colortwinkle(void),
|
|
||||||
mode_lake(void),
|
|
||||||
mode_meteor(void),
|
|
||||||
mode_meteor_smooth(void),
|
|
||||||
mode_railway(void),
|
|
||||||
mode_ripple(void),
|
|
||||||
mode_twinklefox(void),
|
|
||||||
mode_twinklecat(void),
|
|
||||||
mode_halloween_eyes(void),
|
|
||||||
mode_static_pattern(void),
|
|
||||||
mode_tri_static_pattern(void),
|
|
||||||
mode_spots(void),
|
|
||||||
mode_spots_fade(void),
|
|
||||||
mode_glitter(void),
|
|
||||||
mode_candle(void),
|
|
||||||
mode_starburst(void),
|
|
||||||
mode_exploding_fireworks(void),
|
|
||||||
mode_bouncing_balls(void),
|
|
||||||
mode_sinelon(void),
|
|
||||||
mode_sinelon_dual(void),
|
|
||||||
mode_sinelon_rainbow(void),
|
|
||||||
mode_popcorn(void),
|
|
||||||
mode_drip(void),
|
|
||||||
mode_plasma(void),
|
|
||||||
mode_percent(void),
|
|
||||||
mode_ripple_rainbow(void),
|
|
||||||
mode_heartbeat(void),
|
|
||||||
mode_pacifica(void),
|
|
||||||
mode_candle_multi(void),
|
|
||||||
mode_solid_glitter(void),
|
|
||||||
mode_sunrise(void),
|
|
||||||
mode_phased(void),
|
|
||||||
mode_twinkleup(void),
|
|
||||||
mode_noisepal(void),
|
|
||||||
mode_sinewave(void),
|
|
||||||
mode_phased_noise(void),
|
|
||||||
mode_flow(void),
|
|
||||||
mode_chunchun(void),
|
|
||||||
mode_dancing_shadows(void),
|
|
||||||
mode_washing_machine(void),
|
|
||||||
mode_candy_cane(void),
|
|
||||||
mode_blends(void),
|
|
||||||
mode_tv_simulator(void),
|
|
||||||
mode_dynamic_smooth(void),
|
|
||||||
// non-audio transfered from WLED-SR
|
|
||||||
mode_perlinmove(void),
|
|
||||||
mode_wavesins(void),
|
|
||||||
mode_FlowStripe(void);
|
|
||||||
|
|
||||||
// 2D support (panels)
|
|
||||||
bool
|
bool
|
||||||
isMatrix = false;
|
isMatrix = false;
|
||||||
|
|
||||||
@ -915,119 +653,12 @@ class WS2812FX {
|
|||||||
uint32_t
|
uint32_t
|
||||||
getPixelColorXY(uint16_t, uint16_t);
|
getPixelColorXY(uint16_t, uint16_t);
|
||||||
|
|
||||||
// end 2D support
|
// end 2D support
|
||||||
|
|
||||||
// 2D modes
|
|
||||||
uint16_t
|
|
||||||
mode_2Dspaceships(void),
|
|
||||||
mode_2Dcrazybees(void),
|
|
||||||
mode_2Dghostrider(void),
|
|
||||||
mode_2Dfloatingblobs(void),
|
|
||||||
mode_2Dscrollingtext(void),
|
|
||||||
mode_2Ddriftrose(void);
|
|
||||||
|
|
||||||
// WLED-SR modes
|
|
||||||
#ifndef USERMOD_AUDIOREACTIVE
|
|
||||||
uint16_t
|
|
||||||
mode_2Dnoise(void),
|
|
||||||
mode_2Dfirenoise(void),
|
|
||||||
mode_2Dsquaredswirl(void),
|
|
||||||
mode_2Ddna(void),
|
|
||||||
mode_2Dmatrix(void),
|
|
||||||
mode_2Dmetaballs(void),
|
|
||||||
mode_2DPulser(void),
|
|
||||||
mode_2Dgameoflife(void),
|
|
||||||
mode_2Dtartan(void),
|
|
||||||
mode_2DPolarLights(void),
|
|
||||||
mode_2DSwirl(void),
|
|
||||||
mode_2DLissajous(void),
|
|
||||||
mode_2DFrizzles(void),
|
|
||||||
mode_2DPlasmaball(void),
|
|
||||||
mode_2DHiphotic(void),
|
|
||||||
mode_2DSindots(void),
|
|
||||||
mode_2DDNASpiral(void),
|
|
||||||
mode_2DBlackHole(void),
|
|
||||||
mode_2DSunradiation(void),
|
|
||||||
mode_2DWaverly(void),
|
|
||||||
mode_2DDrift(void),
|
|
||||||
mode_2DColoredBursts(void),
|
|
||||||
mode_2DJulia(void),
|
|
||||||
mode_gravimeter(void),
|
|
||||||
mode_gravcenter(void),
|
|
||||||
mode_gravcentric(void),
|
|
||||||
mode_juggles(void),
|
|
||||||
mode_matripix(void),
|
|
||||||
mode_midnoise(void),
|
|
||||||
mode_noisemeter(void),
|
|
||||||
mode_noisefire(void),
|
|
||||||
mode_pixelwave(void),
|
|
||||||
mode_plasmoid(void),
|
|
||||||
mode_puddles(void),
|
|
||||||
mode_puddlepeak(void),
|
|
||||||
mode_ripplepeak(void),
|
|
||||||
mode_2DAkemi(void);
|
|
||||||
#else
|
|
||||||
uint16_t
|
|
||||||
mode_pixels(void),
|
|
||||||
mode_pixelwave(void),
|
|
||||||
mode_juggles(void),
|
|
||||||
mode_matripix(void),
|
|
||||||
mode_gravimeter(void),
|
|
||||||
mode_plasmoid(void),
|
|
||||||
mode_puddles(void),
|
|
||||||
mode_midnoise(void),
|
|
||||||
mode_noisemeter(void),
|
|
||||||
mode_freqwave(void),
|
|
||||||
mode_freqmatrix(void),
|
|
||||||
mode_2DGEQ(void),
|
|
||||||
mode_waterfall(void),
|
|
||||||
mode_freqpixels(void),
|
|
||||||
mode_binmap(void),
|
|
||||||
mode_noisefire(void),
|
|
||||||
mode_puddlepeak(void),
|
|
||||||
mode_noisemove(void),
|
|
||||||
mode_2Dnoise(void),
|
|
||||||
mode_ripplepeak(void),
|
|
||||||
mode_2Dfirenoise(void),
|
|
||||||
mode_2Dsquaredswirl(void),
|
|
||||||
mode_2Ddna(void),
|
|
||||||
mode_2Dmatrix(void),
|
|
||||||
mode_2Dmetaballs(void),
|
|
||||||
mode_freqmap(void),
|
|
||||||
mode_gravcenter(void),
|
|
||||||
mode_gravcentric(void),
|
|
||||||
mode_gravfreq(void),
|
|
||||||
mode_DJLight(void),
|
|
||||||
mode_2DFunkyPlank(void),
|
|
||||||
mode_2DPulser(void),
|
|
||||||
mode_blurz(void),
|
|
||||||
mode_2Dgameoflife(void),
|
|
||||||
mode_2Dtartan(void),
|
|
||||||
mode_2DPolarLights(void),
|
|
||||||
mode_2DSwirl(void),
|
|
||||||
mode_2DLissajous(void),
|
|
||||||
mode_2DFrizzles(void),
|
|
||||||
mode_2DPlasmaball(void),
|
|
||||||
mode_2DHiphotic(void),
|
|
||||||
mode_2DSindots(void),
|
|
||||||
mode_2DDNASpiral(void),
|
|
||||||
mode_2DBlackHole(void),
|
|
||||||
mode_rocktaves(void),
|
|
||||||
mode_2DAkemi(void),
|
|
||||||
mode_2DSunradiation(void),
|
|
||||||
mode_2DWaverly(void),
|
|
||||||
mode_2DDrift(void),
|
|
||||||
mode_2DColoredBursts(void),
|
|
||||||
mode_2DJulia(void),
|
|
||||||
mode_customEffect(void); //WLEDSR Custom Effects
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t crgb_to_col(CRGB fastled);
|
|
||||||
CRGB col_to_crgb(uint32_t);
|
|
||||||
CRGBPalette16 currentPalette;
|
CRGBPalette16 currentPalette;
|
||||||
CRGBPalette16 targetPalette;
|
CRGBPalette16 targetPalette;
|
||||||
|
|
||||||
|
private:
|
||||||
uint16_t _length, _virtualSegmentLength;
|
uint16_t _length, _virtualSegmentLength;
|
||||||
uint16_t _rand16seed;
|
uint16_t _rand16seed;
|
||||||
uint8_t _brightness;
|
uint8_t _brightness;
|
||||||
@ -1050,38 +681,6 @@ class WS2812FX {
|
|||||||
|
|
||||||
show_callback _callback = nullptr;
|
show_callback _callback = nullptr;
|
||||||
|
|
||||||
// mode helper functions
|
|
||||||
uint16_t
|
|
||||||
blink(uint32_t, uint32_t, bool strobe, bool),
|
|
||||||
candle(bool),
|
|
||||||
color_wipe(bool, bool),
|
|
||||||
dynamic(bool),
|
|
||||||
scan(bool),
|
|
||||||
fireworks_base(CRGB*),
|
|
||||||
running_base(bool,bool),
|
|
||||||
larson_scanner(bool),
|
|
||||||
sinelon_base(bool,bool),
|
|
||||||
dissolve(uint32_t),
|
|
||||||
chase(uint32_t, uint32_t, uint32_t, bool),
|
|
||||||
gradient_base(bool),
|
|
||||||
ripple_base(bool),
|
|
||||||
police_base(uint32_t, uint32_t),
|
|
||||||
running(uint32_t, uint32_t, bool theatre=false),
|
|
||||||
tricolor_chase(uint32_t, uint32_t),
|
|
||||||
twinklefox_base(bool),
|
|
||||||
spots_base(uint16_t),
|
|
||||||
phased_base(uint8_t);
|
|
||||||
|
|
||||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
|
|
||||||
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
|
|
||||||
|
|
||||||
void
|
|
||||||
blendPixelColor(uint16_t n, uint32_t color, uint8_t blend),
|
|
||||||
startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot),
|
|
||||||
estimateCurrentAndLimitBri(void),
|
|
||||||
load_gradient_palette(uint8_t),
|
|
||||||
handle_palette(void);
|
|
||||||
|
|
||||||
uint16_t* customMappingTable = nullptr;
|
uint16_t* customMappingTable = nullptr;
|
||||||
uint16_t customMappingSize = 0;
|
uint16_t customMappingSize = 0;
|
||||||
|
|
||||||
@ -1100,18 +699,21 @@ class WS2812FX {
|
|||||||
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[], capabilities, custom 1, custom 2, custom 3
|
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[], capabilities, custom 1, custom 2, custom 3
|
||||||
{0, 7, 0, DEFAULT_SPEED, DEFAULT_INTENSITY, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, 0, DEFAULT_C1, DEFAULT_C2, DEFAULT_C3, 0, 1}
|
{0, 7, 0, DEFAULT_SPEED, DEFAULT_INTENSITY, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, 0, DEFAULT_C1, DEFAULT_C2, DEFAULT_C3, 0, 1}
|
||||||
};
|
};
|
||||||
|
friend class Segment;
|
||||||
|
|
||||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
||||||
friend class Segment_runtime;
|
friend class Segment_runtime;
|
||||||
|
|
||||||
ColorTransition transitions[MAX_NUM_TRANSITIONS]; //12 bytes per element
|
ColorTransition transitions[MAX_NUM_TRANSITIONS]; //12 bytes per element
|
||||||
friend class ColorTransition;
|
friend class ColorTransition;
|
||||||
|
|
||||||
|
void
|
||||||
|
estimateCurrentAndLimitBri(void),
|
||||||
|
load_gradient_palette(uint8_t),
|
||||||
|
handle_palette(void);
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
transitionProgress(uint8_t tNr);
|
transitionProgress(uint8_t tNr);
|
||||||
|
|
||||||
public:
|
|
||||||
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
|
||||||
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char JSON_mode_names[];
|
extern const char JSON_mode_names[];
|
||||||
|
@ -110,15 +110,6 @@ void WS2812FX::setUpMatrix() {
|
|||||||
uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y) {
|
uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y) {
|
||||||
uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels
|
uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels
|
||||||
uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels
|
uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels
|
||||||
/*
|
|
||||||
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) {
|
|
||||||
uint16_t t;
|
|
||||||
// swap X & Y if segment transposed
|
|
||||||
t = x; x = y; y = t;
|
|
||||||
// swap width & height if segment transposed
|
|
||||||
t = width; width = height; height = t;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return (x%width) + (y%height) * width;
|
return (x%width) + (y%height) * width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,13 +285,13 @@ void WS2812FX::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) {
|
|||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t x = 0; x < cols; x++) {
|
for (uint16_t x = 0; x < cols; x++) {
|
||||||
CRGB cur = leds ? leds[XY(x,row)] : col_to_crgb(getPixelColorXY(x, row));
|
CRGB cur = leds ? leds[XY(x,row)] : CRGB(getPixelColorXY(x, row));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (x) {
|
if (x) {
|
||||||
CRGB prev = (leds ? leds[XY(x-1,row)] : col_to_crgb(getPixelColorXY(x-1, row))) + part;
|
CRGB prev = (leds ? leds[XY(x-1,row)] : CRGB(getPixelColorXY(x-1, row))) + part;
|
||||||
if (leds) leds[XY(x-1,row)] = prev;
|
if (leds) leds[XY(x-1,row)] = prev;
|
||||||
else setPixelColorXY(x-1, row, prev);
|
else setPixelColorXY(x-1, row, prev);
|
||||||
}
|
}
|
||||||
@ -321,13 +312,13 @@ void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
|||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t i = 0; i < rows; i++) {
|
for (uint16_t i = 0; i < rows; i++) {
|
||||||
CRGB cur = leds ? leds[XY(col,i)] : col_to_crgb(getPixelColorXY(col, i));
|
CRGB cur = leds ? leds[XY(col,i)] : CRGB(getPixelColorXY(col, i));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (i) {
|
if (i) {
|
||||||
CRGB prev = (leds ? leds[XY(col,i-1)] : col_to_crgb(getPixelColorXY(col, i-1))) + part;
|
CRGB prev = (leds ? leds[XY(col,i-1)] : CRGB(getPixelColorXY(col, i-1))) + part;
|
||||||
if (leds) leds[XY(col,i-1)] = prev;
|
if (leds) leds[XY(col,i-1)] = prev;
|
||||||
else setPixelColorXY(col, i-1, prev);
|
else setPixelColorXY(col, i-1, prev);
|
||||||
}
|
}
|
||||||
@ -374,9 +365,9 @@ void WS2812FX::blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds)
|
|||||||
uint16_t yp = vertical ? y-1 : y;
|
uint16_t yp = vertical ? y-1 : y;
|
||||||
uint16_t xn = vertical ? x : x+1;
|
uint16_t xn = vertical ? x : x+1;
|
||||||
uint16_t yn = vertical ? y+1 : y;
|
uint16_t yn = vertical ? y+1 : y;
|
||||||
CRGB curr = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y));
|
CRGB curr = leds ? leds[XY(x,y)] : CRGB(getPixelColorXY(x,y));
|
||||||
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : (leds ? leds[XY(xp,yp)] : col_to_crgb(getPixelColorXY(xp,yp)));
|
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : (leds ? leds[XY(xp,yp)] : CRGB(getPixelColorXY(xp,yp)));
|
||||||
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : (leds ? leds[XY(xn,yn)] : col_to_crgb(getPixelColorXY(xn,yn)));
|
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : (leds ? leds[XY(xn,yn)] : CRGB(getPixelColorXY(xn,yn)));
|
||||||
uint16_t r, g, b;
|
uint16_t r, g, b;
|
||||||
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
||||||
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
||||||
@ -491,7 +482,7 @@ void WS2812FX::nscale8(CRGB* leds, uint8_t scale) {
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = SEGMENT.virtualHeight();
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
if (leds) leds[XY(x,y)].nscale8(scale);
|
if (leds) leds[XY(x,y)].nscale8(scale);
|
||||||
else setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x, y)).nscale8(scale));
|
else setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,253 @@
|
|||||||
#error "Max segments must be at least max number of busses!"
|
#error "Max segments must be at least max number of busses!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bool Segment::setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
|
||||||
|
if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;
|
||||||
|
if (c == colors[slot]) return false;
|
||||||
|
uint8_t b = (slot == 1) ? cct : opacity;
|
||||||
|
ColorTransition::startTransition(b, colors[slot], segn, slot);
|
||||||
|
colors[slot] = c; return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Segment::setCCT(uint16_t k, uint8_t segn) {
|
||||||
|
if (segn >= MAX_NUM_SEGMENTS) return;
|
||||||
|
if (k > 255) { //kelvin value, convert to 0-255
|
||||||
|
if (k < 1900) k = 1900;
|
||||||
|
if (k > 10091) k = 10091;
|
||||||
|
k = (k - 1900) >> 5;
|
||||||
|
}
|
||||||
|
if (cct == k) return;
|
||||||
|
ColorTransition::startTransition(cct, colors[1], segn, 1);
|
||||||
|
cct = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Segment::setOpacity(uint8_t o, uint8_t segn) {
|
||||||
|
if (segn >= MAX_NUM_SEGMENTS) return;
|
||||||
|
if (opacity == o) return;
|
||||||
|
ColorTransition::startTransition(opacity, colors[0], segn, 0);
|
||||||
|
opacity = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Segment::setOption(uint8_t n, bool val, uint8_t segn) {
|
||||||
|
bool prevOn = false;
|
||||||
|
if (n == SEG_OPTION_ON) {
|
||||||
|
prevOn = getOption(SEG_OPTION_ON);
|
||||||
|
if (!val && prevOn) { //fade off
|
||||||
|
ColorTransition::startTransition(opacity, colors[0], segn, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (val) options |= 0x01 << n;
|
||||||
|
else options &= ~(0x01 << n);
|
||||||
|
if (n == SEG_OPTION_ON && val && !prevOn) { //fade on
|
||||||
|
ColorTransition::startTransition(0, colors[0], segn, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2D matrix
|
||||||
|
uint16_t Segment::virtualWidth() {
|
||||||
|
uint16_t groupLen = groupLength();
|
||||||
|
uint16_t vWidth = ((getOption(SEG_OPTION_TRANSPOSED) ? height() : width()) + groupLen - 1) / groupLen;
|
||||||
|
if (getOption(SEG_OPTION_MIRROR)) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
|
return vWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Segment::virtualHeight() {
|
||||||
|
uint16_t groupLen = groupLength();
|
||||||
|
uint16_t vHeight = ((getOption(SEG_OPTION_TRANSPOSED) ? width() : height()) + groupLen - 1) / groupLen;
|
||||||
|
if (getOption(SEG_OPTION_MIRROR_Y)) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
|
return vHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1D strip
|
||||||
|
uint16_t Segment::virtualLength() {
|
||||||
|
uint16_t groupLen = groupLength();
|
||||||
|
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
||||||
|
if (getOption(SEG_OPTION_MIRROR)) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
|
return vLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Segment::differs(Segment& b) {
|
||||||
|
uint8_t d = 0;
|
||||||
|
if (start != b.start) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
if (stop != b.stop) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
if (offset != b.offset) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (grouping != b.grouping) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (spacing != b.spacing) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (opacity != b.opacity) d |= SEG_DIFFERS_BRI;
|
||||||
|
if (mode != b.mode) d |= SEG_DIFFERS_FX;
|
||||||
|
if (speed != b.speed) d |= SEG_DIFFERS_FX;
|
||||||
|
if (intensity != b.intensity) d |= SEG_DIFFERS_FX;
|
||||||
|
if (palette != b.palette) d |= SEG_DIFFERS_FX;
|
||||||
|
if (custom1 != b.custom1) d |= SEG_DIFFERS_FX;
|
||||||
|
if (custom2 != b.custom2) d |= SEG_DIFFERS_FX;
|
||||||
|
if (custom3 != b.custom3) d |= SEG_DIFFERS_FX;
|
||||||
|
if (startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
if (stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
|
||||||
|
//bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
|
||||||
|
if ((options & 0b11100101110) != (b.options & 0b11100101110)) d |= SEG_DIFFERS_OPT;
|
||||||
|
if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < NUM_COLORS; i++) if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Segment::refreshLightCapabilities() {
|
||||||
|
if (!isActive()) {
|
||||||
|
_capabilities = 0; return;
|
||||||
|
}
|
||||||
|
uint8_t capabilities = 0;
|
||||||
|
|
||||||
|
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
||||||
|
Bus *bus = busses.getBus(b);
|
||||||
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
|
if (!bus->isOk()) continue;
|
||||||
|
if (bus->getStart() >= stop) continue;
|
||||||
|
if (bus->getStart() + bus->getLength() <= start) continue;
|
||||||
|
|
||||||
|
uint8_t type = bus->getType();
|
||||||
|
if (type != TYPE_ANALOG_1CH && (cctFromRgb || type != TYPE_ANALOG_2CH)) capabilities |= 0x01; // segment supports RGB (full color)
|
||||||
|
if (bus->isRgbw()) capabilities |= 0x02; // segment supports white channel
|
||||||
|
if (!cctFromRgb) {
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_ANALOG_5CH:
|
||||||
|
case TYPE_ANALOG_2CH:
|
||||||
|
capabilities |= 0x04; //segment supports white CCT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (correctWB && type != TYPE_ANALOG_1CH) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
||||||
|
uint8_t aWM = Bus::getAutoWhiteMode()<255 ? Bus::getAutoWhiteMode() : bus->getAWMode();
|
||||||
|
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
||||||
|
if (bus->isRgbw() && (whiteSlider || !(capabilities & 0x01))) capabilities |= 0x08; // allow white channel adjustments (AWM allows or is not RGB)
|
||||||
|
}
|
||||||
|
_capabilities = capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Segment_runtime::allocateData(uint16_t len){
|
||||||
|
if (data && _dataLen == len) return true; //already allocated
|
||||||
|
WS2812FX *instance = WS2812FX::getInstance();
|
||||||
|
deallocateData();
|
||||||
|
if (instance->_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||||
|
// if possible use SPI RAM on ESP32
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||||
|
if (psramFound())
|
||||||
|
data = (byte*) ps_malloc(len);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
data = (byte*) malloc(len);
|
||||||
|
if (!data) return false; //allocation failed
|
||||||
|
instance->_usedSegmentData += len;
|
||||||
|
_dataLen = len;
|
||||||
|
memset(data, 0, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Segment_runtime::deallocateData(){
|
||||||
|
free(data);
|
||||||
|
data = nullptr;
|
||||||
|
WS2812FX::getInstance()->_usedSegmentData -= _dataLen;
|
||||||
|
_dataLen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If reset of this segment was request, clears runtime
|
||||||
|
* settings of this segment.
|
||||||
|
* Must not be called while an effect mode function is running
|
||||||
|
* because it could access the data buffer and this method
|
||||||
|
* may free that data buffer.
|
||||||
|
*/
|
||||||
|
void Segment_runtime::resetIfRequired() {
|
||||||
|
if (_requiresReset) {
|
||||||
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
|
deallocateData();
|
||||||
|
_requiresReset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorTransition::startTransition(uint8_t oldBri, uint32_t oldCol, uint8_t segn, uint8_t slot) {
|
||||||
|
WS2812FX *instance = WS2812FX::getInstance();
|
||||||
|
if (segn >= MAX_NUM_SEGMENTS || slot >= NUM_COLORS || instance->_transitionDur == 0) return;
|
||||||
|
if (instance->_brightness == 0) return; //do not need transitions if master bri is off
|
||||||
|
if (!instance->_segments[segn].getOption(SEG_OPTION_ON)) return; //not if segment is off either
|
||||||
|
uint8_t tIndex = 0xFF; //none found
|
||||||
|
uint16_t tProgression = 0;
|
||||||
|
uint8_t s = segn + (slot << 6); //merge slot and segment into one byte
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) {
|
||||||
|
uint8_t tSeg = instance->transitions[i].segment;
|
||||||
|
//see if this segment + color already has a running transition
|
||||||
|
if (tSeg == s) {
|
||||||
|
tIndex = i; break;
|
||||||
|
}
|
||||||
|
if (tSeg == 0xFF) { //free transition
|
||||||
|
tIndex = i; tProgression = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tIndex == 0xFF) { //no slot found yet
|
||||||
|
for (uint8_t i = 0; i < MAX_NUM_TRANSITIONS; i++) {
|
||||||
|
//find most progressed transition to overwrite
|
||||||
|
uint16_t prog = instance->transitions[i].progress();
|
||||||
|
if (prog > tProgression) {
|
||||||
|
tIndex = i; tProgression = prog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorTransition& t = instance->transitions[tIndex];
|
||||||
|
if (t.segment == s) //this is an active transition on the same segment+color
|
||||||
|
{
|
||||||
|
bool wasTurningOff = (oldBri == 0);
|
||||||
|
t.briOld = t.currentBri(wasTurningOff, slot);
|
||||||
|
t.colorOld = t.currentColor(oldCol);
|
||||||
|
} else {
|
||||||
|
t.briOld = oldBri;
|
||||||
|
t.colorOld = oldCol;
|
||||||
|
uint8_t prevSeg = t.segment & 0x3F;
|
||||||
|
if (prevSeg < MAX_NUM_SEGMENTS) instance->_segments[prevSeg].setOption(SEG_OPTION_TRANSITIONAL, false);
|
||||||
|
}
|
||||||
|
t.transitionDur = instance->_transitionDur;
|
||||||
|
t.transitionStart = millis();
|
||||||
|
t.segment = s;
|
||||||
|
instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, true);
|
||||||
|
//refresh immediately, required for Solid mode
|
||||||
|
if (instance->_segment_runtimes[segn].next_time > t.transitionStart + 22) instance->_segment_runtimes[segn].next_time = t.transitionStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ColorTransition::progress(bool allowEnd) { //transition progression between 0-65535
|
||||||
|
WS2812FX *instance = WS2812FX::getInstance();
|
||||||
|
uint32_t timeNow = millis();
|
||||||
|
if (timeNow - transitionStart > transitionDur) {
|
||||||
|
if (allowEnd) {
|
||||||
|
uint8_t segn = segment & 0x3F;
|
||||||
|
if (segn < MAX_NUM_SEGMENTS) instance->_segments[segn].setOption(SEG_OPTION_TRANSITIONAL, false);
|
||||||
|
segment = 0xFF;
|
||||||
|
}
|
||||||
|
return 0xFFFF;
|
||||||
|
}
|
||||||
|
uint32_t elapsed = timeNow - transitionStart;
|
||||||
|
uint32_t prog = elapsed * 0xFFFF / transitionDur;
|
||||||
|
return (prog > 0xFFFF) ? 0xFFFF : prog;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ColorTransition::currentBri(bool turningOff, uint8_t slot) {
|
||||||
|
WS2812FX *instance = WS2812FX::getInstance();
|
||||||
|
uint8_t segn = segment & 0x3F;
|
||||||
|
if (segn >= MAX_NUM_SEGMENTS) return 0;
|
||||||
|
uint8_t briNew = instance->_segments[segn].opacity;
|
||||||
|
if (slot == 0) {
|
||||||
|
if (!instance->_segments[segn].getOption(SEG_OPTION_ON) || turningOff) briNew = 0;
|
||||||
|
} else { //transition slot 1 brightness for CCT transition
|
||||||
|
briNew = instance->_segments[segn].cct;
|
||||||
|
}
|
||||||
|
uint32_t prog = progress() + 1;
|
||||||
|
return ((briNew * prog) + (briOld * (0x10000 - prog))) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//do not call this method from system context (network callback)
|
//do not call this method from system context (network callback)
|
||||||
void WS2812FX::finalizeInit(void)
|
void WS2812FX::finalizeInit(void)
|
||||||
{
|
{
|
||||||
@ -149,8 +396,11 @@ void WS2812FX::service() {
|
|||||||
uint16_t delay = FRAMETIME;
|
uint16_t delay = FRAMETIME;
|
||||||
|
|
||||||
if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
|
if (!SEGMENT.getOption(SEG_OPTION_FREEZE)) { //only run effect function if not frozen
|
||||||
SEGLEN = SEGMENT.virtualLength();
|
_virtualSegmentLength = SEGMENT.virtualLength();
|
||||||
_bri_t = SEGMENT.opacity; _colors_t[0] = SEGMENT.colors[0]; _colors_t[1] = SEGMENT.colors[1]; _colors_t[2] = SEGMENT.colors[2];
|
_bri_t = SEGMENT.opacity;
|
||||||
|
_colors_t[0] = SEGMENT.colors[0];
|
||||||
|
_colors_t[1] = SEGMENT.colors[1];
|
||||||
|
_colors_t[2] = SEGMENT.colors[2];
|
||||||
uint8_t _cct_t = SEGMENT.cct;
|
uint8_t _cct_t = SEGMENT.cct;
|
||||||
if (!SEGMENT.getOption(SEG_OPTION_ON)) _bri_t = 0;
|
if (!SEGMENT.getOption(SEG_OPTION_ON)) _bri_t = 0;
|
||||||
for (uint8_t t = 0; t < MAX_NUM_TRANSITIONS; t++) {
|
for (uint8_t t = 0; t < MAX_NUM_TRANSITIONS; t++) {
|
||||||
@ -166,14 +416,14 @@ void WS2812FX::service() {
|
|||||||
}
|
}
|
||||||
handle_palette();
|
handle_palette();
|
||||||
|
|
||||||
delay = (this->*_mode[SEGMENT.mode])(); // effect function (NOTE: may add SEGMENT and SEGENV to parameters)
|
delay = (*_mode[SEGMENT.mode])();
|
||||||
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SEGENV.next_time = nowUp + delay;
|
SEGENV.next_time = nowUp + delay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SEGLEN = 0;
|
_virtualSegmentLength = 0;
|
||||||
busses.setSegmentCCT(-1);
|
busses.setSegmentCCT(-1);
|
||||||
if(doShow) {
|
if(doShow) {
|
||||||
yield();
|
yield();
|
||||||
@ -187,7 +437,7 @@ void /*IRAM_ATTR*/ WS2812FX::setPixelColor(float i, byte r, byte g, byte b, byte
|
|||||||
{
|
{
|
||||||
if (i<0.0f || i>1.0f) return; // not normalized
|
if (i<0.0f || i>1.0f) return; // not normalized
|
||||||
|
|
||||||
float fC = i * (SEGLEN-1);
|
float fC = i * (_virtualSegmentLength-1);
|
||||||
if (aa) {
|
if (aa) {
|
||||||
uint16_t iL = roundf(fC-0.49f);
|
uint16_t iL = roundf(fC-0.49f);
|
||||||
uint16_t iR = roundf(fC+0.49f);
|
uint16_t iR = roundf(fC+0.49f);
|
||||||
@ -213,8 +463,8 @@ void /*IRAM_ATTR*/ WS2812FX::setPixelColor(float i, byte r, byte g, byte b, byte
|
|||||||
|
|
||||||
void IRAM_ATTR WS2812FX::setPixelColor(int i, byte r, byte g, byte b, byte w)
|
void IRAM_ATTR WS2812FX::setPixelColor(int i, byte r, byte g, byte b, byte w)
|
||||||
{
|
{
|
||||||
uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment;
|
uint8_t segIdx = _virtualSegmentLength ? _segment_index : _mainSegment;
|
||||||
if (isMatrix && SEGLEN) {
|
if (isMatrix && _virtualSegmentLength) {
|
||||||
// map linear pixel into 2D segment area (even for 1D segments, expanding vertically)
|
// map linear pixel into 2D segment area (even for 1D segments, expanding vertically)
|
||||||
uint16_t h = _segments[segIdx].virtualHeight(); // segment height in logical pixels
|
uint16_t h = _segments[segIdx].virtualHeight(); // segment height in logical pixels
|
||||||
for (uint16_t y = 0; y < h; y++) { // expand 1D effect vertically
|
for (uint16_t y = 0; y < h; y++) { // expand 1D effect vertically
|
||||||
@ -223,9 +473,9 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, byte r, byte g, byte b, byte w)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SEGLEN || (realtimeMode && useMainSegmentOnly)) {
|
if (_virtualSegmentLength || (realtimeMode && useMainSegmentOnly)) {
|
||||||
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
|
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
|
||||||
if (SEGLEN && _bri_t < 255) { // SEGLEN!=0 -> from segment/FX
|
if (_virtualSegmentLength && _bri_t < 255) { // _virtualSegmentLength!=0 -> from segment/FX
|
||||||
r = scale8(r, _bri_t);
|
r = scale8(r, _bri_t);
|
||||||
g = scale8(g, _bri_t);
|
g = scale8(g, _bri_t);
|
||||||
b = scale8(b, _bri_t);
|
b = scale8(b, _bri_t);
|
||||||
@ -392,22 +642,11 @@ uint16_t WS2812FX::getFps() {
|
|||||||
return _cumulativeFps +1;
|
return _cumulativeFps +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getTargetFps() {
|
|
||||||
return _targetFps;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812FX::setTargetFps(uint8_t fps) {
|
void WS2812FX::setTargetFps(uint8_t fps) {
|
||||||
if (fps > 0 && fps <= 120) _targetFps = fps;
|
if (fps > 0 && fps <= 120) _targetFps = fps;
|
||||||
_frametime = 1000 / _targetFps;
|
_frametime = 1000 / _targetFps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Forces the next frame to be computed on all active segments.
|
|
||||||
*/
|
|
||||||
void WS2812FX::trigger() {
|
|
||||||
_triggered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||||
if (segid >= MAX_NUM_SEGMENTS) return;
|
if (segid >= MAX_NUM_SEGMENTS) return;
|
||||||
|
|
||||||
@ -420,11 +659,6 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getPaletteCount()
|
|
||||||
{
|
|
||||||
return 13 + GRADIENT_PALETTE_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//applies to all active and selected segments
|
//applies to all active and selected segments
|
||||||
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
|
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
|
||||||
if (slot >= NUM_COLORS) return;
|
if (slot >= NUM_COLORS) return;
|
||||||
@ -465,14 +699,6 @@ void WS2812FX::setBrightness(uint8_t b, bool direct) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getBrightness(void) {
|
|
||||||
return _brightness;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t WS2812FX::getMaxSegments(void) {
|
|
||||||
return MAX_NUM_SEGMENTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t WS2812FX::getFirstSelectedSegId(void)
|
uint8_t WS2812FX::getFirstSelectedSegId(void)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||||
@ -499,10 +725,6 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getMainSegmentId(void) {
|
|
||||||
return _mainSegment;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t WS2812FX::getLastActiveSegmentId(void) {
|
uint8_t WS2812FX::getLastActiveSegmentId(void) {
|
||||||
for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) {
|
for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) {
|
||||||
if (_segments[i].isActive()) return i;
|
if (_segments[i].isActive()) return i;
|
||||||
@ -532,7 +754,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
|
|||||||
//}
|
//}
|
||||||
i += SEGMENT.start;
|
i += SEGMENT.start;
|
||||||
|
|
||||||
if (SEGLEN) {
|
if (_virtualSegmentLength) {
|
||||||
/* offset/phase */
|
/* offset/phase */
|
||||||
i += SEGMENT.offset;
|
i += SEGMENT.offset;
|
||||||
if (i >= SEGMENT.stop) i -= SEGMENT.length();
|
if (i >= SEGMENT.stop) i -= SEGMENT.length();
|
||||||
@ -544,31 +766,6 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
|
|||||||
return busses.getPixelColor(i);
|
return busses.getPixelColor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
|
||||||
if (id >= MAX_NUM_SEGMENTS) return _segments[getMainSegmentId()];
|
|
||||||
return _segments[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
WS2812FX::Segment& WS2812FX::getFirstSelectedSeg(void) {
|
|
||||||
return _segments[getFirstSelectedSegId()];
|
|
||||||
}
|
|
||||||
|
|
||||||
WS2812FX::Segment& WS2812FX::getMainSegment(void) {
|
|
||||||
return _segments[getMainSegmentId()];
|
|
||||||
}
|
|
||||||
|
|
||||||
WS2812FX::Segment* WS2812FX::getSegments(void) {
|
|
||||||
return _segments;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t WS2812FX::getLastShow(void) {
|
|
||||||
return _lastShow;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthTotal(void) {
|
|
||||||
return _length;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthPhysical(void) {
|
uint16_t WS2812FX::getLengthPhysical(void) {
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
||||||
@ -579,64 +776,6 @@ uint16_t WS2812FX::getLengthPhysical(void) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::Segment::differs(Segment& b) {
|
|
||||||
uint8_t d = 0;
|
|
||||||
if (start != b.start) d |= SEG_DIFFERS_BOUNDS;
|
|
||||||
if (stop != b.stop) d |= SEG_DIFFERS_BOUNDS;
|
|
||||||
if (offset != b.offset) d |= SEG_DIFFERS_GSO;
|
|
||||||
if (grouping != b.grouping) d |= SEG_DIFFERS_GSO;
|
|
||||||
if (spacing != b.spacing) d |= SEG_DIFFERS_GSO;
|
|
||||||
if (opacity != b.opacity) d |= SEG_DIFFERS_BRI;
|
|
||||||
if (mode != b.mode) d |= SEG_DIFFERS_FX;
|
|
||||||
if (speed != b.speed) d |= SEG_DIFFERS_FX;
|
|
||||||
if (intensity != b.intensity) d |= SEG_DIFFERS_FX;
|
|
||||||
if (palette != b.palette) d |= SEG_DIFFERS_FX;
|
|
||||||
if (custom1 != b.custom1) d |= SEG_DIFFERS_FX;
|
|
||||||
if (custom2 != b.custom2) d |= SEG_DIFFERS_FX;
|
|
||||||
if (custom3 != b.custom3) d |= SEG_DIFFERS_FX;
|
|
||||||
if (startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
|
|
||||||
if (stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
|
|
||||||
|
|
||||||
//bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
|
|
||||||
if ((options & 0b11100101110) != (b.options & 0b11100101110)) d |= SEG_DIFFERS_OPT;
|
|
||||||
if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < NUM_COLORS; i++) if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
|
||||||
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812FX::Segment::refreshLightCapabilities() {
|
|
||||||
if (!isActive()) {
|
|
||||||
_capabilities = 0; return;
|
|
||||||
}
|
|
||||||
uint8_t capabilities = 0;
|
|
||||||
|
|
||||||
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
|
||||||
Bus *bus = busses.getBus(b);
|
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
|
||||||
if (!bus->isOk()) continue;
|
|
||||||
if (bus->getStart() >= stop) continue;
|
|
||||||
if (bus->getStart() + bus->getLength() <= start) continue;
|
|
||||||
|
|
||||||
uint8_t type = bus->getType();
|
|
||||||
if (type != TYPE_ANALOG_1CH && (cctFromRgb || type != TYPE_ANALOG_2CH)) capabilities |= 0x01; // segment supports RGB (full color)
|
|
||||||
if (bus->isRgbw()) capabilities |= 0x02; // segment supports white channel
|
|
||||||
if (!cctFromRgb) {
|
|
||||||
switch (type) {
|
|
||||||
case TYPE_ANALOG_5CH:
|
|
||||||
case TYPE_ANALOG_2CH:
|
|
||||||
capabilities |= 0x04; //segment supports white CCT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (correctWB && type != TYPE_ANALOG_1CH) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
|
||||||
uint8_t aWM = Bus::getAutoWhiteMode()<255 ? Bus::getAutoWhiteMode() : bus->getAWMode();
|
|
||||||
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
|
||||||
if (bus->isRgbw() && (whiteSlider || !(capabilities & 0x01))) capabilities |= 0x08; // allow white channel adjustments (AWM allows or is not RGB)
|
|
||||||
}
|
|
||||||
_capabilities = capabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
|
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
|
||||||
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
||||||
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
||||||
@ -847,7 +986,7 @@ uint8_t WS2812FX::setPixelSegment(uint8_t n)
|
|||||||
uint8_t prevSegId = _segment_index;
|
uint8_t prevSegId = _segment_index;
|
||||||
if (n < MAX_NUM_SEGMENTS) {
|
if (n < MAX_NUM_SEGMENTS) {
|
||||||
_segment_index = n;
|
_segment_index = n;
|
||||||
SEGLEN = SEGMENT.virtualLength();
|
_virtualSegmentLength = SEGMENT.virtualLength();
|
||||||
}
|
}
|
||||||
return prevSegId;
|
return prevSegId;
|
||||||
}
|
}
|
||||||
@ -863,16 +1002,6 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::setShowCallback(show_callback cb)
|
|
||||||
{
|
|
||||||
_callback = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812FX::setTransition(uint16_t t)
|
|
||||||
{
|
|
||||||
_transitionDur = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WS2812FX::setTransitionMode(bool t)
|
void WS2812FX::setTransitionMode(bool t)
|
||||||
{
|
{
|
||||||
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
|
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
|
||||||
@ -885,51 +1014,6 @@ void WS2812FX::setTransitionMode(bool t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* color blend function
|
|
||||||
*/
|
|
||||||
uint32_t IRAM_ATTR WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) {
|
|
||||||
if(blend == 0) return color1;
|
|
||||||
uint16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
|
||||||
if(blend == blendmax) return color2;
|
|
||||||
uint8_t shift = b16 ? 16 : 8;
|
|
||||||
|
|
||||||
uint32_t w1 = W(color1);
|
|
||||||
uint32_t r1 = R(color1);
|
|
||||||
uint32_t g1 = G(color1);
|
|
||||||
uint32_t b1 = B(color1);
|
|
||||||
|
|
||||||
uint32_t w2 = W(color2);
|
|
||||||
uint32_t r2 = R(color2);
|
|
||||||
uint32_t g2 = G(color2);
|
|
||||||
uint32_t b2 = B(color2);
|
|
||||||
|
|
||||||
uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift;
|
|
||||||
uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift;
|
|
||||||
uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift;
|
|
||||||
uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift;
|
|
||||||
|
|
||||||
return RGBW32(r3, g3, b3, w3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* color add function that preserves ratio
|
|
||||||
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
|
|
||||||
*/
|
|
||||||
uint32_t WS2812FX::color_add(uint32_t c1, uint32_t c2)
|
|
||||||
{
|
|
||||||
uint32_t r = R(c1) + R(c2);
|
|
||||||
uint32_t g = G(c1) + G(c2);
|
|
||||||
uint32_t b = B(c1) + B(c2);
|
|
||||||
uint32_t w = W(c1) + W(c2);
|
|
||||||
uint16_t max = r;
|
|
||||||
if (g > max) max = g;
|
|
||||||
if (b > max) max = b;
|
|
||||||
if (w > max) max = 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fills segment with color
|
* Fills segment with color
|
||||||
*/
|
*/
|
||||||
@ -998,8 +1082,8 @@ void WS2812FX::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
const uint16_t rows = SEGMENT.virtualHeight(); // will be 1 for 1D
|
const uint16_t rows = SEGMENT.virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
if (isMatrix) setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x,y)).nscale8(255-fadeBy));
|
if (isMatrix) setPixelColorXY(x, y, CRGB(getPixelColorXY(x,y)).nscale8(255-fadeBy));
|
||||||
else setPixelColor(x, col_to_crgb(getPixelColor(x)).nscale8(255-fadeBy));
|
else setPixelColor(x, CRGB(getPixelColor(x)).nscale8(255-fadeBy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,9 +1103,9 @@ void WS2812FX::blur(uint8_t 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(uint16_t i = 0; i < SEGLEN; i++)
|
for(uint16_t i = 0; i < _virtualSegmentLength; i++)
|
||||||
{
|
{
|
||||||
CRGB cur = col_to_crgb(getPixelColor(i));
|
CRGB cur = CRGB(getPixelColor(i));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
@ -1038,7 +1122,7 @@ void WS2812FX::blur(uint8_t blur_amount)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t IRAM_ATTR WS2812FX::triwave16(uint16_t in)
|
uint16_t WS2812FX::triwave16(uint16_t in)
|
||||||
{
|
{
|
||||||
if (in < 0x8000) return in *2;
|
if (in < 0x8000) return in *2;
|
||||||
return 0xFFFF - (in - 0x8000)*2;
|
return 0xFFFF - (in - 0x8000)*2;
|
||||||
@ -1105,22 +1189,6 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t IRAM_ATTR WS2812FX::crgb_to_col(CRGB fastled)
|
|
||||||
{
|
|
||||||
return RGBW32(fastled.red, fastled.green, fastled.blue, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CRGB IRAM_ATTR WS2812FX::col_to_crgb(uint32_t color)
|
|
||||||
{
|
|
||||||
CRGB fastled_col;
|
|
||||||
fastled_col.red = R(color);
|
|
||||||
fastled_col.green = G(color);
|
|
||||||
fastled_col.blue = B(color);
|
|
||||||
return fastled_col;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void WS2812FX::load_gradient_palette(uint8_t index)
|
void WS2812FX::load_gradient_palette(uint8_t index)
|
||||||
{
|
{
|
||||||
byte i = constrain(index, 0, GRADIENT_PALETTE_COUNT -1);
|
byte i = constrain(index, 0, GRADIENT_PALETTE_COUNT -1);
|
||||||
@ -1176,22 +1244,22 @@ void WS2812FX::handle_palette(void)
|
|||||||
_lastPaletteChange = millis();
|
_lastPaletteChange = millis();
|
||||||
} break;}
|
} break;}
|
||||||
case 2: {//primary color only
|
case 2: {//primary color only
|
||||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
CRGB prim = CRGB(SEGCOLOR(0));
|
||||||
targetPalette = CRGBPalette16(prim); break;}
|
targetPalette = CRGBPalette16(prim); break;}
|
||||||
case 3: {//primary + secondary
|
case 3: {//primary + secondary
|
||||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
CRGB prim = CRGB(SEGCOLOR(0));
|
||||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
CRGB sec = CRGB(SEGCOLOR(1));
|
||||||
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
|
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
|
||||||
case 4: {//primary + secondary + tertiary
|
case 4: {//primary + secondary + tertiary
|
||||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
CRGB prim = CRGB(SEGCOLOR(0));
|
||||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
CRGB sec = CRGB(SEGCOLOR(1));
|
||||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
CRGB ter = CRGB(SEGCOLOR(2));
|
||||||
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
||||||
case 5: {//primary + secondary (+tert if not off), more distinct
|
case 5: {//primary + secondary (+tert if not off), more distinct
|
||||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
CRGB prim = CRGB(SEGCOLOR(0));
|
||||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
CRGB sec = CRGB(SEGCOLOR(1));
|
||||||
if (SEGCOLOR(2)) {
|
if (SEGCOLOR(2)) {
|
||||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
CRGB ter = CRGB(SEGCOLOR(2));
|
||||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
|
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
|
||||||
} else {
|
} else {
|
||||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
|
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
|
||||||
@ -1227,7 +1295,7 @@ void WS2812FX::handle_palette(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 SEGLEN 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.
|
||||||
* @param mapping if true, LED position in segment is considered for color
|
* @param mapping if true, LED position in segment is considered for color
|
||||||
* @param wrap FastLED palettes will usally wrap back to the start smoothly. Set false to get a hard edge
|
* @param wrap FastLED palettes will usally wrap back to the start smoothly. Set false to get a hard edge
|
||||||
* @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead
|
* @param mcol If the default palette 0 is selected, return the standard color 0, 1 or 2 instead. If >2, Party palette is used instead
|
||||||
@ -1243,12 +1311,12 @@ uint32_t IRAM_ATTR WS2812FX::color_from_palette(uint16_t i, bool mapping, bool w
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t paletteIndex = i;
|
uint8_t paletteIndex = i;
|
||||||
if (mapping && SEGLEN > 1) paletteIndex = (i*255)/(SEGLEN -1);
|
if (mapping && _virtualSegmentLength > 1) paletteIndex = (i*255)/(_virtualSegmentLength -1);
|
||||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col = ColorFromPalette(currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
fastled_col = ColorFromPalette(currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||||
|
|
||||||
return crgb_to_col(fastled_col);
|
return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1302,7 +1370,7 @@ void WS2812FX::deserializeMap(uint8_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//gamma 2.8 lookup table used for color correction
|
//gamma 2.8 lookup table used for color correction
|
||||||
byte gammaT[] = {
|
static byte gammaT[] = {
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||||
@ -1321,7 +1389,7 @@ byte gammaT[] = {
|
|||||||
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
|
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
|
||||||
|
|
||||||
uint8_t WS2812FX::gamma8_cal(uint8_t b, float gamma) {
|
uint8_t WS2812FX::gamma8_cal(uint8_t b, float gamma) {
|
||||||
return (int)(pow((float)b / 255.0, gamma) * 255 + 0.5);
|
return (int)(powf((float)b / 255.0f, gamma) * 255.0f + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::calcGammaTable(float gamma)
|
void WS2812FX::calcGammaTable(float gamma)
|
||||||
|
@ -195,7 +195,7 @@ void handleAnalog(uint8_t b)
|
|||||||
colorHStoRGB(aRead*256,255,col);
|
colorHStoRGB(aRead*256,255,col);
|
||||||
} else {
|
} else {
|
||||||
// otherwise use "double press" for segment selection
|
// otherwise use "double press" for segment selection
|
||||||
WS2812FX::Segment& seg = strip.getSegment(macroDoublePress[b]);
|
Segment& seg = strip.getSegment(macroDoublePress[b]);
|
||||||
if (aRead == 0) {
|
if (aRead == 0) {
|
||||||
seg.setOption(SEG_OPTION_ON, 0); // off
|
seg.setOption(SEG_OPTION_ON, 0); // off
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,54 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color conversion methods
|
* Color conversion & utility methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color blend function
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) {
|
||||||
|
if(blend == 0) return color1;
|
||||||
|
uint16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
||||||
|
if(blend == blendmax) return color2;
|
||||||
|
uint8_t shift = b16 ? 16 : 8;
|
||||||
|
|
||||||
|
uint32_t w1 = W(color1);
|
||||||
|
uint32_t r1 = R(color1);
|
||||||
|
uint32_t g1 = G(color1);
|
||||||
|
uint32_t b1 = B(color1);
|
||||||
|
|
||||||
|
uint32_t w2 = W(color2);
|
||||||
|
uint32_t r2 = R(color2);
|
||||||
|
uint32_t g2 = G(color2);
|
||||||
|
uint32_t b2 = B(color2);
|
||||||
|
|
||||||
|
uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift;
|
||||||
|
|
||||||
|
return RGBW32(r3, g3, b3, w3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color add function that preserves ratio
|
||||||
|
* 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 r = R(c1) + R(c2);
|
||||||
|
uint32_t g = G(c1) + G(c2);
|
||||||
|
uint32_t b = B(c1) + B(c2);
|
||||||
|
uint32_t w = W(c1) + W(c2);
|
||||||
|
uint16_t max = r;
|
||||||
|
if (g > max) max = g;
|
||||||
|
if (b > max) max = b;
|
||||||
|
if (w > max) max = 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);
|
||||||
|
}
|
||||||
|
|
||||||
void setRandomColor(byte* rgb)
|
void setRandomColor(byte* rgb)
|
||||||
{
|
{
|
||||||
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* Readability defines and their associated numerical values + compile-time constants
|
* Readability defines and their associated numerical values + compile-time constants
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GRADIENT_PALETTE_COUNT 58
|
||||||
|
|
||||||
//Defaults
|
//Defaults
|
||||||
#define DEFAULT_CLIENT_SSID "Your_Network"
|
#define DEFAULT_CLIENT_SSID "Your_Network"
|
||||||
#define DEFAULT_AP_PASS "wled1234"
|
#define DEFAULT_AP_PASS "wled1234"
|
||||||
|
@ -58,6 +58,9 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
|||||||
|
|
||||||
|
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
|
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
|
||||||
|
uint32_t color_add(uint32_t,uint32_t);
|
||||||
|
|
||||||
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);
|
||||||
@ -129,7 +132,7 @@ void handleIR();
|
|||||||
|
|
||||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||||
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
||||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||||
void serializeInfo(JsonObject root);
|
void serializeInfo(JsonObject root);
|
||||||
void serializeModeNames(JsonArray arr, const char *qstring);
|
void serializeModeNames(JsonArray arr, const char *qstring);
|
||||||
|
@ -90,7 +90,7 @@ void changeEffect(uint8_t fx)
|
|||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
strip.setMode(i, fx);
|
strip.setMode(i, fx);
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ void changePalette(uint8_t pal)
|
|||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.palette = pal;
|
seg.palette = pal;
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
effectSpeed = (byte)constrain(new_val,0,255);
|
effectSpeed = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
setValuesFromMainSeg();
|
setValuesFromMainSeg();
|
||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the hue of the primary color
|
} else { // if Effect == "solid Color", change the hue of the primary color
|
||||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
fastled_col.red = R(sseg.colors[0]);
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
fastled_col.green = G(sseg.colors[0]);
|
||||||
@ -148,7 +148,7 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
effectIntensity = (byte)constrain(new_val,0,255);
|
effectIntensity = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
setValuesFromMainSeg();
|
setValuesFromMainSeg();
|
||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the saturation of the primary color
|
} else { // if Effect == "solid Color", change the saturation of the primary color
|
||||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
fastled_col.red = R(sseg.colors[0]);
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
fastled_col.green = G(sseg.colors[0]);
|
||||||
@ -193,7 +193,7 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
// main segment may not be selected!
|
// main segment may not be selected!
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
byte capabilities = seg.getLightCapabilities();
|
byte capabilities = seg.getLightCapabilities();
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
@ -233,7 +233,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
setValuesFromFirstSelectedSeg();
|
setValuesFromFirstSelectedSeg();
|
||||||
} else {
|
} else {
|
||||||
byte i = strip.getMainSegmentId();
|
byte i = strip.getMainSegmentId();
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
byte capabilities = seg.getLightCapabilities();
|
byte capabilities = seg.getLightCapabilities();
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
bool isRGB = GET_BIT(capabilities, 0); // is segment RGB capable
|
bool isRGB = GET_BIT(capabilities, 0); // is segment RGB capable
|
||||||
@ -253,7 +253,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
|
|
||||||
void changeWhite(int8_t amount, int16_t cct=-1)
|
void changeWhite(int8_t amount, int16_t cct=-1)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
byte r = R(seg.colors[0]);
|
||||||
byte g = G(seg.colors[0]);
|
byte g = G(seg.colors[0]);
|
||||||
byte b = B(seg.colors[0]);
|
byte b = B(seg.colors[0]);
|
||||||
@ -424,7 +424,7 @@ void decodeIR24CT(uint32_t code)
|
|||||||
|
|
||||||
void decodeIR40(uint32_t code)
|
void decodeIR40(uint32_t code)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
byte r = R(seg.colors[0]);
|
||||||
byte g = G(seg.colors[0]);
|
byte g = G(seg.colors[0]);
|
||||||
byte b = B(seg.colors[0]);
|
byte b = B(seg.colors[0]);
|
||||||
|
@ -11,8 +11,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
byte id = elem["id"] | it;
|
byte id = elem["id"] | it;
|
||||||
if (id >= strip.getMaxSegments()) return;
|
if (id >= strip.getMaxSegments()) return;
|
||||||
|
|
||||||
WS2812FX::Segment& seg = strip.getSegment(id);
|
Segment& seg = strip.getSegment(id);
|
||||||
WS2812FX::Segment prev = seg; //make a backup so we can tell if something changed
|
Segment prev = seg; //make a backup so we can tell if something changed
|
||||||
|
|
||||||
uint16_t start = elem["start"] | seg.start;
|
uint16_t start = elem["start"] | seg.start;
|
||||||
int stop = elem["stop"] | -1;
|
int stop = elem["stop"] | -1;
|
||||||
@ -327,7 +327,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
//apply all selected segments
|
//apply all selected segments
|
||||||
//bool didSet = false;
|
//bool didSet = false;
|
||||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
||||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
Segment &sg = strip.getSegment(s);
|
||||||
if (sg.isActive()) {
|
if (sg.isActive()) {
|
||||||
if (sg.isSelected()) {
|
if (sg.isSelected()) {
|
||||||
deserializeSegment(segVar, s, presetId);
|
deserializeSegment(segVar, s, presetId);
|
||||||
@ -396,7 +396,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
return stateResponse;
|
return stateResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
||||||
{
|
{
|
||||||
root["id"] = id;
|
root["id"] = id;
|
||||||
if (segmentBounds) {
|
if (segmentBounds) {
|
||||||
@ -494,7 +494,7 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
|||||||
bool selectedSegmentsOnly = root[F("sc")] | false;
|
bool selectedSegmentsOnly = root[F("sc")] | false;
|
||||||
JsonArray seg = root.createNestedArray("seg");
|
JsonArray seg = root.createNestedArray("seg");
|
||||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
||||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
Segment &sg = strip.getSegment(s);
|
||||||
if (selectedSegmentsOnly && !sg.isSelected()) continue;
|
if (selectedSegmentsOnly && !sg.isSelected()) continue;
|
||||||
if (sg.isActive()) {
|
if (sg.isActive()) {
|
||||||
JsonObject seg0 = seg.createNestedObject();
|
JsonObject seg0 = seg.createNestedObject();
|
||||||
|
@ -8,7 +8,7 @@ void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegment
|
|||||||
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
||||||
void setValuesFromSegment(uint8_t s)
|
void setValuesFromSegment(uint8_t s)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = strip.getSegment(s);
|
Segment& seg = strip.getSegment(s);
|
||||||
col[0] = R(seg.colors[0]);
|
col[0] = R(seg.colors[0]);
|
||||||
col[1] = G(seg.colors[0]);
|
col[1] = G(seg.colors[0]);
|
||||||
col[2] = B(seg.colors[0]);
|
col[2] = B(seg.colors[0]);
|
||||||
@ -30,9 +30,9 @@ void applyValuesToSelectedSegs()
|
|||||||
{
|
{
|
||||||
// copy of first selected segment to tell if value was updated
|
// copy of first selected segment to tell if value was updated
|
||||||
uint8_t firstSel = strip.getFirstSelectedSegId();
|
uint8_t firstSel = strip.getFirstSelectedSegId();
|
||||||
WS2812FX::Segment selsegPrev = strip.getSegment(firstSel);
|
Segment selsegPrev = strip.getSegment(firstSel);
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
||||||
|
|
||||||
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#ifndef PalettesWLED_h
|
#ifndef PalettesWLED_h
|
||||||
#define PalettesWLED_h
|
#define PalettesWLED_h
|
||||||
|
|
||||||
#define GRADIENT_PALETTE_COUNT 58
|
|
||||||
|
|
||||||
const byte ib_jul01_gp[] PROGMEM = {
|
const byte ib_jul01_gp[] PROGMEM = {
|
||||||
0, 194, 1, 1,
|
0, 194, 1, 1,
|
||||||
94, 1, 29, 18,
|
94, 1, 29, 18,
|
||||||
|
@ -612,7 +612,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WS2812FX::Segment& selseg = strip.getSegment(selectedSeg);
|
Segment& selseg = strip.getSegment(selectedSeg);
|
||||||
pos = req.indexOf(F("SV=")); //segment selected
|
pos = req.indexOf(F("SV=")); //segment selected
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
byte t = getNumVal(&req, pos);
|
byte t = getNumVal(&req, pos);
|
||||||
@ -823,7 +823,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
|
|
||||||
// apply to main and all selected segments to prevent #1618.
|
// apply to main and all selected segments to prevent #1618.
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
||||||
if (fxModeChanged) strip.setMode(i, effectIn);
|
if (fxModeChanged) strip.setMode(i, effectIn);
|
||||||
if (speedChanged) seg.speed = speedIn;
|
if (speedChanged) seg.speed = speedIn;
|
||||||
|
@ -28,7 +28,7 @@ void notify(byte callMode, bool followUp)
|
|||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
byte udpOut[WLEDPACKETSIZE];
|
byte udpOut[WLEDPACKETSIZE];
|
||||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
Segment& mainseg = strip.getMainSegment();
|
||||||
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
|
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
|
||||||
udpOut[1] = callMode;
|
udpOut[1] = callMode;
|
||||||
udpOut[2] = bri;
|
udpOut[2] = bri;
|
||||||
@ -92,7 +92,7 @@ void notify(byte callMode, bool followUp)
|
|||||||
udpOut[39] = strip.getMaxSegments();
|
udpOut[39] = strip.getMaxSegments();
|
||||||
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
|
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment &selseg = strip.getSegment(i);
|
Segment &selseg = strip.getSegment(i);
|
||||||
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
|
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
|
||||||
udpOut[0 +ofs] = i;
|
udpOut[0 +ofs] = i;
|
||||||
udpOut[1 +ofs] = selseg.start >> 8;
|
udpOut[1 +ofs] = selseg.start >> 8;
|
||||||
@ -143,7 +143,7 @@ void realtimeLock(uint32_t timeoutMs, byte md)
|
|||||||
if (!realtimeMode && !realtimeOverride) {
|
if (!realtimeMode && !realtimeOverride) {
|
||||||
uint16_t stop, start;
|
uint16_t stop, start;
|
||||||
if (useMainSegmentOnly) {
|
if (useMainSegmentOnly) {
|
||||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
Segment& mainseg = strip.getMainSegment();
|
||||||
start = mainseg.start;
|
start = mainseg.start;
|
||||||
stop = mainseg.stop;
|
stop = mainseg.stop;
|
||||||
mainseg.setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
mainseg.setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
||||||
@ -343,7 +343,7 @@ void handleNotifications()
|
|||||||
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
|
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
|
||||||
uint8_t id = udpIn[0 +ofs];
|
uint8_t id = udpIn[0 +ofs];
|
||||||
if (id > strip.getMaxSegments()) break;
|
if (id > strip.getMaxSegments()) break;
|
||||||
WS2812FX::Segment& selseg = strip.getSegment(id);
|
Segment& selseg = strip.getSegment(id);
|
||||||
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
|
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
|
||||||
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
|
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
|
||||||
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
|
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
|
||||||
@ -378,7 +378,7 @@ void handleNotifications()
|
|||||||
// simple effect sync, applies to all selected segments
|
// simple effect sync, applies to all selected segments
|
||||||
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
|
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
|
||||||
seg.speed = udpIn[9];
|
seg.speed = udpIn[9];
|
||||||
|
@ -418,7 +418,7 @@ void deEEP() {
|
|||||||
segObj[F("ix")] = EEPROM.read(i+16);
|
segObj[F("ix")] = EEPROM.read(i+16);
|
||||||
segObj["pal"] = EEPROM.read(i+17);
|
segObj["pal"] = EEPROM.read(i+17);
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment* seg = strip.getSegments();
|
Segment* seg = strip.getSegments();
|
||||||
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
||||||
if (ver == 2) { //versions before 2004230 did not have opacity
|
if (ver == 2) { //versions before 2004230 did not have opacity
|
||||||
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user