Merge pull request #3006 from Aircoookie/fx-update
FX updates, 2nd try.
This commit is contained in:
commit
9144ccac6b
555
wled00/FX.cpp
555
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
11
wled00/FX.h
11
wled00/FX.h
@ -519,9 +519,9 @@ typedef struct Segment {
|
|||||||
bool allocateData(size_t len);
|
bool allocateData(size_t len);
|
||||||
void deallocateData(void);
|
void deallocateData(void);
|
||||||
void resetIfRequired(void);
|
void resetIfRequired(void);
|
||||||
/**
|
/**
|
||||||
* Flags that before the next effect is calculated,
|
* Flags that before the next effect is calculated,
|
||||||
* the internal segment state should be reset.
|
* the internal segment state should be reset.
|
||||||
* Call resetIfRequired before calling the next effect function.
|
* Call resetIfRequired before calling the next effect function.
|
||||||
* Safe to call from interrupts and network requests.
|
* Safe to call from interrupts and network requests.
|
||||||
*/
|
*/
|
||||||
@ -588,6 +588,7 @@ typedef struct Segment {
|
|||||||
void moveX(int8_t delta);
|
void moveX(int8_t delta);
|
||||||
void moveY(int8_t delta);
|
void moveY(int8_t delta);
|
||||||
void move(uint8_t dir, uint8_t delta);
|
void move(uint8_t dir, uint8_t delta);
|
||||||
|
void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
||||||
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
|
||||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
|
||||||
@ -641,7 +642,7 @@ class WS2812FX { // 96 bytes
|
|||||||
} mode_data_t;
|
} mode_data_t;
|
||||||
|
|
||||||
static WS2812FX* instance;
|
static WS2812FX* instance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WS2812FX() :
|
WS2812FX() :
|
||||||
@ -885,9 +886,9 @@ class WS2812FX { // 96 bytes
|
|||||||
|
|
||||||
uint16_t* customMappingTable;
|
uint16_t* customMappingTable;
|
||||||
uint16_t customMappingSize;
|
uint16_t customMappingSize;
|
||||||
|
|
||||||
uint32_t _lastShow;
|
uint32_t _lastShow;
|
||||||
|
|
||||||
uint8_t _segment_index;
|
uint8_t _segment_index;
|
||||||
uint8_t _mainSegment;
|
uint8_t _mainSegment;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
FX_2Dfcn.cpp contains all 2D utility functions
|
FX_2Dfcn.cpp contains all 2D utility functions
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
|
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
|
||||||
@ -164,6 +164,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
if (leds) leds[XY(x,y)] = col;
|
if (leds) leds[XY(x,y)] = col;
|
||||||
|
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
|
if (!_bri_t) return;
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
byte g = scale8(G(col), _bri_t);
|
||||||
@ -428,6 +429,29 @@ void Segment::move(uint8_t dir, uint8_t delta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
|
// Bresenham’s Algorithm
|
||||||
|
int d = 3 - (2*radius);
|
||||||
|
int y = radius, x = 0;
|
||||||
|
while (y >= x) {
|
||||||
|
setPixelColorXY(cx+x, cy+y, col);
|
||||||
|
setPixelColorXY(cx-x, cy+y, col);
|
||||||
|
setPixelColorXY(cx+x, cy-y, col);
|
||||||
|
setPixelColorXY(cx-x, cy-y, col);
|
||||||
|
setPixelColorXY(cx+y, cy+x, col);
|
||||||
|
setPixelColorXY(cx-y, cy+x, col);
|
||||||
|
setPixelColorXY(cx+y, cy-x, col);
|
||||||
|
setPixelColorXY(cx-y, cy-x, col);
|
||||||
|
x++;
|
||||||
|
if (d > 0) {
|
||||||
|
y--;
|
||||||
|
d += 4 * (x - y) + 10;
|
||||||
|
} else {
|
||||||
|
d += 4 * x + 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
const uint16_t cols = virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
@ -437,7 +461,7 @@ void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
if (x * x + y * y <= radius * radius &&
|
if (x * x + y * y <= radius * radius &&
|
||||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
||||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
||||||
addPixelColorXY(cx + x, cy + y, col);
|
setPixelColorXY(cx + x, cy + y, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,10 +480,10 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
const uint16_t rows = virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||||
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||||
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||||
int16_t err = (dx>dy ? dx : -dy)/2, e2;
|
int16_t err = (dx>dy ? dx : -dy)/2, e2;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
addPixelColorXY(x0,y0,c);
|
setPixelColorXY(x0,y0,c);
|
||||||
if (x0==x1 && y0==y1) break;
|
if (x0==x1 && y0==y1) break;
|
||||||
e2 = err;
|
e2 = err;
|
||||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||||
|
@ -174,18 +174,18 @@ void Segment::deallocateData() {
|
|||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If reset of this segment was requested, clears runtime
|
* If reset of this segment was requested, clears runtime
|
||||||
* settings of this segment.
|
* settings of this segment.
|
||||||
* Must not be called while an effect mode function is running
|
* Must not be called while an effect mode function is running
|
||||||
* because it could access the data buffer and this method
|
* because it could access the data buffer and this method
|
||||||
* may free that data buffer.
|
* may free that data buffer.
|
||||||
*/
|
*/
|
||||||
void Segment::resetIfRequired() {
|
void Segment::resetIfRequired() {
|
||||||
if (reset) {
|
if (reset) {
|
||||||
if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; }
|
if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; }
|
||||||
//if (_t) { delete _t; _t = nullptr; transitional = false; }
|
//if (_t) { delete _t; _t = nullptr; transitional = false; }
|
||||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,6 +574,20 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
int y = roundf(cos_t(rad) * i);
|
int y = roundf(cos_t(rad) * i);
|
||||||
setPixelColorXY(x, y, col);
|
setPixelColorXY(x, y, col);
|
||||||
}
|
}
|
||||||
|
// Bresenham’s Algorithm
|
||||||
|
//int d = 3 - (2*i);
|
||||||
|
//int y = i, x = 0;
|
||||||
|
//while (y >= x) {
|
||||||
|
// setPixelColorXY(x, y, col);
|
||||||
|
// setPixelColorXY(y, x, col);
|
||||||
|
// x++;
|
||||||
|
// if (d > 0) {
|
||||||
|
// y--;
|
||||||
|
// d += 4 * (x - y) + 10;
|
||||||
|
// } else {
|
||||||
|
// d += 4 * x + 6;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case M12_pCorner:
|
case M12_pCorner:
|
||||||
@ -596,6 +610,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
|
|
||||||
uint16_t len = length();
|
uint16_t len = length();
|
||||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
|
if (!_bri_t) return;
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
byte g = scale8(G(col), _bri_t);
|
||||||
@ -620,7 +635,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
uint16_t indexSet = i + ((reverse) ? -j : j);
|
uint16_t indexSet = i + ((reverse) ? -j : j);
|
||||||
if (indexSet >= start && indexSet < stop) {
|
if (indexSet >= start && indexSet < stop) {
|
||||||
if (mirror) { //set the corresponding mirrored pixel
|
if (mirror) { //set the corresponding mirrored pixel
|
||||||
uint16_t indexMir = stop - indexSet + start - 1;
|
uint16_t indexMir = stop - indexSet + start - 1;
|
||||||
indexMir += offset; // offset/phase
|
indexMir += offset; // offset/phase
|
||||||
if (indexMir >= stop) indexMir -= len; // wrap
|
if (indexMir >= stop) indexMir -= len; // wrap
|
||||||
strip.setPixelColor(indexMir, col);
|
strip.setPixelColor(indexMir, col);
|
||||||
@ -745,7 +760,7 @@ void Segment::refreshLightCapabilities() {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_ANALOG_5CH:
|
case TYPE_ANALOG_5CH:
|
||||||
case TYPE_ANALOG_2CH:
|
case TYPE_ANALOG_2CH:
|
||||||
capabilities |= 0x04; //segment supports white CCT
|
capabilities |= 0x04; //segment supports white CCT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (correctWB && !(type == TYPE_ANALOG_1CH || type == TYPE_ONOFF)) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
if (correctWB && !(type == TYPE_ANALOG_1CH || type == TYPE_ONOFF)) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
||||||
@ -1056,7 +1071,7 @@ void WS2812FX::service() {
|
|||||||
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||||
delay = (*_mode[seg.currentMode(seg.mode)])();
|
delay = (*_mode[seg.currentMode(seg.mode)])();
|
||||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||||
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // foce faster updates during transition
|
if (seg.transitional && delay > FRAMETIME) delay = FRAMETIME; // force faster updates during transition
|
||||||
|
|
||||||
seg.handleTransition();
|
seg.handleTransition();
|
||||||
}
|
}
|
||||||
@ -1097,7 +1112,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
|
|||||||
//Stay safe with high amperage and have a reasonable safety margin!
|
//Stay safe with high amperage and have a reasonable safety margin!
|
||||||
//I am NOT to be held liable for burned down garages!
|
//I am NOT to be held liable for burned down garages!
|
||||||
|
|
||||||
//fine tune power estimation constants for your setup
|
//fine tune power estimation constants for your setup
|
||||||
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
|
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
|
||||||
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
||||||
|
|
||||||
@ -1156,7 +1171,7 @@ void WS2812FX::estimateCurrentAndLimitBri() {
|
|||||||
|
|
||||||
uint32_t powerSum0 = powerSum;
|
uint32_t powerSum0 = powerSum;
|
||||||
powerSum *= _brightness;
|
powerSum *= _brightness;
|
||||||
|
|
||||||
if (powerSum > powerBudget) //scale brightness down to stay in current limit
|
if (powerSum > powerBudget) //scale brightness down to stay in current limit
|
||||||
{
|
{
|
||||||
float scale = (float)powerBudget / (float)powerSum;
|
float scale = (float)powerBudget / (float)powerSum;
|
||||||
@ -1180,7 +1195,7 @@ void WS2812FX::show(void) {
|
|||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
|
|
||||||
estimateCurrentAndLimitBri();
|
estimateCurrentAndLimitBri();
|
||||||
|
|
||||||
// some buses send asynchronously and this method will return before
|
// some buses send asynchronously and this method will return before
|
||||||
// all of the data has been sent.
|
// all of the data has been sent.
|
||||||
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
||||||
@ -1217,7 +1232,7 @@ void WS2812FX::setTargetFps(uint8_t fps) {
|
|||||||
|
|
||||||
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||||
if (segid >= _segments.size()) return;
|
if (segid >= _segments.size()) return;
|
||||||
|
|
||||||
if (m >= getModeCount()) m = getModeCount() - 1;
|
if (m >= getModeCount()) m = getModeCount() - 1;
|
||||||
|
|
||||||
if (_segments[segid].mode != m) {
|
if (_segments[segid].mode != m) {
|
||||||
|
Loading…
Reference in New Issue
Block a user