Skip to content

Commit e1598a9

Browse files
committed
Merge branch '0_15' into blending-styles
2 parents 365c198 + e82f38e commit e1598a9

File tree

10 files changed

+129
-110
lines changed

10 files changed

+129
-110
lines changed

.devcontainer/devcontainer.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@
1212
}
1313
},
1414

15+
// To give the container access to a device serial port, you can uncomment one of the following lines.
16+
// Note: If running on Windows, you will have to do some additional steps:
17+
// https://stackoverflow.com/questions/68527888/how-can-i-use-a-usb-com-port-inside-of-a-vscode-development-container
18+
//
19+
// You can explicitly just forward the port you want to connect to. Replace `/dev/ttyACM0` with the serial port for
20+
// your device. This will only work if the device is plugged in from the start without reconnecting. Adding the
21+
// `dialout` group is needed if read/write permisions for the port are limitted to the dialout user.
22+
// "runArgs": ["--device=/dev/ttyACM0", "--group-add", "dialout"],
23+
//
24+
// Alternatively, you can give more comprehensive access to the host system. This will expose all the host devices to
25+
// the container. Adding the `dialout` group is needed if read/write permisions for the port are limitted to the
26+
// dialout user. This could allow the container to modify unrelated serial devices, which would be a similar level of
27+
// risk to running the build directly on the host.
28+
// "runArgs": ["--privileged", "-v", "/dev/bus/usb:/dev/bus/usb", "--group-add", "dialout"],
29+
1530
// Set *default* container specific settings.json values on container create.
1631
"settings": {
1732
"terminal.integrated.shell.linux": "/bin/bash",

wled00/FX.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,14 +2106,17 @@ uint16_t mode_fire_2012() {
21062106
for (unsigned stripNr=0; stripNr<strips; stripNr++)
21072107
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
21082108

2109-
if (SEGMENT.is2D()) SEGMENT.blur(32);
2109+
if (SEGMENT.is2D()) {
2110+
uint8_t blurAmount = SEGMENT.custom2 >> 2;
2111+
SEGMENT.blur(blurAmount);
2112+
}
21102113

21112114
if (it != SEGENV.step)
21122115
SEGENV.step = it;
21132116

21142117
return FRAMETIME;
21152118
}
2116-
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1;sx=64,ix=160,m12=1"; // bars
2119+
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1;sx=64,ix=160,m12=1,c2=128"; // bars
21172120

21182121

21192122
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
@@ -7456,7 +7459,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma.
74567459
if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(SEGMENT.speed);
74577460

74587461
for (int x=0; x < cols; x++) {
7459-
uint8_t band = map(x, 0, cols-1, 0, NUM_BANDS - 1);
7462+
uint8_t band = map(x, 0, cols, 0, NUM_BANDS);
74607463
if (NUM_BANDS < 16) band = map(band, 0, NUM_BANDS - 1, 0, 15); // always use full range. comment out this line to get the previous behaviour.
74617464
band = constrain(band, 0, 15);
74627465
unsigned colorIndex = band * 17;

wled00/FX.h

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -590,17 +590,17 @@ typedef struct Segment {
590590

591591
// transition functions
592592
void startTransition(uint16_t dur); // transition has to start before actual segment values change
593-
void stopTransition(void); // ends transition mode by destroying transition structure
594-
void handleTransition(void);
593+
void stopTransition(void); // ends transition mode by destroying transition structure (does nothing if not in transition)
594+
inline void handleTransition(void) { if (progress() == 0xFFFFU) stopTransition(); }
595595
#ifndef WLED_DISABLE_MODE_BLEND
596596
void swapSegenv(tmpsegd_t &tmpSegD); // copies segment data into specifed buffer, if buffer is not a transition buffer, segment data is overwritten from transition buffer
597597
void restoreSegenv(tmpsegd_t &tmpSegD); // restores segment data from buffer, if buffer is not transition buffer, changed values are copied to transition buffer
598598
#endif
599-
uint16_t progress(void); // transition progression between 0-65535
600-
uint8_t currentBri(bool useCct = false); // current segment brightness/CCT (blended while in transition)
601-
uint8_t currentMode(void); // currently active effect/mode (while in transition)
602-
uint8_t currentPalette(void); // currently active palette (while in transition)
603-
uint32_t currentColor(uint8_t slot); // currently active segment color (blended while in transition)
599+
uint16_t progress(void) const; // transition progression between 0-65535
600+
uint8_t currentBri(bool useCct = false) const; // current segment brightness/CCT (blended while in transition)
601+
uint8_t currentMode(void) const; // currently active effect/mode (while in transition)
602+
uint8_t currentPalette(void) const; // currently active palette (while in transition)
603+
uint32_t currentColor(uint8_t slot) const; // currently active segment color (blended while in transition)
604604
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
605605
void setCurrentPalette(void);
606606

@@ -618,8 +618,8 @@ typedef struct Segment {
618618
#ifndef WLED_DISABLE_MODE_BLEND
619619
static inline void setClippingRect(int startX, int stopX, int startY = 0, int stopY = 1) { _clipStart = startX; _clipStop = stopX; _clipStartY = startY; _clipStopY = stopY; };
620620
#endif
621-
bool isPixelClipped(int i);
622-
uint32_t getPixelColor(int i);
621+
bool isPixelClipped(int i) const;
622+
uint32_t getPixelColor(int i) const;
623623
// 1D support functions (some implement 2D as well)
624624
void blur(uint8_t, bool smear = false);
625625
void fill(uint32_t c);
@@ -631,8 +631,8 @@ typedef struct Segment {
631631
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); }
632632
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); }
633633
inline void fadePixelColor(uint16_t n, uint8_t fade) { setPixelColor(n, color_fade(getPixelColor(n), fade, true)); }
634-
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
635-
uint32_t color_wheel(uint8_t pos);
634+
uint32_t color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255) const;
635+
uint32_t color_wheel(uint8_t pos) const;
636636

637637
// 2D matrix
638638
uint16_t virtualWidth(void) const; // segment width in virtual pixels (accounts for groupping and spacing)
@@ -650,8 +650,8 @@ typedef struct Segment {
650650
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
651651
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
652652
#endif
653-
bool isPixelXYClipped(int x, int y);
654-
uint32_t getPixelColorXY(int x, int y);
653+
bool isPixelXYClipped(int x, int y) const;
654+
uint32_t getPixelColorXY(int x, int y) const;
655655
// 2D support functions
656656
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); }
657657
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
@@ -761,15 +761,7 @@ class WS2812FX { // 96 bytes
761761
customMappingSize(0),
762762
_lastShow(0),
763763
_segment_index(0),
764-
_mainSegment(0),
765-
_queuedChangesSegId(255),
766-
_qStart(0),
767-
_qStop(0),
768-
_qStartY(0),
769-
_qStopY(0),
770-
_qGrouping(0),
771-
_qSpacing(0),
772-
_qOffset(0)
764+
_mainSegment(0)
773765
{
774766
WS2812FX::instance = this;
775767
_mode.reserve(_modeCount); // allocate memory to prevent initial fragmentation (does not increase size())
@@ -976,14 +968,6 @@ class WS2812FX { // 96 bytes
976968

977969
uint8_t _segment_index;
978970
uint8_t _mainSegment;
979-
uint8_t _queuedChangesSegId;
980-
uint16_t _qStart, _qStop, _qStartY, _qStopY;
981-
uint8_t _qGrouping, _qSpacing;
982-
uint16_t _qOffset;
983-
/*
984-
void
985-
setUpSegmentFromQueuedChanges(void);
986-
*/
987971
};
988972

989973
extern const char JSON_mode_names[];

wled00/FX_2Dfcn.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ uint16_t IRAM_ATTR Segment::XY(int x, int y) {
171171
// if clipping start > stop the clipping range is inverted
172172
// _modeBlend==true -> old effect during transition
173173
// _modeBlend==false -> new effect during transition
174-
bool IRAM_ATTR Segment::isPixelXYClipped(int x, int y) {
174+
bool IRAM_ATTR Segment::isPixelXYClipped(int x, int y) const {
175175
#ifndef WLED_DISABLE_MODE_BLEND
176176
if (_clipStart != _clipStop && blendingStyle > BLEND_STYLE_FADE) {
177177
const bool invertX = _clipStart > _clipStop;
@@ -234,7 +234,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
234234

235235
if (reverse ) x = vW - x - 1;
236236
if (reverse_y) y = vH - y - 1;
237-
if (transpose) { unsigned t = x; x = y; y = t; } // swap X & Y if segment transposed
237+
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed
238238

239239
x *= groupLength(); // expand to physical pixels
240240
y *= groupLength(); // expand to physical pixels
@@ -318,7 +318,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
318318
#endif
319319

320320
// returns RGBW values of pixel
321-
uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
321+
uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) const {
322322
if (!isActive()) return 0; // not active
323323

324324
int vW = virtualWidth();
@@ -346,9 +346,9 @@ uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
346346

347347
if (x >= vW || y >= vH || x<0 || y<0 || isPixelXYClipped(x,y)) return 0; // if pixel would fall out of virtual segment just exit
348348

349-
if (reverse ) x = vW - x - 1;
349+
if (reverse ) x = vW - x - 1;
350350
if (reverse_y) y = vH - y - 1;
351-
if (transpose) { unsigned t = x; x = y; y = t; } // swap X & Y if segment transposed
351+
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed
352352
x *= groupLength(); // expand to physical pixels
353353
y *= groupLength(); // expand to physical pixels
354354
if (x >= width() || y >= height()) return 0;

wled00/FX_fcn.cpp

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,8 @@ void Segment::stopTransition() {
328328
}
329329
}
330330

331-
void Segment::handleTransition() {
332-
unsigned _progress = progress();
333-
if (_progress == 0xFFFFU) stopTransition();
334-
}
335-
336331
// transition progression between 0-65535
337-
uint16_t IRAM_ATTR Segment::progress() {
332+
uint16_t IRAM_ATTR Segment::progress() const {
338333
if (isInTransition()) {
339334
unsigned diff = millis() - _t->_start;
340335
if (_t->_dur > 0 && diff < _t->_dur) return diff * 0xFFFFU / _t->_dur;
@@ -413,7 +408,7 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
413408
}
414409
#endif
415410

416-
uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
411+
uint8_t IRAM_ATTR Segment::currentBri(bool useCct) const {
417412
uint32_t prog = progress();
418413
uint32_t curBri = useCct ? cct : (on ? opacity : 0);
419414
if (prog < 0xFFFFU) {
@@ -430,7 +425,7 @@ uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
430425
return curBri;
431426
}
432427

433-
uint8_t IRAM_ATTR Segment::currentMode() {
428+
uint8_t IRAM_ATTR Segment::currentMode() const {
434429
#ifndef WLED_DISABLE_MODE_BLEND
435430
unsigned prog = progress();
436431
if (prog == 0xFFFFU) return mode;
@@ -446,7 +441,7 @@ uint8_t IRAM_ATTR Segment::currentMode() {
446441
#endif
447442
}
448443

449-
uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
444+
uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) const {
450445
if (slot >= NUM_COLORS) slot = 0;
451446
uint32_t prog = progress();
452447
if (prog == 0xFFFFU) return colors[slot];
@@ -463,7 +458,7 @@ uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
463458
#endif
464459
}
465460

466-
uint8_t IRAM_ATTR Segment::currentPalette() {
461+
uint8_t IRAM_ATTR Segment::currentPalette() const {
467462
unsigned prog = progress();
468463
if (prog < 0xFFFFU) {
469464
#ifndef WLED_DISABLE_MODE_BLEND
@@ -731,9 +726,11 @@ uint16_t IRAM_ATTR Segment::virtualLength() const {
731726
vLen = vH;
732727
break;
733728
case M12_pCorner:
734-
case M12_pArc:
735729
vLen = max(vW,vH); // get the longest dimension
736730
break;
731+
case M12_pArc:
732+
vLen = sqrt16(vH*vH + vW*vW); // use diagonal
733+
break;
737734
case M12_sPinwheel:
738735
vLen = getPinwheelLength(vW, vH);
739736
break;
@@ -751,7 +748,7 @@ uint16_t IRAM_ATTR Segment::virtualLength() const {
751748
// if clipping start > stop the clipping range is inverted
752749
// _modeBlend==true -> old effect during transition
753750
// _modeBlend==false -> new effect during transition
754-
bool IRAM_ATTR Segment::isPixelClipped(int i) {
751+
bool IRAM_ATTR Segment::isPixelClipped(int i) const {
755752
#ifndef WLED_DISABLE_MODE_BLEND
756753
if (_clipStart != _clipStop && blendingStyle > BLEND_STYLE_FADE) {
757754
bool invert = _clipStart > _clipStop; // ineverted start & stop
@@ -804,12 +801,14 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
804801
if (i==0)
805802
setPixelColorXY(0, 0, col);
806803
else {
807-
float step = HALF_PI / (2.85f*i);
808-
for (float rad = 0.0f; rad <= HALF_PI+step/2; rad += step) {
809-
// may want to try float version as well (with or without antialiasing)
810-
int x = roundf(sin_t(rad) * i);
811-
int y = roundf(cos_t(rad) * i);
804+
float r = i;
805+
float step = HALF_PI / (2.8284f * r + 4); // we only need (PI/4)/(r/sqrt(2)+1) steps
806+
for (float rad = 0.0f; rad <= (HALF_PI/2)+step/2; rad += step) {
807+
int x = roundf(sin_t(rad) * r);
808+
int y = roundf(cos_t(rad) * r);
809+
// exploit symmetry
812810
setPixelColorXY(x, y, col);
811+
setPixelColorXY(y, x, col);
813812
}
814813
// Bresenham’s Algorithm (may not fill every pixel)
815814
//int d = 3 - (2*i);
@@ -981,7 +980,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
981980
}
982981
#endif
983982

984-
uint32_t IRAM_ATTR Segment::getPixelColor(int i)
983+
uint32_t IRAM_ATTR Segment::getPixelColor(int i) const
985984
{
986985
if (!isActive()) return 0; // not active
987986
#ifndef WLED_DISABLE_2D
@@ -1161,7 +1160,7 @@ void Segment::fade_out(uint8_t rate) {
11611160
const int rows = virtualHeight(); // will be 1 for 1D
11621161

11631162
rate = (255-rate) >> 1;
1164-
float mappedRate = float(rate) +1.1f;
1163+
float mappedRate = 1.0f / (float(rate) + 1.1f);
11651164

11661165
uint32_t color = colors[1]; // SEGCOLOR(1); // target color
11671166
int w2 = W(color);
@@ -1171,15 +1170,16 @@ void Segment::fade_out(uint8_t rate) {
11711170

11721171
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
11731172
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
1173+
if (color == colors[1]) continue; // already at target color
11741174
int w1 = W(color);
11751175
int r1 = R(color);
11761176
int g1 = G(color);
11771177
int b1 = B(color);
11781178

1179-
int wdelta = (w2 - w1) / mappedRate;
1180-
int rdelta = (r2 - r1) / mappedRate;
1181-
int gdelta = (g2 - g1) / mappedRate;
1182-
int bdelta = (b2 - b1) / mappedRate;
1179+
int wdelta = (w2 - w1) * mappedRate;
1180+
int rdelta = (r2 - r1) * mappedRate;
1181+
int gdelta = (g2 - g1) * mappedRate;
1182+
int bdelta = (b2 - b1) * mappedRate;
11831183

11841184
// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
11851185
wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1;
@@ -1251,7 +1251,7 @@ void Segment::blur(uint8_t blur_amount, bool smear) {
12511251
* The colours are a transition r -> g -> b -> back to r
12521252
* Inspired by the Adafruit examples.
12531253
*/
1254-
uint32_t Segment::color_wheel(uint8_t pos) {
1254+
uint32_t Segment::color_wheel(uint8_t pos) const {
12551255
if (palette) return color_from_palette(pos, false, true, 0); // perhaps "strip.paletteBlend < 2" should be better instead of "true"
12561256
uint8_t w = W(currentColor(0));
12571257
pos = 255 - pos;
@@ -1275,7 +1275,7 @@ uint32_t Segment::color_wheel(uint8_t pos) {
12751275
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
12761276
* @returns Single color from palette
12771277
*/
1278-
uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) {
1278+
uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) const {
12791279
uint32_t color = gamma32(currentColor(mcol));
12801280

12811281
// default palette or no RGB support on segment

wled00/bus_manager.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -378,30 +378,48 @@ void BusDigital::cleanup() {
378378
}
379379

380380

381+
#ifdef ESP8266
382+
// 1 MHz clock
383+
#define CLOCK_FREQUENCY 1000000UL
384+
#else
385+
// Use XTAL clock if possible to avoid timer frequency error when setting APB clock < 80 Mhz
386+
// https://github.com/espressif/arduino-esp32/blob/2.0.2/cores/esp32/esp32-hal-ledc.c
387+
#ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK
388+
#define CLOCK_FREQUENCY 40000000UL
389+
#else
390+
#define CLOCK_FREQUENCY 80000000UL
391+
#endif
392+
#endif
393+
394+
#ifdef ESP8266
395+
#define MAX_BIT_WIDTH 10
396+
#else
397+
#ifdef SOC_LEDC_TIMER_BIT_WIDE_NUM
398+
// C6/H2/P4: 20 bit, S2/S3/C2/C3: 14 bit
399+
#define MAX_BIT_WIDTH SOC_LEDC_TIMER_BIT_WIDE_NUM
400+
#else
401+
// ESP32: 20 bit (but in reality we would never go beyond 16 bit as the frequency would be to low)
402+
#define MAX_BIT_WIDTH 20
403+
#endif
404+
#endif
405+
381406
BusPwm::BusPwm(BusConfig &bc)
382407
: Bus(bc.type, bc.start, bc.autoWhite, 1, bc.reversed)
383408
{
384409
if (!IS_PWM(bc.type)) return;
385410
unsigned numPins = NUM_PWM_PINS(bc.type);
386411
_frequency = bc.frequency ? bc.frequency : WLED_PWM_FREQ;
412+
// duty cycle resolution (_depth) can be extracted from this formula: CLOCK_FREQUENCY > _frequency * 2^_depth
413+
for (_depth = MAX_BIT_WIDTH; _depth > 8; _depth--) if (((CLOCK_FREQUENCY/_frequency) >> _depth) > 0) break;
387414

388415
#ifdef ESP8266
389-
// duty cycle resolution (_depth) can be extracted from this formula: 1MHz > _frequency * 2^_depth
390-
if (_frequency > 1760) _depth = 8;
391-
else if (_frequency > 880) _depth = 9;
392-
else _depth = 10; // WLED_PWM_FREQ <= 880Hz
393416
analogWriteRange((1<<_depth)-1);
394417
analogWriteFreq(_frequency);
395418
#else
396419
_ledcStart = pinManager.allocateLedc(numPins);
397420
if (_ledcStart == 255) { //no more free LEDC channels
398421
deallocatePins(); return;
399422
}
400-
// duty cycle resolution (_depth) can be extracted from this formula: 80MHz > _frequency * 2^_depth
401-
if (_frequency > 78124) _depth = 9;
402-
else if (_frequency > 39062) _depth = 10;
403-
else if (_frequency > 19531) _depth = 11;
404-
else _depth = 12; // WLED_PWM_FREQ <= 19531Hz
405423
#endif
406424

407425
for (unsigned i = 0; i < numPins; i++) {
@@ -419,7 +437,7 @@ BusPwm::BusPwm(BusConfig &bc)
419437
}
420438
_data = _pwmdata; // avoid malloc() and use stack
421439
_valid = true;
422-
DEBUG_PRINTF_P(PSTR("%successfully inited PWM strip with type %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
440+
DEBUG_PRINTF_P(PSTR("%successfully inited PWM strip with type %u, frequency %u, bit depth %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _frequency, _depth, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
423441
}
424442

425443
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {

0 commit comments

Comments
 (0)