Merge branch 'mdev' of https://github.com/troyhacks/WLED into mdev
This commit is contained in:
@@ -2148,7 +2148,7 @@ uint16_t mode_fire_2012() {
|
||||
|
||||
// Step 4. Map from heat cells to LED colors
|
||||
for (int j = 0; j < SEGLEN; j++) {
|
||||
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j],byte(240)), 255, NOBLEND));
|
||||
SEGMENT.setPixelColor(indexToVStrip(j, stripNr), ColorFromPalette(SEGPALETTE, min(heat[j], byte(240)), 255, NOBLEND));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2156,14 +2156,19 @@ uint16_t mode_fire_2012() {
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
||||
|
||||
if (SEGMENT.is2D()) SEGMENT.blur(32);
|
||||
if (SEGMENT.is2D()) {
|
||||
uint8_t blurAmount = SEGMENT.custom2 >> 2;
|
||||
if (blurAmount > 48) blurAmount += blurAmount-48; // extra blur when slider > 192 (bush burn)
|
||||
if (blurAmount < 16) SEGMENT.blurCols(SEGMENT.custom2 >> 1); // no side-burn when slider < 64 (faster)
|
||||
else SEGMENT.blur(blurAmount);
|
||||
}
|
||||
|
||||
if (it != SEGENV.step)
|
||||
SEGENV.step = it;
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1.5d;sx=64,ix=160,m12=1"; // bars WLEDMM 1.5d,
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,2D Blur,Boost;;!;1.5d;sx=64,ix=160,c2=128,m12=1"; // bars WLEDMM 1.5d,
|
||||
|
||||
|
||||
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
|
||||
@@ -4922,17 +4927,18 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(16 + (SEGMENT.speed>>3)); // create fading trails
|
||||
unsigned long t = strip.now/128; // timebase
|
||||
const unsigned long ratio = 128; // rotation speed
|
||||
unsigned long t = strip.now; // timebase
|
||||
// outer stars
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
|
||||
y = beatsin8(SEGMENT.intensity>>3, 0, rows - 1, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
|
||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||
}
|
||||
// inner stars
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
x = beatsin8(SEGMENT.custom2>>3, cols/4, cols - 1 - cols/4, 0, ((i % 2) ? 128 : 0) + (t * i)/ratio);
|
||||
y = beatsin8(SEGMENT.custom3 , rows/4, rows - 1 - rows/4, 0, ((i % 2) ? 192 : 64) + (t * i)/ratio);
|
||||
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||
}
|
||||
// central white dot
|
||||
@@ -6270,6 +6276,10 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
}
|
||||
|
||||
SEGMENT.fadeToBlackBy(20);
|
||||
bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 6); //WLEDMM
|
||||
const uint16_t minDim = min(cols, rows); // WLEDMM use smaller dimension to find good blob size
|
||||
float max_grow = min(minDim/4.f,2.f);
|
||||
if (minDim>=24) max_grow =(minDim/8.0f); // WLEDMM allow bigger blobs
|
||||
|
||||
// Bounce balls around
|
||||
for (size_t i = 0; i < Amount; i++) {
|
||||
@@ -6278,18 +6288,18 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
if (blob->grow[i]) {
|
||||
// enlarge radius until it is >= 4
|
||||
blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
||||
if (blob->r[i] >= min(cols/4.f,2.f)) {
|
||||
if (blob->r[i] >= max_grow) {
|
||||
blob->grow[i] = false;
|
||||
}
|
||||
} else {
|
||||
// reduce radius until it is < 1
|
||||
blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
|
||||
if (blob->r[i] < 1.f) {
|
||||
if (blob->r[i] < 0.8f) {
|
||||
blob->grow[i] = true;
|
||||
}
|
||||
}
|
||||
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
|
||||
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c);
|
||||
if (blob->r[i] > 1.f) SEGMENT.fillCircle(roundf(blob->x[i]), roundf(blob->y[i]), roundf(blob->r[i]), c, drawAA);
|
||||
else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
|
||||
// move x
|
||||
if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f));
|
||||
@@ -6662,20 +6672,26 @@ uint16_t mode_2DWaverly(void) {
|
||||
|
||||
long t = strip.now / 2;
|
||||
for (int i = 0; i < cols; i++) {
|
||||
uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
|
||||
uint16_t thisMax = map(thisVal, 0, 512, 0, rows);
|
||||
//uint16_t thisVal = volumeSmth*SEGMENT.intensity/64 * inoise8(i * 45 , t , t)/64; // WLEDMM back to SR code
|
||||
unsigned thisVal = unsigned(volumeSmth*SEGMENT.intensity) * inoise8(i * 45 , t , t) / (64*64); // WLEDMM same result but more accurate
|
||||
|
||||
for (int j = 0; j < thisMax; j++) {
|
||||
//int thisMax = map(thisVal, 0, 512, 0, rows);
|
||||
int thisMax = (thisVal * rows) / 512; // WLEDMM same result, just faster
|
||||
int thisMax2 = min(int(rows), thisMax); // WLEDMM limit height to visible are
|
||||
|
||||
for (int j = 0; j < thisMax2; j++) {
|
||||
//int jmap = map(j, 0, thisMax, 250, 0);
|
||||
int jmap = 250 - ((j * 250) / thisMax); // WLEDMM same result, just faster
|
||||
if (!SEGENV.check1)
|
||||
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
|
||||
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
|
||||
SEGMENT.addPixelColorXY(i, j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
|
||||
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
|
||||
}
|
||||
}
|
||||
SEGMENT.blur(16);
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_2DWaverly()
|
||||
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Amplification,Sensitivity,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
|
||||
static const char _data_FX_MODE_2DWAVERLY[] PROGMEM = "Waverly ☾@Fade Rate,Amplification,,,,No Clouds,Sound Pressure,AGC debug;;!;2v;ix=64,si=0"; // Beatsin
|
||||
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
@@ -7511,9 +7527,9 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
}
|
||||
|
||||
// shift the pixels one pixel up
|
||||
SEGMENT.setPixelColor(0, color);
|
||||
// if SEGLEN equals 1 this loop won't execute
|
||||
for (int i = SEGLEN - 1; i > 0; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); //move to the left
|
||||
SEGMENT.setPixelColor(0, color);
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
|
||||
149
wled00/FX.h
149
wled00/FX.h
@@ -33,7 +33,7 @@
|
||||
|
||||
bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
|
||||
void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp
|
||||
bool strip_uses_global_leds(void); // WLEDMM implemented in FX_fcn.cpp
|
||||
bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented in FX_fcn.cpp
|
||||
|
||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||
#define USE_GET_MILLISECOND_TIMER
|
||||
@@ -434,6 +434,20 @@ typedef struct Segment {
|
||||
static size_t _usedSegmentData; // WLEDMM uint16_t is too small
|
||||
void setPixelColorXY_fast(int x, int y,uint32_t c, uint32_t scaled_col, int cols, int rows); // set relative pixel within segment with color - faster, but no error checking!!!
|
||||
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
// WLEDMM cache some values that won't change while drawing a frame
|
||||
bool _isSimpleSegment = false;
|
||||
bool _isValid2D = false;
|
||||
uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity
|
||||
bool _firstFill = true; // dirty HACK support
|
||||
uint16_t _2dWidth = 0; // virtualWidth
|
||||
uint16_t _2dHeight = 0; // virtualHeight
|
||||
|
||||
void setPixelColorXY_slow(int x, int y, uint32_t c); // set relative pixel within segment with color - full slow version
|
||||
#else
|
||||
void setPixelColorXY_slow(int x, int y, uint32_t c) { setPixelColorXY(x,y,c); } // not FASTPATH - slow is the normal
|
||||
#endif
|
||||
|
||||
// perhaps this should be per segment, not static
|
||||
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
||||
|
||||
@@ -587,6 +601,7 @@ typedef struct Segment {
|
||||
bool allocateData(size_t len);
|
||||
void deallocateData(void);
|
||||
void resetIfRequired(void);
|
||||
void startFrame(void); // cache a few values that don't change while an effect is drawing
|
||||
/**
|
||||
* Flags that before the next effect is calculated,
|
||||
* the internal segment state should be reset.
|
||||
@@ -625,7 +640,7 @@ typedef struct Segment {
|
||||
void setPixelColor(float i, uint32_t c, bool aa = true);
|
||||
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); }
|
||||
inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
|
||||
uint32_t __attribute__((pure)) getPixelColor(int i); // WLEDMM attribute added
|
||||
uint32_t __attribute__((pure)) getPixelColor(int i) const; // WLEDMM attribute added
|
||||
// 1D support functions (some implement 2D as well)
|
||||
void blur(uint8_t, bool smear = false);
|
||||
void fill(uint32_t c);
|
||||
@@ -637,11 +652,22 @@ typedef struct Segment {
|
||||
inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline
|
||||
inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline
|
||||
void fadePixelColor(uint16_t n, uint8_t fade);
|
||||
uint8_t get_random_wheel_index(uint8_t pos);
|
||||
uint8_t get_random_wheel_index(uint8_t pos) const;
|
||||
uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255);
|
||||
uint32_t __attribute__((pure)) color_wheel(uint8_t pos);
|
||||
|
||||
// 2D Blur: shortcuts for bluring columns or rows only (50% faster than full 2D blur)
|
||||
inline void blurCols(fract8 blur_amount, bool smear = false) { // blur all columns
|
||||
const unsigned cols = virtualWidth();
|
||||
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount, smear);
|
||||
}
|
||||
inline void blurRows(fract8 blur_amount, bool smear = false) { // blur all rows
|
||||
const unsigned rows = virtualHeight();
|
||||
for ( unsigned i = 0; i < rows; i++) blurRow(i, blur_amount, smear);
|
||||
}
|
||||
|
||||
// 2D matrix
|
||||
#ifndef WLEDMM_FASTPATH
|
||||
inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline
|
||||
uint_fast16_t groupLen = groupLength();
|
||||
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
||||
@@ -654,22 +680,53 @@ typedef struct Segment {
|
||||
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vHeight;
|
||||
}
|
||||
#else
|
||||
inline uint16_t virtualWidth() const { return(_2dWidth);} // WLEDMM get pre-calculated virtualWidth
|
||||
inline uint16_t virtualHeight() const { return(_2dHeight);} // WLEDMM get pre-calculated virtualHeight
|
||||
|
||||
uint16_t calc_virtualWidth() const {
|
||||
uint_fast16_t groupLen = groupLength();
|
||||
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
||||
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vWidth;
|
||||
}
|
||||
uint16_t calc_virtualHeight() const {
|
||||
uint_fast16_t groupLen = groupLength();
|
||||
uint_fast16_t vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
|
||||
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t nrOfVStrips(void) const;
|
||||
void createjMap(); //WLEDMM jMap
|
||||
void deletejMap(); //WLEDMM jMap
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
|
||||
uint_fast16_t width = virtualWidth(); // segment width in logical pixels
|
||||
uint_fast16_t height = virtualHeight(); // segment height in logical pixels
|
||||
if (width == 0) return 0; // softhack007 avoid div/0
|
||||
if (height == 0) return (x%width); // softhack007 avoid div/0
|
||||
inline uint16_t XY(uint_fast16_t x, uint_fast16_t y) const { // support function to get relative index within segment (for leds[]) // WLEDMM inline for speed
|
||||
uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0
|
||||
uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0
|
||||
return (x%width) + (y%height) * width;
|
||||
}
|
||||
|
||||
//void setPixelColorXY_fast(int x, int y,uint32_t c); // set relative pixel within segment with color - wrapper for _fast
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
// WLEDMM this is a "gateway" function - we either call _fast or fall back to "slow"
|
||||
inline void setPixelColorXY(int x, int y, uint32_t col) {
|
||||
if (!_isSimpleSegment) { // slow path
|
||||
setPixelColorXY_slow(x, y, col);
|
||||
} else { // fast path
|
||||
// some sanity checks
|
||||
if (!_isValid2D) return; // not active
|
||||
if ((unsigned(x) >= _2dWidth) || (unsigned(y) >= _2dHeight)) return; // check if (x,y) are out-of-range - due to 2's complement, this also catches negative values
|
||||
if (!_brightness && !transitional) return; // black-out
|
||||
|
||||
uint32_t scaled_col = (_brightness == 255) ? col : color_fade(col, _brightness); // calculate final color
|
||||
setPixelColorXY_fast(x, y, col, scaled_col, int(_2dWidth), int(_2dHeight)); // call "fast" function
|
||||
}
|
||||
}
|
||||
#else
|
||||
void setPixelColorXY(int x, int y, uint32_t c); // set relative pixel within segment with color
|
||||
#endif
|
||||
inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); }
|
||||
inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); }
|
||||
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||
@@ -679,7 +736,7 @@ typedef struct Segment {
|
||||
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); }
|
||||
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
|
||||
//#endif
|
||||
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y);
|
||||
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y) const;
|
||||
// 2D support functions
|
||||
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
|
||||
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); }
|
||||
@@ -695,12 +752,12 @@ typedef struct Segment {
|
||||
void move(uint8_t dir, uint8_t delta, bool wrap = false);
|
||||
void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
||||
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||
void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
|
||||
inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||
void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft);
|
||||
inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
|
||||
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX);
|
||||
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline
|
||||
void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0);
|
||||
inline void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline
|
||||
void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0);
|
||||
inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0);
|
||||
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline
|
||||
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
|
||||
@@ -745,7 +802,7 @@ typedef struct Segment {
|
||||
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) {}
|
||||
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
||||
#endif
|
||||
uint8_t * getAudioPalette(int pal); //WLEDMM netmindz ar palette
|
||||
uint8_t * getAudioPalette(int pal) const; //WLEDMM netmindz ar palette
|
||||
} segment;
|
||||
//static int segSize = sizeof(Segment);
|
||||
|
||||
@@ -868,64 +925,64 @@ class WS2812FX { // 96 bytes
|
||||
|
||||
bool
|
||||
checkSegmentAlignment(void),
|
||||
hasRGBWBus(void),
|
||||
hasCCTBus(void),
|
||||
hasRGBWBus(void) const,
|
||||
hasCCTBus(void) const,
|
||||
// return true if the strip is being sent pixel updates
|
||||
isUpdating(void),
|
||||
isUpdating(void) const,
|
||||
deserializeMap(uint8_t n=0),
|
||||
useLedsArray = false;
|
||||
|
||||
inline bool isServicing(void) { return _isServicing; }
|
||||
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
||||
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
|
||||
inline bool isServicing(void) const { return _isServicing; }
|
||||
inline bool hasWhiteChannel(void) const {return _hasWhiteChannel;}
|
||||
inline bool isOffRefreshRequired(void) const {return _isOffRefreshRequired;}
|
||||
|
||||
uint8_t
|
||||
paletteFade,
|
||||
paletteBlend,
|
||||
milliampsPerLed,
|
||||
cctBlending,
|
||||
getActiveSegmentsNum(void),
|
||||
getFirstSelectedSegId(void),
|
||||
getLastActiveSegmentId(void),
|
||||
getActiveSegsLightCapabilities(bool selectedOnly = false),
|
||||
getActiveSegmentsNum(void) const,
|
||||
getFirstSelectedSegId(void) __attribute__((pure)),
|
||||
getLastActiveSegmentId(void) const,
|
||||
getActiveSegsLightCapabilities(bool selectedOnly = false) __attribute__((pure)),
|
||||
setPixelSegment(uint8_t n);
|
||||
|
||||
inline uint8_t getBrightness(void) { return _brightness; }
|
||||
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
|
||||
inline uint8_t getSegmentsNum(void) { return _segments.size(); } // returns currently present 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; } // will only return built-in palette count
|
||||
inline uint8_t getTargetFps() { return _targetFps; }
|
||||
inline uint8_t getModeCount() { return _modeCount; }
|
||||
inline uint8_t getBrightness(void) const { return _brightness; }
|
||||
inline uint8_t getMaxSegments(void) const { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
|
||||
inline uint8_t getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments
|
||||
inline uint8_t getCurrSegmentId(void) const { return _segment_index; }
|
||||
inline uint8_t getMainSegmentId(void) const { return _mainSegment; }
|
||||
inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
||||
inline uint8_t getTargetFps() const { return _targetFps; }
|
||||
inline uint8_t getModeCount() const { return _modeCount; }
|
||||
|
||||
uint16_t
|
||||
ablMilliampsMax,
|
||||
currentMilliamps,
|
||||
getLengthPhysical(void),
|
||||
__attribute__((pure)) getLengthTotal(void), // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
||||
getFps();
|
||||
getLengthPhysical(void) const,
|
||||
__attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
||||
getFps() const;
|
||||
|
||||
inline uint16_t getFrameTime(void) { return _frametime; }
|
||||
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
||||
inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H
|
||||
inline uint16_t getTransition(void) { return _transitionDur; }
|
||||
inline uint16_t getFrameTime(void) const { return _frametime; }
|
||||
inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; }
|
||||
inline uint16_t getLength(void) const { return _length; } // 2D matrix may have less pixels than W*H
|
||||
inline uint16_t getTransition(void) const { return _transitionDur; }
|
||||
|
||||
uint32_t
|
||||
now,
|
||||
timebase;
|
||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t); // WLEDMM attribute pure = does not have side-effects
|
||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects
|
||||
|
||||
inline uint32_t getLastShow(void) { return _lastShow; }
|
||||
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; }
|
||||
inline uint32_t getLastShow(void) const { return _lastShow; }
|
||||
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; }
|
||||
|
||||
const char *
|
||||
getModeData(uint8_t id = 0) { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
|
||||
getModeData(uint8_t id = 0) const { return (id && id<_modeCount) ? _modeData[id] : PSTR("Solid"); }
|
||||
|
||||
const char **
|
||||
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
|
||||
|
||||
Segment& getSegment(uint8_t id);
|
||||
Segment& getSegment(uint8_t id) __attribute__((pure));
|
||||
inline Segment& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
|
||||
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
||||
inline Segment* getSegments(void) { return &(_segments[0]); }
|
||||
@@ -992,7 +1049,7 @@ class WS2812FX { // 96 bytes
|
||||
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||
|
||||
uint32_t
|
||||
getPixelColorXY(uint16_t, uint16_t);
|
||||
getPixelColorXY(uint16_t, uint16_t) const;
|
||||
|
||||
// end 2D support
|
||||
|
||||
|
||||
@@ -171,13 +171,31 @@ void WS2812FX::setUpMatrix() {
|
||||
//WLEDMM: no resetSegments here, only do it in set.cpp/handleSettingsSet - as we want t0 maintain the segment settings after setup has changed
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
// softhack007 hack: delete mapping table in case it only contains "identity"
|
||||
if (customMappingTable != nullptr && customMappingTableSize > 0) {
|
||||
bool isIdentity = true;
|
||||
for (size_t i = 0; (i< customMappingSize) && isIdentity; i++) { //WLEDMM use customMappingTableSize
|
||||
if (customMappingTable[i] != (uint16_t)i ) isIdentity = false;
|
||||
}
|
||||
if (isIdentity) {
|
||||
free(customMappingTable); customMappingTable = nullptr;
|
||||
USER_PRINTF("!setupmatrix: customMappingTable is not needed. Dropping %d bytes.\n", customMappingTableSize * sizeof(uint16_t));
|
||||
customMappingTableSize = 0;
|
||||
customMappingSize = 0;
|
||||
loadedLedmap = 0; //WLEDMM
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
isMatrix = false; // no matter what config says
|
||||
#endif
|
||||
}
|
||||
|
||||
// absolute matrix version of setPixelColor(), without error checking
|
||||
void IRAM_ATTR WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
{
|
||||
uint_fast16_t index = y * Segment::maxWidth + x;
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
@@ -200,7 +218,7 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM
|
||||
}
|
||||
|
||||
// returns RGBW values of pixel
|
||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) const {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
||||
#else
|
||||
@@ -217,13 +235,29 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
|
||||
// WLEDMM cache some values so we don't need to re-calc then for each pixel
|
||||
void Segment::startFrame(void) {
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
_isValid2D = isActive() && is2D();
|
||||
_brightness = currentBri(on ? opacity : 0);
|
||||
_isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved
|
||||
// if (reverse_y) _isSimpleSegment = false; // for A/B testing
|
||||
_2dWidth = is2D() ? calc_virtualWidth() : virtualLength();
|
||||
_2dHeight = calc_virtualHeight();
|
||||
#if 0 && defined(WLED_ENABLE_HUB75MATRIX)
|
||||
_firstFill = true; // dirty HACK
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
// WLEDMM end
|
||||
|
||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||
// WLEDMM Segment::XY()is declared inline, see FX.h
|
||||
|
||||
|
||||
// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
|
||||
// * expects scaled color (final brightness) as additional input parameter, plus segment virtualWidth() and virtualHeight()
|
||||
void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
|
||||
void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_t scaled_col, int cols, int rows) //WLEDMM
|
||||
{
|
||||
unsigned i = UINT_MAX;
|
||||
bool sameColor = false;
|
||||
@@ -266,7 +300,11 @@ void IRAM_ATTR Segment::setPixelColorXY_fast(int x, int y, uint32_t col, uint32_
|
||||
|
||||
|
||||
// normal Segment::setPixelColorXY with error checking, and support for grouping / spacing
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally, renamed to "_slow"
|
||||
#else
|
||||
void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
#endif
|
||||
{
|
||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
const int_fast16_t cols = virtualWidth(); // WLEDMM optimization
|
||||
@@ -386,7 +424,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa, bool fast
|
||||
}
|
||||
|
||||
// returns RGBW values of pixel
|
||||
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) {
|
||||
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
|
||||
if (x<0 || y<0 || !isActive()) return 0; // not active or out-of range
|
||||
if (ledsrgb) {
|
||||
int i = XY(x,y);
|
||||
@@ -520,7 +558,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
||||
for (int j = 0; j < dim1; j++) {
|
||||
int x = vertical ? i : j;
|
||||
int y = vertical ? j : i;
|
||||
setPixelColorXY(x, y, out[j]);
|
||||
if (in[j] != out[j]) setPixelColorXY(x, y, out[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,19 +672,26 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col,
|
||||
}
|
||||
|
||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||
void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, bool soft) {
|
||||
if (!isActive() || radius == 0) return; // not active
|
||||
void Segment::fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft) {
|
||||
if (!isActive() || radius <= 0) return; // not active
|
||||
// draw soft bounding circle
|
||||
if (soft) drawCircle(cx, cy, radius, col, soft);
|
||||
// fill it
|
||||
const int cols = virtualWidth();
|
||||
const int rows = virtualHeight();
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
if (x * x + y * y <= radius * radius &&
|
||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
||||
|
||||
const int_fast32_t maxRadius2 = radius * radius - (((radius > 3) && !soft) ? 1:0); // WLEDMM pre-compute r^2; '-1' removes spikes from bigger blobs
|
||||
// WLEDMM pre-compute boundaries
|
||||
const int startx = max(-radius, -int(cx));
|
||||
const int endx = min(radius, cols-1-int(cx));
|
||||
const int starty = max(-radius, -int(cy));
|
||||
const int endy = min(radius, rows-1-int(cy));
|
||||
|
||||
// fill it - WLEDMM optimized
|
||||
for (int y = starty; y <= endy; y++) {
|
||||
for (int x = startx; x <= endx; x++) {
|
||||
if ((x * x + y * y) <= maxRadius2) {
|
||||
setPixelColorXY(cx + x, cy + y, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,7 +718,11 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
uint32_t scaled_col = c;
|
||||
if (simpleSegment) {
|
||||
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
uint8_t _bri_t = _brightness;
|
||||
#else
|
||||
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||
#endif
|
||||
if (!_bri_t && !transitional) return;
|
||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
||||
}
|
||||
@@ -698,7 +747,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
// single pixel (line length == 0)
|
||||
if (dx+dy == 0) {
|
||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x0, y0, c);
|
||||
else setPixelColorXY_slow(x0, y0, c);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -734,7 +783,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
for (;;) {
|
||||
// if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen
|
||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x0, y0, c);
|
||||
else setPixelColorXY_slow(x0, y0, c);
|
||||
if (x0==x1 && y0==y1) break;
|
||||
int e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
@@ -743,27 +792,34 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
}
|
||||
}
|
||||
|
||||
void Segment::drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor) {
|
||||
if (!isActive()) return; // not active
|
||||
// float step = degrees / (2.85f*MAX(radius,1));
|
||||
// for (float rad = 0.0f; rad <= degrees+step/2; rad += step) {
|
||||
// // may want to try float version as well (with or without antialiasing)
|
||||
// int x = roundf(sin_t(rad) * radius);
|
||||
// int y = roundf(cos_t(rad) * radius);
|
||||
// setPixelColorXY(x+x0, y+y0, c);
|
||||
// }
|
||||
float minradius = radius - .5;
|
||||
float maxradius = radius + .5;
|
||||
for (int x=0; x<virtualWidth(); x++) for (int y=0; y<virtualHeight(); y++) {
|
||||
void Segment::drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor) {
|
||||
if (!isActive() || (radius <=0)) return; // not active
|
||||
float minradius = float(radius) - .5;
|
||||
float maxradius = float(radius) + .5;
|
||||
// WLEDMM pre-calculate values to speed up the loop
|
||||
const int minradius2 = roundf(minradius * minradius);
|
||||
const int maxradius2 = roundf(maxradius * maxradius);
|
||||
|
||||
int newX = x - x0;
|
||||
int newY = y - y0;
|
||||
// WLEDMM only loop over surrounding square (50% faster)
|
||||
const int width = virtualWidth();
|
||||
const int height = virtualHeight();
|
||||
const int startx = max(0, int(x0)-radius-1);
|
||||
const int endx = min(width, int(x0)+radius+1);
|
||||
const int starty = max(0, int(y0)-radius-1);
|
||||
const int endy = min(height, int(y0)+radius+1);
|
||||
|
||||
if (newX*newX + newY*newY >= minradius * minradius && newX*newX + newY*newY <= maxradius * maxradius)
|
||||
for (int x=startx; x<endx; x++) for (int y=starty; y<endy; y++) {
|
||||
int newX2 = x - int(x0); newX2 *= newX2; // (distance from centerX) ^2
|
||||
int newY2 = y - int(y0); newY2 *= newY2; // (distance from centerY) ^2
|
||||
int distance2 = newX2 + newY2;
|
||||
|
||||
if ((distance2 >= minradius2) && (distance2 <= maxradius2)) {
|
||||
setPixelColorXY(x, y, color);
|
||||
} else {
|
||||
if (fillColor != 0)
|
||||
if (newX*newX + newY*newY < minradius * minradius)
|
||||
if (distance2 < minradius2)
|
||||
setPixelColorXY(x, y, fillColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,10 +915,11 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel
|
||||
// multiply the intensities by the colour, and saturating-add them to the pixels
|
||||
for (int i = 0; i < 4; i++) {
|
||||
CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1));
|
||||
CRGB oldLed = led;
|
||||
led.r = qadd8(led.r, c.r * wu[i] >> 8);
|
||||
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
||||
led.b = qadd8(led.b, c.b * wu[i] >> 8);
|
||||
setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led);
|
||||
if (led != oldLed) setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led); // WLEDMM don't repaint same color
|
||||
}
|
||||
}
|
||||
#undef WU_WEIGHT
|
||||
|
||||
@@ -132,7 +132,7 @@ void Segment::allocLeds() {
|
||||
ledsrgbSize = ledsrgb?size:0;
|
||||
if (ledsrgb == nullptr) {
|
||||
USER_PRINTLN("allocLeds failed!!");
|
||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
||||
errorFlag = ERR_LOW_BUF; // WLEDMM raise errorflag
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -266,6 +266,7 @@ void Segment::resetIfRequired() {
|
||||
deallocateData();
|
||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||
startFrame(); // WLEDMM update cached propoerties
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +674,11 @@ class JMapC {
|
||||
if (size > 0)
|
||||
return size;
|
||||
else
|
||||
#ifndef WLEDMM_FASTPATH
|
||||
return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); //pixels
|
||||
#else
|
||||
return SEGMENT.calc_virtualWidth() * SEGMENT.calc_virtualHeight(); // calc pixel sizes
|
||||
#endif
|
||||
}
|
||||
void setPixelColor(uint16_t i, uint32_t col) {
|
||||
updatejMapDoc();
|
||||
@@ -765,7 +770,11 @@ class JMapC {
|
||||
jMapFile.close();
|
||||
|
||||
maxWidth++; maxHeight++;
|
||||
#ifndef WLEDMM_FASTPATH
|
||||
scale = min(SEGMENT.virtualWidth() / maxWidth, SEGMENT.virtualHeight() / maxHeight); // WLEDMM use native min/max
|
||||
#else
|
||||
scale = min(SEGMENT.calc_virtualWidth() / maxWidth, SEGMENT.calc_virtualHeight() / maxHeight); // WLEDMM re-calc width/heiht from active settings
|
||||
#endif
|
||||
dataSize += sizeof(jVectorMap);
|
||||
USER_PRINT("dataSize ");
|
||||
USER_PRINT(dataSize);
|
||||
@@ -803,10 +812,13 @@ constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big"
|
||||
constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50
|
||||
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
||||
constexpr int Pinwheel_Steps_XL = 368;
|
||||
constexpr int Pinwheel_Size_XL = 58; // larger than this -> use "XXL"
|
||||
constexpr int Pinwheel_Steps_XXL = 456;
|
||||
constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians
|
||||
constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians
|
||||
constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians
|
||||
constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians
|
||||
constexpr float Int_to_Rad_XXL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XXL; // conversion: from 0...456 to Radians
|
||||
|
||||
constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction)
|
||||
|
||||
@@ -816,8 +828,9 @@ static float getPinwheelAngle(int i, int vW, int vH) {
|
||||
if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small;
|
||||
if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med;
|
||||
if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big;
|
||||
if (maxXY <= Pinwheel_Size_XL) return float(i) * Int_to_Rad_XL;
|
||||
// else
|
||||
return float(i) * Int_to_Rad_XL;
|
||||
return float(i) * Int_to_Rad_XXL;
|
||||
}
|
||||
// Pinwheel helper function: matrix dimensions to number of rays
|
||||
static int getPinwheelLength(int vW, int vH) {
|
||||
@@ -825,8 +838,9 @@ static int getPinwheelLength(int vW, int vH) {
|
||||
if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small;
|
||||
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
||||
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
||||
if (maxXY <= Pinwheel_Size_XL) return Pinwheel_Steps_XL;
|
||||
// else
|
||||
return Pinwheel_Steps_XL;
|
||||
return Pinwheel_Steps_XXL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -873,7 +887,7 @@ uint16_t Segment::virtualLength() const {
|
||||
}
|
||||
|
||||
//WLEDMM used for M12_sBlock
|
||||
void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
|
||||
static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH, uint16_t vStrip) {
|
||||
float i2;
|
||||
if (i<=SEGLEN*0.25) { //top, left to right
|
||||
i2 = i/(SEGLEN*0.25);
|
||||
@@ -898,7 +912,7 @@ void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16_t vH,
|
||||
|
||||
}
|
||||
|
||||
void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally
|
||||
{
|
||||
if (!isActive()) return; // not active
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@@ -1057,7 +1071,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
||||
// set pixel
|
||||
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
||||
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
||||
else setPixelColorXY(x, y, col);
|
||||
else setPixelColorXY_slow(x, y, col);
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
@@ -1162,7 +1176,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Segment::getPixelColor(int i)
|
||||
uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const
|
||||
{
|
||||
if (!isActive()) return 0; // not active
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@@ -1336,8 +1350,20 @@ void Segment::refreshLightCapabilities() {
|
||||
/*
|
||||
* Fills segment with color - WLEDMM using faster sPC if possible
|
||||
*/
|
||||
void Segment::fill(uint32_t c) {
|
||||
void __attribute__((hot)) Segment::fill(uint32_t c) {
|
||||
if (!isActive()) return; // not active
|
||||
|
||||
#if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH)
|
||||
// DIRTY HACK - this ignores the first fill(black) in each frame, knowing that HUB75 has already blanked out the display.
|
||||
if (_firstFill) {
|
||||
_firstFill = false;
|
||||
if (c == BLACK) {
|
||||
if (ledsrgb && ledsrgbSize > 0) memset(ledsrgb, 0, ledsrgbSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
|
||||
@@ -1353,7 +1379,7 @@ void Segment::fill(uint32_t c) {
|
||||
// fill 2D segment
|
||||
for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||
if (simpleSegment) setPixelColorXY_fast(x, y, c, scaled_col, cols, rows);
|
||||
else setPixelColorXY(x, y, c);
|
||||
else setPixelColorXY_slow(x, y, c);
|
||||
}
|
||||
} else { // fill 1D strip
|
||||
for (int x = 0; x < cols; x++) setPixelColor(x, c);
|
||||
@@ -1408,7 +1434,7 @@ void Segment::fade_out(uint8_t rate) {
|
||||
int g2 = G(color2);
|
||||
int b2 = B(color2);
|
||||
|
||||
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
|
||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||
uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
||||
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
|
||||
int w1 = W(color);
|
||||
@@ -1426,15 +1452,17 @@ void Segment::fade_out(uint8_t rate) {
|
||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||
uint32_t colorNew = RGBW32(r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); // WLEDMM
|
||||
|
||||
//if ((wdelta == 0) && (rdelta == 0) && (gdelta == 0) && (bdelta == 0)) continue; // WLEDMM delta = zero => no change // causes problem with text overlay
|
||||
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
else setPixelColor((uint16_t)x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
if (colorNew != color) { // WLEDMM speedup - do not repaint the same color
|
||||
if (is2D()) setPixelColorXY(x, y, colorNew);
|
||||
else setPixelColor(x, colorNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fades all pixels to black using nscale8()
|
||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
||||
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||
@@ -1442,8 +1470,11 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
|
||||
// WLEDMM minor optimization
|
||||
if(is2D()) {
|
||||
for (uint_fast16_t y = 0; y < rows; y++) for (uint_fast16_t x = 0; x < cols; x++) {
|
||||
setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown));
|
||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||
uint32_t cc = getPixelColorXY(x,y); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion
|
||||
uint32_t cc2 = color_fade(cc, scaledown); // fade
|
||||
//if (cc2 != cc) // WLEDMM only re-paint if faded color is different - disabled - causes problem with text overlay
|
||||
setPixelColorXY((uint16_t)x, (uint16_t)y, cc2);
|
||||
}
|
||||
} else {
|
||||
for (uint_fast16_t x = 0; x < cols; x++) {
|
||||
@@ -1455,7 +1486,7 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||
/*
|
||||
* blurs segment content, source: FastLED colorutils.cpp
|
||||
*/
|
||||
void Segment::blur(uint8_t blur_amount, bool smear) {
|
||||
void __attribute__((hot)) Segment::blur(uint8_t blur_amount, bool smear) {
|
||||
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (is2D()) {
|
||||
@@ -1516,7 +1547,7 @@ uint32_t Segment::color_wheel(uint8_t pos) {
|
||||
/*
|
||||
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
||||
*/
|
||||
uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int types, use native min/max
|
||||
uint8_t Segment::get_random_wheel_index(uint8_t pos) const { // WLEDMM use fast int types, use native min/max
|
||||
uint_fast8_t r = 0, x = 0, y = 0, d = 0;
|
||||
|
||||
while(d < 42) {
|
||||
@@ -1537,7 +1568,7 @@ uint8_t Segment::get_random_wheel_index(uint8_t pos) { // WLEDMM use fast int ty
|
||||
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
|
||||
* @returns Single color from palette
|
||||
*/
|
||||
uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
|
||||
uint32_t __attribute__((hot)) Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri) // WLEDMM use fast int types
|
||||
{
|
||||
// default palette or no RGB support on segment
|
||||
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
||||
@@ -1557,7 +1588,7 @@ uint32_t Segment::color_from_palette(uint_fast16_t i, bool mapping, bool wrap, u
|
||||
}
|
||||
|
||||
//WLEDMM netmindz ar palette
|
||||
uint8_t * Segment::getAudioPalette(int pal) {
|
||||
uint8_t * Segment::getAudioPalette(int pal) const {
|
||||
// https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339
|
||||
|
||||
um_data_t *um_data;
|
||||
@@ -1834,6 +1865,7 @@ void WS2812FX::service() {
|
||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
||||
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
||||
|
||||
seg.startFrame(); // WLEDMM
|
||||
// effect blending (execute previous effect)
|
||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||
@@ -1865,7 +1897,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
||||
busses.setPixelColor(i, col);
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint_fast16_t i) // WLEDMM fast int types
|
||||
uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types
|
||||
{
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
if (i >= _length) return 0;
|
||||
@@ -2003,7 +2035,7 @@ void WS2812FX::show(void) {
|
||||
* Returns a true value if any of the strips are still being updated.
|
||||
* On some hardware (ESP32), strip updates are done asynchronously.
|
||||
*/
|
||||
bool WS2812FX::isUpdating() {
|
||||
bool WS2812FX::isUpdating() const {
|
||||
return !busses.canAllShow();
|
||||
}
|
||||
|
||||
@@ -2011,7 +2043,7 @@ bool WS2812FX::isUpdating() {
|
||||
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
|
||||
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accuracy varies
|
||||
*/
|
||||
uint16_t WS2812FX::getFps() {
|
||||
uint16_t WS2812FX::getFps() const {
|
||||
if (millis() - _lastShow > 2000) return 0;
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
|
||||
@@ -2102,14 +2134,14 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getLastActiveSegmentId(void) {
|
||||
uint8_t WS2812FX::getLastActiveSegmentId(void) const {
|
||||
for (size_t i = _segments.size() -1; i > 0; i--) {
|
||||
if (_segments[i].isActive()) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
||||
uint8_t WS2812FX::getActiveSegmentsNum(void) const {
|
||||
uint8_t c = 0;
|
||||
for (size_t i = 0; i < _segments.size(); i++) {
|
||||
if (_segments[i].isActive()) c++;
|
||||
@@ -2117,13 +2149,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
||||
return c;
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::getLengthTotal(void) { // WLEDMM fast int types
|
||||
uint16_t WS2812FX::getLengthTotal(void) const { // WLEDMM fast int types
|
||||
uint_fast16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
||||
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
|
||||
uint16_t WS2812FX::getLengthPhysical(void) const { // WLEDMM fast int types
|
||||
uint_fast16_t len = 0;
|
||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||
Bus *bus = busses.getBus(b);
|
||||
@@ -2136,7 +2168,7 @@ uint16_t WS2812FX::getLengthPhysical(void) { // WLEDMM fast int types
|
||||
//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)
|
||||
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
||||
bool WS2812FX::hasRGBWBus(void) {
|
||||
bool WS2812FX::hasRGBWBus(void) const {
|
||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||
Bus *bus = busses.getBus(b);
|
||||
if (bus == nullptr || bus->getLength()==0) break;
|
||||
@@ -2145,7 +2177,7 @@ bool WS2812FX::hasRGBWBus(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WS2812FX::hasCCTBus(void) {
|
||||
bool WS2812FX::hasCCTBus(void) const {
|
||||
if (cctFromRgb && !correctWB) return false;
|
||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||
Bus *bus = busses.getBus(b);
|
||||
|
||||
@@ -9,6 +9,36 @@
|
||||
#include "bus_wrapper.h"
|
||||
#include "bus_manager.h"
|
||||
|
||||
// WLEDMM functions to get/set bits in an array - based on functions created by Brandon for GOL
|
||||
// toDo : make this a class that's completely defined in a header file
|
||||
bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit value
|
||||
size_t byteIndex = position / 8;
|
||||
unsigned bitIndex = position % 8;
|
||||
uint8_t byteValue = byteArray[byteIndex];
|
||||
return (byteValue >> bitIndex) & 1;
|
||||
}
|
||||
|
||||
void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr
|
||||
//if (byteArray == nullptr) return;
|
||||
size_t byteIndex = position / 8;
|
||||
unsigned bitIndex = position % 8;
|
||||
if (value)
|
||||
byteArray[byteIndex] |= (1 << bitIndex);
|
||||
else
|
||||
byteArray[byteIndex] &= ~(1 << bitIndex);
|
||||
}
|
||||
|
||||
size_t getBitArrayBytes(size_t num_bits) { // number of bytes needed for an array with num_bits bits
|
||||
return (num_bits + 7) / 8;
|
||||
}
|
||||
|
||||
void setBitArray(uint8_t* byteArray, size_t numBits, bool value) { // set all bits to same value
|
||||
if (byteArray == nullptr) return;
|
||||
size_t len = getBitArrayBytes(numBits);
|
||||
if (value) memset(byteArray, 0xFF, len);
|
||||
else memset(byteArray, 0x00, len);
|
||||
}
|
||||
|
||||
//WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope
|
||||
#if 0
|
||||
//colors.cpp
|
||||
@@ -49,13 +79,6 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte
|
||||
#include "wled.h"
|
||||
#endif
|
||||
|
||||
//color mangling macros
|
||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||
#define R(c) (byte((c) >> 16))
|
||||
#define G(c) (byte((c) >> 8))
|
||||
#define B(c) (byte(c))
|
||||
#define W(c) (byte((c) >> 24))
|
||||
|
||||
|
||||
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
||||
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
||||
@@ -86,7 +109,7 @@ uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaul
|
||||
}
|
||||
|
||||
|
||||
uint32_t Bus::autoWhiteCalc(uint32_t c) {
|
||||
uint32_t Bus::autoWhiteCalc(uint32_t c) const {
|
||||
uint8_t aWM = _autoWhiteMode;
|
||||
if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM;
|
||||
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
||||
@@ -139,7 +162,7 @@ void BusDigital::show() {
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
}
|
||||
|
||||
bool BusDigital::canShow() {
|
||||
bool BusDigital::canShow() const {
|
||||
return PolyBus::canShow(_busPtr, _iType);
|
||||
}
|
||||
|
||||
@@ -182,7 +205,7 @@ void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) {
|
||||
uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) const {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
@@ -200,7 +223,7 @@ uint32_t IRAM_ATTR_YN BusDigital::getPixelColor(uint16_t pix) {
|
||||
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
}
|
||||
|
||||
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
||||
uint8_t BusDigital::getPins(uint8_t* pinArray) const {
|
||||
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
||||
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||
return numPins;
|
||||
@@ -317,7 +340,7 @@ void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
}
|
||||
|
||||
//does no index check
|
||||
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
||||
uint32_t BusPwm::getPixelColor(uint16_t pix) const {
|
||||
if (!_valid) return 0;
|
||||
#if 1
|
||||
// WLEDMM stick with the old code - we don't have cctICused
|
||||
@@ -356,7 +379,7 @@ void BusPwm::show() {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BusPwm::getPins(uint8_t* pinArray) {
|
||||
uint8_t BusPwm::getPins(uint8_t* pinArray) const {
|
||||
if (!_valid) return 0;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
@@ -408,7 +431,7 @@ void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
_data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
|
||||
uint32_t BusOnOff::getPixelColor(uint16_t pix) const {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data, _data, _data, _data);
|
||||
}
|
||||
@@ -418,7 +441,7 @@ void BusOnOff::show() {
|
||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||
}
|
||||
|
||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
|
||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) const {
|
||||
if (!_valid) return 0;
|
||||
pinArray[0] = _pin;
|
||||
return 1;
|
||||
@@ -467,7 +490,7 @@ void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (_rgbw) _data[offset+3] = W(c);
|
||||
}
|
||||
|
||||
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
|
||||
uint32_t BusNetwork::getPixelColor(uint16_t pix) const {
|
||||
if (!_valid || pix >= _len) return 0;
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
||||
@@ -480,7 +503,7 @@ void BusNetwork::show() {
|
||||
_broadcastLock = false;
|
||||
}
|
||||
|
||||
uint8_t BusNetwork::getPins(uint8_t* pinArray) {
|
||||
uint8_t BusNetwork::getPins(uint8_t* pinArray) const {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
pinArray[i] = _client[i];
|
||||
}
|
||||
@@ -501,9 +524,9 @@ void BusNetwork::cleanup() {
|
||||
|
||||
BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
|
||||
_valid = false;
|
||||
mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory
|
||||
|
||||
|
||||
fourScanPanel = nullptr;
|
||||
|
||||
switch(bc.type) {
|
||||
@@ -546,7 +569,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
||||
|
||||
USER_PRINTLN("MatrixPanel_I2S_DMA - Matrix Portal S3 config");
|
||||
|
||||
mxconfig.double_buff = true; // <------------- Turn on double buffer
|
||||
//mxconfig.double_buff = true; // <------------- Turn on double buffer
|
||||
|
||||
mxconfig.gpio.r1 = 42;
|
||||
mxconfig.gpio.g1 = 41;
|
||||
@@ -594,6 +617,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
||||
mxconfig.gpio.d = 21;
|
||||
mxconfig.gpio.e = 12;
|
||||
|
||||
// mxconfig.double_buff = true; // <------------- Turn on double buffer
|
||||
// mxconfig.driver = HUB75_I2S_CFG::ICN2038S; // experimental - use specific shift register driver
|
||||
//mxconfig.latch_blanking = 3;
|
||||
// mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M; // experimental - 5MHZ should be enugh, but colours looks slightly better at 10MHz
|
||||
//mxconfig.min_refresh_rate = 90;
|
||||
//mxconfig.min_refresh_rate = 120;
|
||||
|
||||
#else
|
||||
USER_PRINTLN("MatrixPanel_I2S_DMA - Default pins");
|
||||
/*
|
||||
@@ -655,14 +685,35 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
||||
USER_PRINTLN("MatrixPanel_I2S_DMA created");
|
||||
// let's adjust default brightness
|
||||
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
||||
_bri = 25;
|
||||
|
||||
delay(24); // experimental
|
||||
// Allocate memory and start DMA display
|
||||
if( not display->begin() ) {
|
||||
USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle
|
||||
_valid = true;
|
||||
display->clearScreen(); // initially clear the screen buffer
|
||||
|
||||
if (_ledBuffer) free(_ledBuffer); // should not happen
|
||||
if (_ledsDirty) free(_ledsDirty); // should not happen
|
||||
_ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits
|
||||
|
||||
if (_ledsDirty == nullptr) {
|
||||
display->stopDMAoutput();
|
||||
delete display; display = nullptr;
|
||||
_valid = false;
|
||||
USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!"));
|
||||
return; // fail is we cannot get memory for the buffer
|
||||
}
|
||||
setBitArray(_ledsDirty, _len, false); // reset dirty bits
|
||||
|
||||
if (mxconfig.double_buff == false) {
|
||||
_ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
||||
}
|
||||
}
|
||||
|
||||
switch(bc.type) {
|
||||
@@ -686,28 +737,125 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
||||
break;
|
||||
}
|
||||
|
||||
if (_valid) {
|
||||
_panelWidth = fourScanPanel ? fourScanPanel->width() : display->width(); // cache width - it will never change
|
||||
}
|
||||
|
||||
USER_PRINTLN("MatrixPanel_I2S_DMA started");
|
||||
USER_PRINT(F("MatrixPanel_I2S_DMA "));
|
||||
USER_PRINTF("%sstarted, width=%u, %u pixels.\n", _valid? "":"not ", _panelWidth, _len);
|
||||
|
||||
if (mxconfig.double_buff == true) USER_PRINTLN(F("MatrixPanel_I2S_DMA driver native double-buffering enabled."));
|
||||
if (_ledBuffer != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS buffer enabled."));
|
||||
if (_ledsDirty != nullptr) USER_PRINTLN(F("MatrixPanel_I2S_DMA LEDS dirty bit optimization enabled."));
|
||||
if ((_ledBuffer != nullptr) || (_ledsDirty != nullptr)) {
|
||||
USER_PRINT(F("MatrixPanel_I2S_DMA LEDS buffer uses "));
|
||||
USER_PRINT((_ledBuffer? _len*sizeof(CRGB) :0) + (_ledsDirty? getBitArrayBytes(_len) :0));
|
||||
USER_PRINTLN(F(" bytes."));
|
||||
}
|
||||
}
|
||||
|
||||
void BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
r = R(c);
|
||||
g = G(c);
|
||||
b = B(c);
|
||||
if(fourScanPanel != nullptr) {
|
||||
x = pix % fourScanPanel->width();
|
||||
y = floor(pix / fourScanPanel->width());
|
||||
fourScanPanel->drawPixelRGB888(x, y, r, g, b);
|
||||
void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (!_valid || pix >= _len) return;
|
||||
// if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
|
||||
if (_ledBuffer) {
|
||||
CRGB fastled_col = CRGB(c);
|
||||
if (_ledBuffer[pix] != fastled_col) {
|
||||
_ledBuffer[pix] = fastled_col;
|
||||
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
|
||||
}
|
||||
}
|
||||
else {
|
||||
x = pix % display->width();
|
||||
y = floor(pix / display->width());
|
||||
display->drawPixelRGB888(x, y, r, g, b);
|
||||
if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
|
||||
setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK"
|
||||
|
||||
#ifndef NO_CIE1931
|
||||
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||
#endif
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
|
||||
if(fourScanPanel != nullptr) {
|
||||
int width = _panelWidth;
|
||||
int x = pix % width;
|
||||
int y = pix / width;
|
||||
fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||
} else {
|
||||
int width = _panelWidth;
|
||||
int x = pix % width;
|
||||
int y = pix / width;
|
||||
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const {
|
||||
if (!_valid || pix >= _len) return BLACK;
|
||||
if (_ledBuffer)
|
||||
return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours
|
||||
else
|
||||
return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not
|
||||
}
|
||||
|
||||
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
||||
this->display->setBrightness(b);
|
||||
_bri = b;
|
||||
if (_bri > 238) _bri=238;
|
||||
display->setBrightness(_bri);
|
||||
}
|
||||
|
||||
void __attribute__((hot)) BusHub75Matrix::show(void) {
|
||||
if (!_valid) return;
|
||||
display->setBrightness(_bri);
|
||||
|
||||
if (_ledBuffer) {
|
||||
// write out buffered LEDs
|
||||
bool isFourScan = (fourScanPanel != nullptr);
|
||||
//if (isFourScan) fourScanPanel->setRotation(0);
|
||||
unsigned height = isFourScan ? fourScanPanel->height() : display->height();
|
||||
unsigned width = _panelWidth;
|
||||
|
||||
//while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
||||
|
||||
size_t pix = 0; // running pixel index
|
||||
for (int y=0; y<height; y++) for (int x=0; x<width; x++) {
|
||||
if (getBitFromArray(_ledsDirty, pix) == true) { // only repaint the "dirty" pixels
|
||||
uint32_t c = uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; // get RGB color, removing FastLED "alpha" component
|
||||
#ifndef NO_CIE1931
|
||||
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||
#endif
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
if (isFourScan) fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||
else display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||
}
|
||||
pix ++;
|
||||
}
|
||||
setBitArray(_ledsDirty, _len, false); // buffer shown - reset all dirty bits
|
||||
}
|
||||
|
||||
if(mxconfig.double_buff) {
|
||||
display->flipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels)
|
||||
// while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
||||
display->clearScreen(); // Now clear the back-buffer
|
||||
setBitArray(_ledsDirty, _len, false); // dislay buffer is blank - reset all dirty bits
|
||||
}
|
||||
}
|
||||
|
||||
void BusHub75Matrix::cleanup() {
|
||||
if (display && _valid) display->stopDMAoutput(); // terminate DMA driver (display goes black)
|
||||
_valid = false;
|
||||
_panelWidth = 0;
|
||||
deallocatePins();
|
||||
USER_PRINTLN("HUB75 output ended.");
|
||||
|
||||
//if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior
|
||||
delete display;
|
||||
display = nullptr;
|
||||
fourScanPanel = nullptr;
|
||||
if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr;
|
||||
if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr;
|
||||
}
|
||||
|
||||
void BusHub75Matrix::deallocatePins() {
|
||||
@@ -808,7 +956,7 @@ void BusManager::setStatusPixel(uint32_t c) {
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
|
||||
void IRAM_ATTR __attribute__((hot)) BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
|
||||
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||
// WLEDMM same bus as last time - no need to search again
|
||||
lastBus->setPixelColor(pix - laststart, c);
|
||||
@@ -836,7 +984,7 @@ void BusManager::setBrightness(uint8_t b, bool immediate) {
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
||||
void __attribute__((cold)) BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
||||
if (cct > 255) cct = 255;
|
||||
if (cct >= 0) {
|
||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
||||
@@ -845,7 +993,7 @@ void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
||||
Bus::setCCT(cct);
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR
|
||||
uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR
|
||||
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||
// WLEDMM same bus as last time - no need to search again
|
||||
return lastBus->getPixelColor(pix - laststart);
|
||||
@@ -866,20 +1014,20 @@ uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BusManager::canAllShow() {
|
||||
bool BusManager::canAllShow() const {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
if (!busses[i]->canShow()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bus* BusManager::getBus(uint8_t busNr) {
|
||||
Bus* BusManager::getBus(uint8_t busNr) const {
|
||||
if (busNr >= numBusses) return nullptr;
|
||||
return busses[busNr];
|
||||
}
|
||||
|
||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
uint16_t BusManager::getTotalLength() {
|
||||
uint16_t BusManager::getTotalLength() const {
|
||||
uint_fast16_t len = 0;
|
||||
for (uint_fast8_t i=0; i<numBusses; i++) len += busses[i]->getLength(); // WLEDMM use fast native types
|
||||
return len;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
|
||||
//extern volatile bool previousBufferFree; // experimental
|
||||
#endif
|
||||
/*
|
||||
* Class for addressing various light types
|
||||
@@ -11,6 +12,27 @@
|
||||
|
||||
#include "const.h"
|
||||
|
||||
#if !defined(FASTLED_VERSION) // only pull in FastLED if we don't have it yet
|
||||
#define FASTLED_INTERNAL
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
|
||||
//color mangling macros
|
||||
#if !defined(RGBW32)
|
||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||
#define R(c) (byte((c) >> 16))
|
||||
#define G(c) (byte((c) >> 8))
|
||||
#define B(c) (byte(c))
|
||||
#define W(c) (byte((c) >> 24))
|
||||
#endif
|
||||
|
||||
// WLEDMM bitarray utilities
|
||||
void setBitInArray(uint8_t* byteArray, size_t position, bool value); // set bit
|
||||
bool getBitFromArray(const uint8_t* byteArray, size_t position) __attribute__((pure)); // get bit value
|
||||
size_t getBitArrayBytes(size_t num_bits) __attribute__((const)); // number of bytes needed for an array with num_bits bits
|
||||
void setBitArray(uint8_t* byteArray, size_t numBits, bool value); // set all bits to same value
|
||||
|
||||
|
||||
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
||||
@@ -112,35 +134,35 @@ class Bus {
|
||||
virtual bool canShow() { return true; }
|
||||
virtual void setStatusPixel(uint32_t c) {}
|
||||
virtual void setPixelColor(uint16_t pix, uint32_t c) = 0;
|
||||
virtual uint32_t getPixelColor(uint16_t pix) { return 0; }
|
||||
virtual uint32_t getPixelColor(uint16_t pix) const { return 0; }
|
||||
virtual void setBrightness(uint8_t b, bool immediate=false) { _bri = b; };
|
||||
virtual void cleanup() = 0;
|
||||
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
|
||||
virtual uint16_t getLength() { return _len; }
|
||||
virtual uint8_t getPins(uint8_t* pinArray) const { return 0; }
|
||||
virtual uint16_t getLength() const { return _len; }
|
||||
virtual void setColorOrder() {}
|
||||
virtual uint8_t getColorOrder() { return COL_ORDER_RGB; }
|
||||
virtual uint8_t getColorOrder() const { return COL_ORDER_RGB; }
|
||||
virtual uint8_t skippedLeds() { return 0; }
|
||||
virtual uint16_t getFrequency() { return 0U; }
|
||||
inline uint16_t getStart() { return _start; }
|
||||
virtual uint16_t getFrequency() const { return 0U; }
|
||||
inline uint16_t getStart() const { return _start; }
|
||||
inline void setStart(uint16_t start) { _start = start; }
|
||||
inline uint8_t getType() { return _type; }
|
||||
inline bool isOk() { return _valid; }
|
||||
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
||||
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
||||
virtual uint16_t getMaxPixels() { return MAX_LEDS_PER_BUS; };
|
||||
inline uint8_t getType() const { return _type; }
|
||||
inline bool isOk() const { return _valid; }
|
||||
inline bool isOffRefreshRequired() const { return _needsRefresh; }
|
||||
bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; }
|
||||
virtual uint16_t getMaxPixels() const { return MAX_LEDS_PER_BUS; };
|
||||
|
||||
virtual bool hasRGB() {
|
||||
virtual bool hasRGB() const {
|
||||
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool hasWhite() { return Bus::hasWhite(_type); }
|
||||
virtual bool hasWhite() const { return Bus::hasWhite(_type); }
|
||||
static bool hasWhite(uint8_t type) {
|
||||
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814 || type == TYPE_UCS8904) return true; // digital types with white channel
|
||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
||||
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
||||
return false;
|
||||
}
|
||||
virtual bool hasCCT() {
|
||||
virtual bool hasCCT() const {
|
||||
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
||||
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
||||
return false;
|
||||
@@ -157,7 +179,7 @@ class Bus {
|
||||
#endif
|
||||
}
|
||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
||||
inline uint8_t getAutoWhiteMode() const { return _autoWhiteMode; }
|
||||
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||
|
||||
@@ -175,7 +197,7 @@ class Bus {
|
||||
static int16_t _cct;
|
||||
static uint8_t _cctBlend;
|
||||
|
||||
uint32_t autoWhiteCalc(uint32_t c);
|
||||
uint32_t autoWhiteCalc(uint32_t c) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -185,7 +207,7 @@ class BusDigital : public Bus {
|
||||
|
||||
inline void show();
|
||||
|
||||
bool canShow();
|
||||
bool canShow() const;
|
||||
|
||||
void setBrightness(uint8_t b, bool immediate);
|
||||
|
||||
@@ -193,25 +215,25 @@ class BusDigital : public Bus {
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
uint32_t getPixelColor(uint16_t pix) const;
|
||||
|
||||
uint8_t getColorOrder() {
|
||||
uint8_t getColorOrder() const {
|
||||
return _colorOrder;
|
||||
}
|
||||
|
||||
uint16_t getLength() {
|
||||
uint16_t getLength() const {
|
||||
return _len - _skip;
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
uint8_t getPins(uint8_t* pinArray) const;
|
||||
|
||||
void setColorOrder(uint8_t colorOrder);
|
||||
|
||||
uint8_t skippedLeds() {
|
||||
uint8_t skippedLeds() const {
|
||||
return _skip;
|
||||
}
|
||||
|
||||
uint16_t getFrequency() { return _frequencykHz; }
|
||||
uint16_t getFrequency() const { return _frequencykHz; }
|
||||
|
||||
void reinit();
|
||||
|
||||
@@ -239,13 +261,13 @@ class BusPwm : public Bus {
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
//does no index check
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
uint32_t getPixelColor(uint16_t pix) const;
|
||||
|
||||
void show();
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
uint8_t getPins(uint8_t* pinArray) const;
|
||||
|
||||
uint16_t getFrequency() { return _frequency; }
|
||||
uint16_t getFrequency() const { return _frequency; }
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
@@ -273,11 +295,11 @@ class BusOnOff : public Bus {
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
uint32_t getPixelColor(uint16_t pix) const;
|
||||
|
||||
void show();
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
uint8_t getPins(uint8_t* pinArray) const;
|
||||
|
||||
void cleanup() {
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
@@ -297,24 +319,24 @@ class BusNetwork : public Bus {
|
||||
public:
|
||||
BusNetwork(BusConfig &bc);
|
||||
|
||||
uint16_t getMaxPixels() override { return 4096; };
|
||||
bool hasRGB() { return true; }
|
||||
bool hasWhite() { return _rgbw; }
|
||||
uint16_t getMaxPixels() const override { return 4096; };
|
||||
bool hasRGB() const { return true; }
|
||||
bool hasWhite() const { return _rgbw; }
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t __attribute__((pure)) getPixelColor(uint16_t pix); // WLEDMM attribute added
|
||||
uint32_t __attribute__((pure)) getPixelColor(uint16_t pix) const; // WLEDMM attribute added
|
||||
|
||||
void show();
|
||||
|
||||
bool canShow() {
|
||||
bool canShow() const {
|
||||
// this should be a return value from UDP routine if it is still sending data out
|
||||
return !_broadcastLock;
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
uint8_t getPins(uint8_t* pinArray) const;
|
||||
|
||||
uint16_t getLength() {
|
||||
uint16_t getLength() const {
|
||||
return _len;
|
||||
}
|
||||
|
||||
@@ -338,36 +360,26 @@ class BusHub75Matrix : public Bus {
|
||||
public:
|
||||
BusHub75Matrix(BusConfig &bc);
|
||||
|
||||
uint16_t getMaxPixels() override { return 4096; };
|
||||
uint16_t getMaxPixels() const override { return 4096; };
|
||||
|
||||
bool hasRGB() { return true; }
|
||||
bool hasWhite() { return false; }
|
||||
bool hasRGB() const override { return true; }
|
||||
bool hasWhite() const override { return false; }
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
void setPixelColor(uint16_t pix, uint32_t c) override;
|
||||
uint32_t getPixelColor(uint16_t pix) const override;
|
||||
|
||||
void show() {
|
||||
if(mxconfig.double_buff) {
|
||||
display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels)
|
||||
display->clearScreen(); // Now clear the back-buffer
|
||||
}
|
||||
}
|
||||
void show(void) override;
|
||||
|
||||
void setBrightness(uint8_t b, bool immediate);
|
||||
void setBrightness(uint8_t b, bool immediate) override;
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
uint8_t getPins(uint8_t* pinArray) const override {
|
||||
pinArray[0] = mxconfig.chain_length;
|
||||
return 1;
|
||||
} // Fake value due to keep finaliseInit happy
|
||||
|
||||
void deallocatePins();
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
fourScanPanel = nullptr;
|
||||
// delete fourScanPanel;
|
||||
delete display;
|
||||
_valid = false;
|
||||
}
|
||||
void cleanup(void) override;
|
||||
|
||||
~BusHub75Matrix() {
|
||||
cleanup();
|
||||
@@ -377,8 +389,9 @@ class BusHub75Matrix : public Bus {
|
||||
MatrixPanel_I2S_DMA *display = nullptr;
|
||||
VirtualMatrixPanel *fourScanPanel = nullptr;
|
||||
HUB75_I2S_CFG mxconfig;
|
||||
uint8_t r, g, b, x, y;
|
||||
|
||||
unsigned _panelWidth = 0;
|
||||
CRGB *_ledBuffer = nullptr;
|
||||
byte *_ledsDirty = nullptr;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -387,7 +400,7 @@ class BusManager {
|
||||
BusManager() {};
|
||||
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
static uint32_t memUsage(BusConfig &bc);
|
||||
static uint32_t memUsage(BusConfig &bc) __attribute__((pure));
|
||||
|
||||
int add(BusConfig &bc);
|
||||
|
||||
@@ -406,12 +419,12 @@ class BusManager {
|
||||
|
||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added
|
||||
|
||||
bool canAllShow();
|
||||
bool canAllShow() const;
|
||||
|
||||
Bus* getBus(uint8_t busNr);
|
||||
Bus* getBus(uint8_t busNr) const;
|
||||
|
||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
uint16_t getTotalLength();
|
||||
uint16_t getTotalLength() const;
|
||||
|
||||
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
||||
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||
@@ -421,7 +434,7 @@ class BusManager {
|
||||
return colorOrderMap;
|
||||
}
|
||||
|
||||
inline uint8_t getNumBusses() {
|
||||
inline uint8_t getNumBusses() const {
|
||||
return numBusses;
|
||||
}
|
||||
|
||||
@@ -434,7 +447,7 @@ class BusManager {
|
||||
unsigned laststart = 0;
|
||||
unsigned lastend = 0;
|
||||
|
||||
inline uint8_t getNumVirtualBusses() {
|
||||
inline uint8_t getNumVirtualBusses() const {
|
||||
int j = 0;
|
||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||
return j;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/*
|
||||
* color blend function
|
||||
*/
|
||||
IRAM_ATTR_YN uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) {
|
||||
IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) {
|
||||
if(blend == 0) return color1;
|
||||
if (color1 == color2) return color1; // WLEDMM shortcut
|
||||
const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
||||
@@ -71,7 +71,7 @@ IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM
|
||||
* if using "video" method the resulting color will never become black unless it is already black
|
||||
*/
|
||||
|
||||
IRAM_ATTR_YN uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
||||
IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
||||
{
|
||||
if (amount == 0) return 0; // WLEDMM shortcut
|
||||
|
||||
@@ -297,7 +297,7 @@ static float maxf (float v, float w) // WLEDMM better use standard library fmax
|
||||
|
||||
// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance)
|
||||
// called from bus manager when color correction is enabled!
|
||||
uint32_t IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN
|
||||
uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN
|
||||
{
|
||||
//remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor()
|
||||
static byte correctionRGB[4] = {0,0,0,0};
|
||||
@@ -406,13 +406,19 @@ static void calcInvGammaTable(float gamma)
|
||||
gammaTinv[i] = (int)(powf((float)i / 255.0f, gammaInv) * 255.0f + 0.5f);
|
||||
}
|
||||
}
|
||||
uint8_t unGamma8(uint8_t value) {
|
||||
uint8_t __attribute__((hot)) unGamma8(uint8_t value) {
|
||||
//if (!gammaCorrectCol || (value == 0) || (value == 255)) return value;
|
||||
if ((value == 0) || (value == 255)) return value;
|
||||
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value;
|
||||
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
||||
return gammaTinv[value];
|
||||
}
|
||||
|
||||
uint32_t __attribute__((hot)) unGamma24(uint32_t c) {
|
||||
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return c;
|
||||
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
||||
return RGBW32(gammaTinv[R(c)], gammaTinv[G(c)], gammaTinv[B(c)], W(c));
|
||||
}
|
||||
// wleDMM end
|
||||
|
||||
uint8_t gamma8_cal(uint8_t b, float gamma)
|
||||
@@ -432,13 +438,13 @@ void calcGammaTable(float gamma)
|
||||
}
|
||||
|
||||
// used for individual channel or brightness gamma correction
|
||||
IRAM_ATTR_YN uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN
|
||||
IRAM_ATTR_YN __attribute__((hot)) uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN
|
||||
{
|
||||
return gammaT[b];
|
||||
}
|
||||
|
||||
// used for color gamma correction
|
||||
uint32_t gamma32(uint32_t color)
|
||||
uint32_t __attribute__((hot)) gamma32(uint32_t color)
|
||||
{
|
||||
if (!gammaCorrectCol) return color;
|
||||
uint8_t w = W(color);
|
||||
|
||||
@@ -352,6 +352,7 @@
|
||||
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
|
||||
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
||||
#define ERR_LOW_AJAX_MEM 36 // WLEDMM: low memory (oappend)
|
||||
#define ERR_LOW_BUF 37 // WLEDMM: low memory (LED buffer from allocLEDs)
|
||||
|
||||
// Timer mode types
|
||||
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
||||
@@ -480,7 +481,9 @@
|
||||
#endif
|
||||
|
||||
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
||||
#if !defined(MIN_HEAP_SIZE)
|
||||
#define MIN_HEAP_SIZE 8192
|
||||
#endif
|
||||
|
||||
// Maximum size of node map (list of other WLED instances)
|
||||
#ifdef ESP8266
|
||||
|
||||
@@ -2008,6 +2008,9 @@ function readState(s,command=false)
|
||||
case 36:
|
||||
errstr = "Low Memory (oappend buffer).";
|
||||
break;
|
||||
case 37:
|
||||
errstr = "no memory for LEDs buffer.";
|
||||
break;
|
||||
}
|
||||
showToast('Error ' + s.error + ": " + errstr, true);
|
||||
}
|
||||
|
||||
@@ -187,6 +187,9 @@ void DMXInput::updateInternal()
|
||||
unsigned long now = millis();
|
||||
if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) {
|
||||
if (!packet.err) {
|
||||
if(!connected) {
|
||||
USER_PRINTLN("DMX Input - connected");
|
||||
}
|
||||
connected = true;
|
||||
identify = isIdentifyOn();
|
||||
if (!packet.is_rdm) {
|
||||
@@ -199,6 +202,9 @@ void DMXInput::updateInternal()
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(connected) {
|
||||
USER_PRINTLN("DMX Input - disconnected");
|
||||
}
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ void calcGammaTable(float gamma);
|
||||
uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure
|
||||
uint32_t __attribute__((pure)) gamma32(uint32_t); // WLEDMM: added attribute pure
|
||||
uint8_t unGamma8(uint8_t value); // WLEDMM revert gamma correction
|
||||
uint32_t unGamma24(uint32_t c); // WLEDMM for 24bit color (white left as-is)
|
||||
|
||||
//dmx_output.cpp
|
||||
void initDMXOutput();
|
||||
@@ -249,7 +250,7 @@ void refreshNodeList();
|
||||
void sendSysInfoUDP();
|
||||
|
||||
//network.cpp
|
||||
int getSignalQuality(int rssi);
|
||||
int getSignalQuality(int rssi) __attribute__((const));
|
||||
void WiFiEvent(WiFiEvent_t event);
|
||||
|
||||
//um_manager.cpp
|
||||
@@ -368,7 +369,7 @@ bool oappendi(int i); // append new number to temp buffer efficiently
|
||||
void sappend(char stype, const char* key, int val);
|
||||
void sappends(char stype, const char* key, char* val);
|
||||
void prepareHostname(char* hostname);
|
||||
bool isAsterisksOnly(const char* str, byte maxLen);
|
||||
bool isAsterisksOnly(const char* str, byte maxLen) __attribute__((pure));
|
||||
bool requestJSONBufferLock(uint8_t module=255);
|
||||
void releaseJSONBufferLock();
|
||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||
@@ -409,13 +410,14 @@ void clearEEPROM();
|
||||
//wled_math.cpp
|
||||
#ifndef WLED_USE_REAL_MATH
|
||||
template <typename T> T atan_t(T x);
|
||||
float cos_t(float phi);
|
||||
float sin_t(float x);
|
||||
float tan_t(float x);
|
||||
float cos_t(float phi) __attribute__((const));
|
||||
float sin_t(float x) __attribute__((const));
|
||||
float tan_t(float x) __attribute__((const));
|
||||
float acos_t(float x);
|
||||
float asin_t(float x);
|
||||
float floor_t(float x);
|
||||
float fmod_t(float num, float denom);
|
||||
float atan_t(float x) __attribute__((const));
|
||||
float floor_t(float x) __attribute__((const));
|
||||
float fmod_t(float num, float denom) __attribute__((const));
|
||||
#else
|
||||
#include <math.h> // WLEDMM use "float" variants
|
||||
#define sin_t sinf
|
||||
|
||||
@@ -68,7 +68,7 @@ void toggleOnOff()
|
||||
|
||||
|
||||
//scales the brightness with the briMultiplier factor
|
||||
IRAM_ATTR_YN byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN
|
||||
IRAM_ATTR_YN __attribute__((hot)) byte scaledBri(byte in) // WLEDMM added IRAM_ATTR_YN
|
||||
{
|
||||
if (briMultiplier == 100) return(in); // WLEDMM shortcut
|
||||
uint_fast16_t val = ((uint_fast16_t)in*(uint_fast16_t)briMultiplier)/100; // WLEDMM
|
||||
|
||||
@@ -89,7 +89,7 @@ const ethernet_settings ethernetBoards[] = {
|
||||
|
||||
// ESP32-ETHERNET-KIT-VE
|
||||
{
|
||||
0, // eth_address,
|
||||
1, // eth_address, WLED-MM: Changed from 0 to 1 based on not working with 0 on same devkit.
|
||||
5, // eth_power,
|
||||
23, // eth_mdc,
|
||||
18, // eth_mdio,
|
||||
|
||||
@@ -723,7 +723,7 @@ bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) {
|
||||
*/
|
||||
|
||||
// Check if supplied GPIO is ok to use
|
||||
bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
bool PinManagerClass::isPinOk(byte gpio, bool output) const
|
||||
{
|
||||
#ifdef ESP32
|
||||
if (digitalPinIsValid(gpio)) {
|
||||
@@ -757,7 +757,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
return false;
|
||||
}
|
||||
|
||||
PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
||||
PinOwner PinManagerClass::getPinOwner(byte gpio) const {
|
||||
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
|
||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||
return ownerTag[gpio];
|
||||
|
||||
@@ -125,9 +125,9 @@ class PinManagerClass {
|
||||
// will return true for reserved pins
|
||||
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
||||
// will return false for reserved pins
|
||||
bool isPinOk(byte gpio, bool output = true);
|
||||
bool isPinOk(byte gpio, bool output = true) const;
|
||||
|
||||
PinOwner getPinOwner(byte gpio);
|
||||
PinOwner getPinOwner(byte gpio) const;
|
||||
|
||||
// WLEDMM begin
|
||||
String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text
|
||||
|
||||
@@ -116,7 +116,7 @@ char* dayShortStr(uint8_t day);
|
||||
|
||||
/* low level functions to convert to and from system time */
|
||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
||||
time_t makeTime(tmElements_t &tm) __attribute__((pure)); // convert time elements into time_t
|
||||
|
||||
} // extern "C++"
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -1220,7 +1220,7 @@ void WLED::handleConnection()
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||
if ((!strip.isUpdating()) && (now - heapTime > 5000)) { // WLEDMM: updated with better logic for small heap available by block, not total. // WLEDMM trying to use a moment when the strip is idle
|
||||
#if defined(ARDUINO_ARCH_ESP32S2)
|
||||
#if defined(ARDUINO_ARCH_ESP32S2) || defined(WLED_ENABLE_HUB75MATRIX)
|
||||
uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2
|
||||
#else
|
||||
uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2407171
|
||||
#define VERSION 2408080
|
||||
|
||||
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
|
||||
#define _MoonModules_WLED_
|
||||
@@ -928,9 +928,9 @@ public:
|
||||
}
|
||||
|
||||
// boot starts here
|
||||
void setup();
|
||||
void setup() __attribute__((used));
|
||||
|
||||
void loop();
|
||||
void loop() __attribute__((used));
|
||||
void reset();
|
||||
|
||||
void beginStrip();
|
||||
|
||||
@@ -61,6 +61,7 @@ void esp_heap_trace_free_hook(void* ptr)
|
||||
unsigned long lastMillis = 0; //WLEDMM
|
||||
unsigned long loopCounter = 0; //WLEDMM
|
||||
|
||||
void setup() __attribute__((used)); // needed for -flto
|
||||
void setup() {
|
||||
#ifdef WLED_DEBUG_HEAP
|
||||
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
|
||||
@@ -68,6 +69,7 @@ void setup() {
|
||||
WLED::instance().setup();
|
||||
}
|
||||
|
||||
void loop() __attribute__((used)); // needed for -flto
|
||||
void loop() {
|
||||
//WLEDMM show loops per second
|
||||
loopCounter++;
|
||||
|
||||
Reference in New Issue
Block a user