FX updates:

- Ripple (2D & no Bg)
- Glitter (no Bg)
- Sparkle (no Bg)
- Scan (no Bg)
- Two dots (no Bg)
- ICU (no Bg)
- Lightning (no Bg)
- Halloween eyes (no Bg)
- Spots (no Bg)
- Bouncing Balls (no BG)
- Popcorn (no Bg)
- Starburst (no Bg)
- Drip (no Bg)
- Whitespace cleanup
- draw_circle()

"no Bg" will allow overlapping segments if checked.
This commit is contained in:
Blaž Kristan 2023-01-06 09:10:39 +01:00
parent 98be19b29f
commit c7eccfb714
4 changed files with 317 additions and 282 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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)
@ -428,6 +428,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) {
// Bresenhams Algorithm
int d = 3 - (2*radius);
int y = radius, x = 0;
while (y >= x) {
addPixelColorXY(cx+x, cy+y, col);
addPixelColorXY(cx-x, cy+y, col);
addPixelColorXY(cx+x, cy-y, col);
addPixelColorXY(cx-x, cy-y, col);
addPixelColorXY(cx+y, cy+x, col);
addPixelColorXY(cx-y, cy+x, col);
addPixelColorXY(cx+y, cy-x, col);
addPixelColorXY(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();
@ -456,7 +479,7 @@ 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); addPixelColorXY(x0,y0,c);

View File

@ -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);
} }
// Bresenhams 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:
@ -620,7 +634,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 +759,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)
@ -1097,7 +1111,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 +1170,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 +1194,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 +1231,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) {