Merge branch 'mdev' of https://github.com/troyhacks/WLED into mdev
This commit is contained in:
@@ -1036,9 +1036,10 @@ HUB75_build_flags =
|
|||||||
-D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size
|
-D NO_FAST_FUNCTIONS ;; If you are not using AdafruitGFX than you probably do not need this either, save memory/code size
|
||||||
-D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already
|
-D NO_CIE1931 ;; Do not use LED brightness compensation described in CIE 1931. We use FastLED dimming already
|
||||||
-D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips
|
-D S3_LCD_DIV_NUM=20 ;; Attempt to fix wifi performance issue when panel active with S3 chips
|
||||||
;; HUB75_lib_deps = https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10 ;; does not work any more
|
|
||||||
;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30)
|
;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.11 ;; breaks the build (2024-07-30)
|
||||||
HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; something strange is going on here ...
|
;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ...
|
||||||
|
HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#1e4c80a26454aca7b8129bd5a966b0af329d2703 ;; 3.0.10 - something strange is going on here ...
|
||||||
|
;; HUB75_lib_deps = https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA.git#c4ecdcfeeb5aa668d92ddf3c3c74bc93316f6e10 ;; 3.0.11
|
||||||
HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes)
|
HUB75_lib_ignore = ESP32 HUB75 LED MATRIX PANEL DMA Display ;; to remove the HUB75 lib dependancy (saves a few bytes)
|
||||||
|
|
||||||
NetDebug_build_flags =
|
NetDebug_build_flags =
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ static volatile float micReal_max2 = 0.0f; // MicIn data max afte
|
|||||||
// some prototypes, to ensure consistent interfaces
|
// some prototypes, to ensure consistent interfaces
|
||||||
static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float
|
static float mapf(float x, float in_min, float in_max, float out_min, float out_max); // map function for float
|
||||||
static float fftAddAvg(int from, int to); // average of several FFT result bins
|
static float fftAddAvg(int from, int to); // average of several FFT result bins
|
||||||
void FFTcode(void * parameter); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
|
void FFTcode(void * parameter) __attribute__((noreturn)); // audio processing task: read samples, run FFT, fill GEQ channels from FFT results
|
||||||
static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass)
|
static void runMicFilter(uint16_t numSamples, float *sampleBuffer); // pre-filtering of raw samples (band-pass)
|
||||||
static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels
|
static void postProcessFFTResults(bool noiseGateOpen, int numberOfChannels, bool i2sFastpath); // post-processing and post-amp of GEQ channels
|
||||||
|
|
||||||
|
|||||||
@@ -2148,7 +2148,7 @@ uint16_t mode_fire_2012() {
|
|||||||
|
|
||||||
// Step 4. Map from heat cells to LED colors
|
// Step 4. Map from heat cells to LED colors
|
||||||
for (int j = 0; j < SEGLEN; j++) {
|
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++)
|
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||||
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
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)
|
if (it != SEGENV.step)
|
||||||
SEGENV.step = it;
|
SEGENV.step = it;
|
||||||
|
|
||||||
return FRAMETIME;
|
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
|
// 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
|
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
|
// outer stars
|
||||||
for (size_t i = 0; i < 8; i++) {
|
for (unsigned i = 0; i < 8; i++) {
|
||||||
x = beatsin8(SEGMENT.custom1>>3, 0, cols - 1, 0, ((i % 2) ? 128 : 0) + t * 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);
|
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));
|
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||||
}
|
}
|
||||||
// inner stars
|
// inner stars
|
||||||
for (size_t i = 0; i < 4; i++) {
|
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);
|
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);
|
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));
|
SEGMENT.addPixelColorXY(x, y, CHSV(i*32, 255, 255));
|
||||||
}
|
}
|
||||||
// central white dot
|
// central white dot
|
||||||
@@ -6270,6 +6276,10 @@ uint16_t mode_2Dfloatingblobs(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SEGMENT.fadeToBlackBy(20);
|
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
|
// Bounce balls around
|
||||||
for (size_t i = 0; i < Amount; i++) {
|
for (size_t i = 0; i < Amount; i++) {
|
||||||
@@ -6278,18 +6288,18 @@ uint16_t mode_2Dfloatingblobs(void) {
|
|||||||
if (blob->grow[i]) {
|
if (blob->grow[i]) {
|
||||||
// enlarge radius until it is >= 4
|
// 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;
|
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;
|
blob->grow[i] = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// reduce radius until it is < 1
|
// 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;
|
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;
|
blob->grow[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
|
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);
|
else SEGMENT.setPixelColorXY((int)roundf(blob->x[i]), (int)roundf(blob->y[i]), c);
|
||||||
// move x
|
// 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));
|
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;
|
long t = strip.now / 2;
|
||||||
for (int i = 0; i < cols; i++) {
|
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 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);
|
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)
|
if (!SEGENV.check1)
|
||||||
SEGMENT.addPixelColorXY(i, 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, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
|
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, jmap, 255, LINEARBLEND));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SEGMENT.blur(16);
|
SEGMENT.blur(16);
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
} // mode_2DWaverly()
|
} // 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
|
#endif // WLED_DISABLE_2D
|
||||||
|
|
||||||
@@ -7511,9 +7527,9 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift the pixels one pixel up
|
// shift the pixels one pixel up
|
||||||
SEGMENT.setPixelColor(0, color);
|
|
||||||
// if SEGLEN equals 1 this loop won't execute
|
// 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
|
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;
|
return FRAMETIME;
|
||||||
|
|||||||
149
wled00/FX.h
149
wled00/FX.h
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
|
bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp
|
||||||
void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.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 FASTLED_INTERNAL //remove annoying pragma messages
|
||||||
#define USE_GET_MILLISECOND_TIMER
|
#define USE_GET_MILLISECOND_TIMER
|
||||||
@@ -434,6 +434,20 @@ typedef struct Segment {
|
|||||||
static size_t _usedSegmentData; // WLEDMM uint16_t is too small
|
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!!!
|
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
|
// perhaps this should be per segment, not static
|
||||||
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
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);
|
bool allocateData(size_t len);
|
||||||
void deallocateData(void);
|
void deallocateData(void);
|
||||||
void resetIfRequired(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,
|
* Flags that before the next effect is calculated,
|
||||||
* the internal segment state should be reset.
|
* the internal segment state should be reset.
|
||||||
@@ -625,7 +640,7 @@ typedef struct Segment {
|
|||||||
void setPixelColor(float i, uint32_t c, bool aa = true);
|
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, 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); }
|
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)
|
// 1D support functions (some implement 2D as well)
|
||||||
void blur(uint8_t, bool smear = false);
|
void blur(uint8_t, bool smear = false);
|
||||||
void fill(uint32_t c);
|
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, 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
|
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);
|
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_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);
|
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
|
// 2D matrix
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline
|
inline uint16_t virtualWidth() const { // WLEDMM use fast types, and make function inline
|
||||||
uint_fast16_t groupLen = groupLength();
|
uint_fast16_t groupLen = groupLength();
|
||||||
uint_fast16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
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
|
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vHeight;
|
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;
|
uint16_t nrOfVStrips(void) const;
|
||||||
void createjMap(); //WLEDMM jMap
|
void createjMap(); //WLEDMM jMap
|
||||||
void deletejMap(); //WLEDMM jMap
|
void deletejMap(); //WLEDMM jMap
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#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
|
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 = virtualWidth(); // segment width in logical pixels
|
uint_fast16_t width = max(uint16_t(1), virtualWidth()); // segment width in logical pixels -- softhack007 avoid div/0
|
||||||
uint_fast16_t height = virtualHeight(); // segment height in logical pixels
|
uint_fast16_t height = max(uint16_t(1), virtualHeight()); // segment height in logical pixels -- softhack007 avoid div/0
|
||||||
if (width == 0) return 0; // softhack007 avoid div/0
|
|
||||||
if (height == 0) return (x%width); // softhack007 avoid div/0
|
|
||||||
return (x%width) + (y%height) * width;
|
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
|
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(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, 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)); }
|
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, 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); }
|
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
|
//#endif
|
||||||
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y);
|
uint32_t __attribute__((pure)) getPixelColorXY(int x, int y) const;
|
||||||
// 2D support functions
|
// 2D support functions
|
||||||
void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend);
|
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); }
|
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 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);
|
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); }
|
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);
|
void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft);
|
||||||
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); }
|
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);
|
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
|
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);
|
void drawArc(unsigned x0, unsigned y0, int 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
|
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);
|
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
|
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);
|
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 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) {}
|
inline void wu_pixel(uint32_t x, uint32_t y, CRGB c) {}
|
||||||
#endif
|
#endif
|
||||||
uint8_t * getAudioPalette(int pal); //WLEDMM netmindz ar palette
|
uint8_t * getAudioPalette(int pal) const; //WLEDMM netmindz ar palette
|
||||||
} segment;
|
} segment;
|
||||||
//static int segSize = sizeof(Segment);
|
//static int segSize = sizeof(Segment);
|
||||||
|
|
||||||
@@ -868,64 +925,64 @@ class WS2812FX { // 96 bytes
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
checkSegmentAlignment(void),
|
checkSegmentAlignment(void),
|
||||||
hasRGBWBus(void),
|
hasRGBWBus(void) const,
|
||||||
hasCCTBus(void),
|
hasCCTBus(void) const,
|
||||||
// return true if the strip is being sent pixel updates
|
// return true if the strip is being sent pixel updates
|
||||||
isUpdating(void),
|
isUpdating(void) const,
|
||||||
deserializeMap(uint8_t n=0),
|
deserializeMap(uint8_t n=0),
|
||||||
useLedsArray = false;
|
useLedsArray = false;
|
||||||
|
|
||||||
inline bool isServicing(void) { return _isServicing; }
|
inline bool isServicing(void) const { return _isServicing; }
|
||||||
inline bool hasWhiteChannel(void) {return _hasWhiteChannel;}
|
inline bool hasWhiteChannel(void) const {return _hasWhiteChannel;}
|
||||||
inline bool isOffRefreshRequired(void) {return _isOffRefreshRequired;}
|
inline bool isOffRefreshRequired(void) const {return _isOffRefreshRequired;}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
paletteFade,
|
paletteFade,
|
||||||
paletteBlend,
|
paletteBlend,
|
||||||
milliampsPerLed,
|
milliampsPerLed,
|
||||||
cctBlending,
|
cctBlending,
|
||||||
getActiveSegmentsNum(void),
|
getActiveSegmentsNum(void) const,
|
||||||
getFirstSelectedSegId(void),
|
getFirstSelectedSegId(void) __attribute__((pure)),
|
||||||
getLastActiveSegmentId(void),
|
getLastActiveSegmentId(void) const,
|
||||||
getActiveSegsLightCapabilities(bool selectedOnly = false),
|
getActiveSegsLightCapabilities(bool selectedOnly = false) __attribute__((pure)),
|
||||||
setPixelSegment(uint8_t n);
|
setPixelSegment(uint8_t n);
|
||||||
|
|
||||||
inline uint8_t getBrightness(void) { return _brightness; }
|
inline uint8_t getBrightness(void) const { return _brightness; }
|
||||||
inline uint8_t getMaxSegments(void) { return MAX_NUM_SEGMENTS; } // returns maximum number of supported segments (fixed value)
|
inline uint8_t getMaxSegments(void) const { 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 getSegmentsNum(void) const { return _segments.size(); } // returns currently present segments
|
||||||
inline uint8_t getCurrSegmentId(void) { return _segment_index; }
|
inline uint8_t getCurrSegmentId(void) const { return _segment_index; }
|
||||||
inline uint8_t getMainSegmentId(void) { return _mainSegment; }
|
inline uint8_t getMainSegmentId(void) const { return _mainSegment; }
|
||||||
inline uint8_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
inline uint8_t getPaletteCount() const { return 13 + GRADIENT_PALETTE_COUNT; } // will only return built-in palette count
|
||||||
inline uint8_t getTargetFps() { return _targetFps; }
|
inline uint8_t getTargetFps() const { return _targetFps; }
|
||||||
inline uint8_t getModeCount() { return _modeCount; }
|
inline uint8_t getModeCount() const { return _modeCount; }
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
ablMilliampsMax,
|
ablMilliampsMax,
|
||||||
currentMilliamps,
|
currentMilliamps,
|
||||||
getLengthPhysical(void),
|
getLengthPhysical(void) const,
|
||||||
__attribute__((pure)) getLengthTotal(void), // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
__attribute__((pure)) getLengthTotal(void) const, // will include virtual/nonexistent pixels in matrix //WLEDMM attribute added
|
||||||
getFps();
|
getFps() const;
|
||||||
|
|
||||||
inline uint16_t getFrameTime(void) { return _frametime; }
|
inline uint16_t getFrameTime(void) const { return _frametime; }
|
||||||
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
inline uint16_t getMinShowDelay(void) const { return MIN_SHOW_DELAY; }
|
||||||
inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H
|
inline uint16_t getLength(void) const { return _length; } // 2D matrix may have less pixels than W*H
|
||||||
inline uint16_t getTransition(void) { return _transitionDur; }
|
inline uint16_t getTransition(void) const { return _transitionDur; }
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
now,
|
now,
|
||||||
timebase;
|
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 getLastShow(void) const { return _lastShow; }
|
||||||
inline uint32_t segColor(uint8_t i) { return _colors_t[i]; }
|
inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; }
|
||||||
|
|
||||||
const char *
|
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 **
|
const char **
|
||||||
getModeDataSrc(void) { return &(_modeData[0]); } // vectors use arrays for underlying data
|
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& getFirstSelectedSeg(void) { return _segments[getFirstSelectedSegId()]; }
|
||||||
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
inline Segment& getMainSegment(void) { return _segments[getMainSegmentId()]; }
|
||||||
inline Segment* getSegments(void) { return &(_segments[0]); }
|
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)); }
|
inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); }
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
getPixelColorXY(uint16_t, uint16_t);
|
getPixelColorXY(uint16_t, uint16_t) const;
|
||||||
|
|
||||||
// end 2D support
|
// 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
|
//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
|
#else
|
||||||
isMatrix = false; // no matter what config says
|
isMatrix = false; // no matter what config says
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// absolute matrix version of setPixelColor(), without error checking
|
// 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;
|
uint_fast16_t index = y * Segment::maxWidth + x;
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
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
|
// 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
|
#ifndef WLED_DISABLE_2D
|
||||||
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types
|
||||||
#else
|
#else
|
||||||
@@ -217,13 +235,29 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
|||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#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)
|
// 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
|
// WLEDMM Segment::XY()is declared inline, see FX.h
|
||||||
|
|
||||||
|
|
||||||
// Simplified version of Segment::setPixelColorXY - without error checking. Does not support grouping or spacing
|
// 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()
|
// * 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;
|
unsigned i = UINT_MAX;
|
||||||
bool sameColor = false;
|
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
|
// 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
|
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
|
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||||
const int_fast16_t cols = virtualWidth(); // WLEDMM optimization
|
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
|
// 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 (x<0 || y<0 || !isActive()) return 0; // not active or out-of range
|
||||||
if (ledsrgb) {
|
if (ledsrgb) {
|
||||||
int i = XY(x,y);
|
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++) {
|
for (int j = 0; j < dim1; j++) {
|
||||||
int x = vertical ? i : j;
|
int x = vertical ? i : j;
|
||||||
int y = vertical ? j : i;
|
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
|
// 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) {
|
void Segment::fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft) {
|
||||||
if (!isActive() || radius == 0) return; // not active
|
if (!isActive() || radius <= 0) return; // not active
|
||||||
// draw soft bounding circle
|
// draw soft bounding circle
|
||||||
if (soft) drawCircle(cx, cy, radius, col, soft);
|
if (soft) drawCircle(cx, cy, radius, col, soft);
|
||||||
// fill it
|
|
||||||
const int cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const int rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
for (int y = -radius; y <= radius; y++) {
|
|
||||||
for (int x = -radius; x <= radius; x++) {
|
const int_fast32_t maxRadius2 = radius * radius - (((radius > 3) && !soft) ? 1:0); // WLEDMM pre-compute r^2; '-1' removes spikes from bigger blobs
|
||||||
if (x * x + y * y <= radius * radius &&
|
// WLEDMM pre-compute boundaries
|
||||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
const int startx = max(-radius, -int(cx));
|
||||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
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);
|
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;
|
uint32_t scaled_col = c;
|
||||||
if (simpleSegment) {
|
if (simpleSegment) {
|
||||||
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
|
// 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);
|
uint8_t _bri_t = currentBri(on ? opacity : 0);
|
||||||
|
#endif
|
||||||
if (!_bri_t && !transitional) return;
|
if (!_bri_t && !transitional) return;
|
||||||
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
|
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)
|
// single pixel (line length == 0)
|
||||||
if (dx+dy == 0) {
|
if (dx+dy == 0) {
|
||||||
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
if (simpleSegment) setPixelColorXY_fast(x0, y0, c, scaled_col, cols, rows);
|
||||||
else setPixelColorXY(x0, y0, c);
|
else setPixelColorXY_slow(x0, y0, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +783,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
// if (x0 >= cols || y0 >= rows) break; // WLEDMM we hit the edge - should never happen
|
// 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);
|
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;
|
if (x0==x1 && y0==y1) break;
|
||||||
int e2 = err;
|
int e2 = err;
|
||||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
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) {
|
void Segment::drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive() || (radius <=0)) return; // not active
|
||||||
// float step = degrees / (2.85f*MAX(radius,1));
|
float minradius = float(radius) - .5;
|
||||||
// for (float rad = 0.0f; rad <= degrees+step/2; rad += step) {
|
float maxradius = float(radius) + .5;
|
||||||
// // may want to try float version as well (with or without antialiasing)
|
// WLEDMM pre-calculate values to speed up the loop
|
||||||
// int x = roundf(sin_t(rad) * radius);
|
const int minradius2 = roundf(minradius * minradius);
|
||||||
// int y = roundf(cos_t(rad) * radius);
|
const int maxradius2 = roundf(maxradius * maxradius);
|
||||||
// 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++) {
|
|
||||||
|
|
||||||
int newX = x - x0;
|
// WLEDMM only loop over surrounding square (50% faster)
|
||||||
int newY = y - y0;
|
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);
|
setPixelColorXY(x, y, color);
|
||||||
|
} else {
|
||||||
if (fillColor != 0)
|
if (fillColor != 0)
|
||||||
if (newX*newX + newY*newY < minradius * minradius)
|
if (distance2 < minradius2)
|
||||||
setPixelColorXY(x, y, fillColor);
|
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
|
// multiply the intensities by the colour, and saturating-add them to the pixels
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1));
|
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.r = qadd8(led.r, c.r * wu[i] >> 8);
|
||||||
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
led.g = qadd8(led.g, c.g * wu[i] >> 8);
|
||||||
led.b = qadd8(led.b, c.b * 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
|
#undef WU_WEIGHT
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void Segment::allocLeds() {
|
|||||||
ledsrgbSize = ledsrgb?size:0;
|
ledsrgbSize = ledsrgb?size:0;
|
||||||
if (ledsrgb == nullptr) {
|
if (ledsrgb == nullptr) {
|
||||||
USER_PRINTLN("allocLeds failed!!");
|
USER_PRINTLN("allocLeds failed!!");
|
||||||
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
|
errorFlag = ERR_LOW_BUF; // WLEDMM raise errorflag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -266,6 +266,7 @@ void Segment::resetIfRequired() {
|
|||||||
deallocateData();
|
deallocateData();
|
||||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||||
|
startFrame(); // WLEDMM update cached propoerties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +674,11 @@ class JMapC {
|
|||||||
if (size > 0)
|
if (size > 0)
|
||||||
return size;
|
return size;
|
||||||
else
|
else
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
return SEGMENT.virtualWidth() * SEGMENT.virtualHeight(); //pixels
|
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) {
|
void setPixelColor(uint16_t i, uint32_t col) {
|
||||||
updatejMapDoc();
|
updatejMapDoc();
|
||||||
@@ -765,7 +770,11 @@ class JMapC {
|
|||||||
jMapFile.close();
|
jMapFile.close();
|
||||||
|
|
||||||
maxWidth++; maxHeight++;
|
maxWidth++; maxHeight++;
|
||||||
|
#ifndef WLEDMM_FASTPATH
|
||||||
scale = min(SEGMENT.virtualWidth() / maxWidth, SEGMENT.virtualHeight() / maxHeight); // WLEDMM use native min/max
|
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);
|
dataSize += sizeof(jVectorMap);
|
||||||
USER_PRINT("dataSize ");
|
USER_PRINT("dataSize ");
|
||||||
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_Steps_Big = 304; // no holes up to 50x50
|
||||||
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
||||||
constexpr int Pinwheel_Steps_XL = 368;
|
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_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_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_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_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)
|
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_Small) return float(i) * Int_to_Rad_Small;
|
||||||
if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med;
|
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_Big) return float(i) * Int_to_Rad_Big;
|
||||||
|
if (maxXY <= Pinwheel_Size_XL) return float(i) * Int_to_Rad_XL;
|
||||||
// else
|
// else
|
||||||
return float(i) * Int_to_Rad_XL;
|
return float(i) * Int_to_Rad_XXL;
|
||||||
}
|
}
|
||||||
// Pinwheel helper function: matrix dimensions to number of rays
|
// Pinwheel helper function: matrix dimensions to number of rays
|
||||||
static int getPinwheelLength(int vW, int vH) {
|
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_Small) return Pinwheel_Steps_Small;
|
||||||
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
||||||
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
||||||
|
if (maxXY <= Pinwheel_Size_XL) return Pinwheel_Steps_XL;
|
||||||
// else
|
// else
|
||||||
return Pinwheel_Steps_XL;
|
return Pinwheel_Steps_XXL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -873,7 +887,7 @@ uint16_t Segment::virtualLength() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//WLEDMM used for M12_sBlock
|
//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;
|
float i2;
|
||||||
if (i<=SEGLEN*0.25) { //top, left to right
|
if (i<=SEGLEN*0.25) { //top, left to right
|
||||||
i2 = i/(SEGLEN*0.25);
|
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
|
if (!isActive()) return; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
@@ -1057,7 +1071,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
|
|||||||
// set pixel
|
// set pixel
|
||||||
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
if (x != lastX || y != lastY) { // only paint if pixel position is different
|
||||||
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
if (simpleSegment) setPixelColorXY_fast(x, y, col, scaled_col, vW, vH);
|
||||||
else setPixelColorXY(x, y, col);
|
else setPixelColorXY_slow(x, y, col);
|
||||||
}
|
}
|
||||||
lastX = x;
|
lastX = x;
|
||||||
lastY = y;
|
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
|
if (!isActive()) return 0; // not active
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
@@ -1336,8 +1350,20 @@ void Segment::refreshLightCapabilities() {
|
|||||||
/*
|
/*
|
||||||
* Fills segment with color - WLEDMM using faster sPC if possible
|
* 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 (!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 cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
@@ -1353,7 +1379,7 @@ void Segment::fill(uint32_t c) {
|
|||||||
// fill 2D segment
|
// fill 2D segment
|
||||||
for(int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
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);
|
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
|
} else { // fill 1D strip
|
||||||
for (int x = 0; x < cols; x++) setPixelColor(x, c);
|
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 g2 = G(color2);
|
||||||
int b2 = B(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);
|
uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
|
||||||
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
|
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
|
||||||
int w1 = W(color);
|
int w1 = W(color);
|
||||||
@@ -1426,15 +1452,17 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 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 (colorNew != color) { // WLEDMM speedup - do not repaint the same color
|
||||||
if (is2D()) setPixelColorXY((uint16_t)x, (uint16_t)y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
if (is2D()) setPixelColorXY(x, y, colorNew);
|
||||||
else setPixelColor((uint16_t)x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
else setPixelColor(x, colorNew);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fades all pixels to black using nscale8()
|
// 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
|
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 cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
|
||||||
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
|
||||||
@@ -1442,8 +1470,11 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
|
|
||||||
// WLEDMM minor optimization
|
// WLEDMM minor optimization
|
||||||
if(is2D()) {
|
if(is2D()) {
|
||||||
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++) {
|
||||||
setPixelColorXY((uint16_t)x, (uint16_t)y, CRGB(getPixelColorXY(x,y)).nscale8(scaledown));
|
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 {
|
} else {
|
||||||
for (uint_fast16_t x = 0; x < cols; x++) {
|
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
|
* 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"
|
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
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.
|
* 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;
|
uint_fast8_t r = 0, x = 0, y = 0, d = 0;
|
||||||
|
|
||||||
while(d < 42) {
|
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)
|
* @param pbri Value to scale the brightness of the returned color by. Default is 255. (no scaling)
|
||||||
* @returns Single color from palette
|
* @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
|
// default palette or no RGB support on segment
|
||||||
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) {
|
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
|
//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
|
// 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;
|
um_data_t *um_data;
|
||||||
@@ -1834,6 +1865,7 @@ void WS2812FX::service() {
|
|||||||
if (!cctFromRgb || correctWB) busses.setSegmentCCT(seg.currentBri(seg.cct, true), correctWB);
|
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]);
|
for (uint8_t c = 0; c < NUM_COLORS; c++) _colors_t[c] = gamma32(_colors_t[c]);
|
||||||
|
|
||||||
|
seg.startFrame(); // WLEDMM
|
||||||
// effect blending (execute previous effect)
|
// effect blending (execute previous effect)
|
||||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
// 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());
|
//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);
|
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 < customMappingSize) i = customMappingTable[i];
|
||||||
if (i >= _length) return 0;
|
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.
|
* Returns a true value if any of the strips are still being updated.
|
||||||
* On some hardware (ESP32), strip updates are done asynchronously.
|
* On some hardware (ESP32), strip updates are done asynchronously.
|
||||||
*/
|
*/
|
||||||
bool WS2812FX::isUpdating() {
|
bool WS2812FX::isUpdating() const {
|
||||||
return !busses.canAllShow();
|
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.
|
* 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
|
* 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;
|
if (millis() - _lastShow > 2000) return 0;
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
|
return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding
|
||||||
@@ -2102,14 +2134,14 @@ void WS2812FX::setMainSegmentId(uint8_t n) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getLastActiveSegmentId(void) {
|
uint8_t WS2812FX::getLastActiveSegmentId(void) const {
|
||||||
for (size_t i = _segments.size() -1; i > 0; i--) {
|
for (size_t i = _segments.size() -1; i > 0; i--) {
|
||||||
if (_segments[i].isActive()) return i;
|
if (_segments[i].isActive()) return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
uint8_t WS2812FX::getActiveSegmentsNum(void) const {
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
for (size_t i = 0; i < _segments.size(); i++) {
|
for (size_t i = 0; i < _segments.size(); i++) {
|
||||||
if (_segments[i].isActive()) c++;
|
if (_segments[i].isActive()) c++;
|
||||||
@@ -2117,13 +2149,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
|||||||
return c;
|
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
|
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
|
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
||||||
return len;
|
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;
|
uint_fast16_t len = 0;
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
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.
|
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
|
||||||
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
//returns if there is an RGBW bus (supports RGB and White, not only white)
|
||||||
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
//not influenced by auto-white mode, also true if white slider does not affect output white channel
|
||||||
bool WS2812FX::hasRGBWBus(void) {
|
bool WS2812FX::hasRGBWBus(void) const {
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
if (bus == nullptr || bus->getLength()==0) break;
|
if (bus == nullptr || bus->getLength()==0) break;
|
||||||
@@ -2145,7 +2177,7 @@ bool WS2812FX::hasRGBWBus(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WS2812FX::hasCCTBus(void) {
|
bool WS2812FX::hasCCTBus(void) const {
|
||||||
if (cctFromRgb && !correctWB) return false;
|
if (cctFromRgb && !correctWB) return false;
|
||||||
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
for (unsigned b = 0; b < busses.getNumBusses(); b++) { // WLEDMM use native (fast) types
|
||||||
Bus *bus = busses.getBus(b);
|
Bus *bus = busses.getBus(b);
|
||||||
|
|||||||
@@ -9,6 +9,36 @@
|
|||||||
#include "bus_wrapper.h"
|
#include "bus_wrapper.h"
|
||||||
#include "bus_manager.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
|
//WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope
|
||||||
#if 0
|
#if 0
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
@@ -49,13 +79,6 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#endif
|
#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) {
|
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
||||||
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
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;
|
uint8_t aWM = _autoWhiteMode;
|
||||||
if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM;
|
if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM;
|
||||||
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
||||||
@@ -139,7 +162,7 @@ void BusDigital::show() {
|
|||||||
PolyBus::show(_busPtr, _iType);
|
PolyBus::show(_busPtr, _iType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BusDigital::canShow() {
|
bool BusDigital::canShow() const {
|
||||||
return PolyBus::canShow(_busPtr, _iType);
|
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);
|
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;
|
if (reversed) pix = _len - pix -1;
|
||||||
else pix += _skip;
|
else pix += _skip;
|
||||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
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);
|
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;
|
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
||||||
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||||
return numPins;
|
return numPins;
|
||||||
@@ -317,7 +340,7 @@ void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//does no index check
|
//does no index check
|
||||||
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
uint32_t BusPwm::getPixelColor(uint16_t pix) const {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
#if 1
|
#if 1
|
||||||
// WLEDMM stick with the old code - we don't have cctICused
|
// 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;
|
if (!_valid) return 0;
|
||||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||||
for (uint8_t i = 0; i < numPins; i++) {
|
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;
|
_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;
|
if (!_valid) return 0;
|
||||||
return RGBW32(_data, _data, _data, _data);
|
return RGBW32(_data, _data, _data, _data);
|
||||||
}
|
}
|
||||||
@@ -418,7 +441,7 @@ void BusOnOff::show() {
|
|||||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
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;
|
if (!_valid) return 0;
|
||||||
pinArray[0] = _pin;
|
pinArray[0] = _pin;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -467,7 +490,7 @@ void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
if (_rgbw) _data[offset+3] = W(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;
|
if (!_valid || pix >= _len) return 0;
|
||||||
uint16_t offset = pix * _UDPchannels;
|
uint16_t offset = pix * _UDPchannels;
|
||||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
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;
|
_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++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
pinArray[i] = _client[i];
|
pinArray[i] = _client[i];
|
||||||
}
|
}
|
||||||
@@ -501,9 +524,9 @@ void BusNetwork::cleanup() {
|
|||||||
|
|
||||||
BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
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
|
mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory
|
||||||
|
|
||||||
|
|
||||||
fourScanPanel = nullptr;
|
fourScanPanel = nullptr;
|
||||||
|
|
||||||
switch(bc.type) {
|
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");
|
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.r1 = 42;
|
||||||
mxconfig.gpio.g1 = 41;
|
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.d = 21;
|
||||||
mxconfig.gpio.e = 12;
|
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
|
#else
|
||||||
USER_PRINTLN("MatrixPanel_I2S_DMA - Default pins");
|
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");
|
USER_PRINTLN("MatrixPanel_I2S_DMA created");
|
||||||
// let's adjust default brightness
|
// let's adjust default brightness
|
||||||
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
||||||
|
_bri = 25;
|
||||||
|
|
||||||
|
delay(24); // experimental
|
||||||
// Allocate memory and start DMA display
|
// Allocate memory and start DMA display
|
||||||
if( not display->begin() ) {
|
if( not display->begin() ) {
|
||||||
USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
delay(18); // experiment - give the driver a moment (~ one full frame @ 60hz) to settle
|
||||||
_valid = true;
|
_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) {
|
switch(bc.type) {
|
||||||
@@ -686,28 +737,125 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
break;
|
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) {
|
void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
||||||
r = R(c);
|
if (!_valid || pix >= _len) return;
|
||||||
g = G(c);
|
// if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||||
b = B(c);
|
|
||||||
if(fourScanPanel != nullptr) {
|
if (_ledBuffer) {
|
||||||
x = pix % fourScanPanel->width();
|
CRGB fastled_col = CRGB(c);
|
||||||
y = floor(pix / fourScanPanel->width());
|
if (_ledBuffer[pix] != fastled_col) {
|
||||||
fourScanPanel->drawPixelRGB888(x, y, r, g, b);
|
_ledBuffer[pix] = fastled_col;
|
||||||
|
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
x = pix % display->width();
|
if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
|
||||||
y = floor(pix / display->width());
|
setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK"
|
||||||
display->drawPixelRGB888(x, y, r, g, b);
|
|
||||||
|
#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) {
|
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() {
|
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)) {
|
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||||
// WLEDMM same bus as last time - no need to search again
|
// WLEDMM same bus as last time - no need to search again
|
||||||
lastBus->setPixelColor(pix - laststart, c);
|
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 > 255) cct = 255;
|
||||||
if (cct >= 0) {
|
if (cct >= 0) {
|
||||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
//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);
|
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)) {
|
if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr)) {
|
||||||
// WLEDMM same bus as last time - no need to search again
|
// WLEDMM same bus as last time - no need to search again
|
||||||
return lastBus->getPixelColor(pix - laststart);
|
return lastBus->getPixelColor(pix - laststart);
|
||||||
@@ -866,20 +1014,20 @@ uint32_t IRAM_ATTR BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BusManager::canAllShow() {
|
bool BusManager::canAllShow() const {
|
||||||
for (uint8_t i = 0; i < numBusses; i++) {
|
for (uint8_t i = 0; i < numBusses; i++) {
|
||||||
if (!busses[i]->canShow()) return false;
|
if (!busses[i]->canShow()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bus* BusManager::getBus(uint8_t busNr) {
|
Bus* BusManager::getBus(uint8_t busNr) const {
|
||||||
if (busNr >= numBusses) return nullptr;
|
if (busNr >= numBusses) return nullptr;
|
||||||
return busses[busNr];
|
return busses[busNr];
|
||||||
}
|
}
|
||||||
|
|
||||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
//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;
|
uint_fast16_t len = 0;
|
||||||
for (uint_fast8_t i=0; i<numBusses; i++) len += busses[i]->getLength(); // WLEDMM use fast native types
|
for (uint_fast8_t i=0; i<numBusses; i++) len += busses[i]->getLength(); // WLEDMM use fast native types
|
||||||
return len;
|
return len;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||||
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||||
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
|
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
|
||||||
|
//extern volatile bool previousBufferFree; // experimental
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Class for addressing various light types
|
* Class for addressing various light types
|
||||||
@@ -11,6 +12,27 @@
|
|||||||
|
|
||||||
#include "const.h"
|
#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 GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
||||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||||
#define UNSET_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 bool canShow() { return true; }
|
||||||
virtual void setStatusPixel(uint32_t c) {}
|
virtual void setStatusPixel(uint32_t c) {}
|
||||||
virtual void setPixelColor(uint16_t pix, uint32_t c) = 0;
|
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 setBrightness(uint8_t b, bool immediate=false) { _bri = b; };
|
||||||
virtual void cleanup() = 0;
|
virtual void cleanup() = 0;
|
||||||
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
|
virtual uint8_t getPins(uint8_t* pinArray) const { return 0; }
|
||||||
virtual uint16_t getLength() { return _len; }
|
virtual uint16_t getLength() const { return _len; }
|
||||||
virtual void setColorOrder() {}
|
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 uint8_t skippedLeds() { return 0; }
|
||||||
virtual uint16_t getFrequency() { return 0U; }
|
virtual uint16_t getFrequency() const { return 0U; }
|
||||||
inline uint16_t getStart() { return _start; }
|
inline uint16_t getStart() const { return _start; }
|
||||||
inline void setStart(uint16_t start) { _start = start; }
|
inline void setStart(uint16_t start) { _start = start; }
|
||||||
inline uint8_t getType() { return _type; }
|
inline uint8_t getType() const { return _type; }
|
||||||
inline bool isOk() { return _valid; }
|
inline bool isOk() const { return _valid; }
|
||||||
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
inline bool isOffRefreshRequired() const { return _needsRefresh; }
|
||||||
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
bool containsPixel(uint16_t pix) const { return pix >= _start && pix < _start+_len; }
|
||||||
virtual uint16_t getMaxPixels() { return MAX_LEDS_PER_BUS; };
|
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;
|
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool hasWhite() { return Bus::hasWhite(_type); }
|
virtual bool hasWhite() const { return Bus::hasWhite(_type); }
|
||||||
static bool hasWhite(uint8_t 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_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_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
|
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool hasCCT() {
|
virtual bool hasCCT() const {
|
||||||
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
||||||
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
||||||
return false;
|
return false;
|
||||||
@@ -157,7 +179,7 @@ class Bus {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
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 void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||||
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||||
|
|
||||||
@@ -175,7 +197,7 @@ class Bus {
|
|||||||
static int16_t _cct;
|
static int16_t _cct;
|
||||||
static uint8_t _cctBlend;
|
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();
|
inline void show();
|
||||||
|
|
||||||
bool canShow();
|
bool canShow() const;
|
||||||
|
|
||||||
void setBrightness(uint8_t b, bool immediate);
|
void setBrightness(uint8_t b, bool immediate);
|
||||||
|
|
||||||
@@ -193,25 +215,25 @@ class BusDigital : public Bus {
|
|||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
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;
|
return _colorOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getLength() {
|
uint16_t getLength() const {
|
||||||
return _len - _skip;
|
return _len - _skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
void setColorOrder(uint8_t colorOrder);
|
void setColorOrder(uint8_t colorOrder);
|
||||||
|
|
||||||
uint8_t skippedLeds() {
|
uint8_t skippedLeds() const {
|
||||||
return _skip;
|
return _skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getFrequency() { return _frequencykHz; }
|
uint16_t getFrequency() const { return _frequencykHz; }
|
||||||
|
|
||||||
void reinit();
|
void reinit();
|
||||||
|
|
||||||
@@ -239,13 +261,13 @@ class BusPwm : public Bus {
|
|||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
//does no index check
|
//does no index check
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
uint32_t getPixelColor(uint16_t pix) const;
|
||||||
|
|
||||||
void show();
|
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() {
|
void cleanup() {
|
||||||
deallocatePins();
|
deallocatePins();
|
||||||
@@ -273,11 +295,11 @@ class BusOnOff : public Bus {
|
|||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
void setPixelColor(uint16_t pix, uint32_t c);
|
||||||
|
|
||||||
uint32_t getPixelColor(uint16_t pix);
|
uint32_t getPixelColor(uint16_t pix) const;
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||||
@@ -297,24 +319,24 @@ class BusNetwork : public Bus {
|
|||||||
public:
|
public:
|
||||||
BusNetwork(BusConfig &bc);
|
BusNetwork(BusConfig &bc);
|
||||||
|
|
||||||
uint16_t getMaxPixels() override { return 4096; };
|
uint16_t getMaxPixels() const override { return 4096; };
|
||||||
bool hasRGB() { return true; }
|
bool hasRGB() const { return true; }
|
||||||
bool hasWhite() { return _rgbw; }
|
bool hasWhite() const { return _rgbw; }
|
||||||
|
|
||||||
void setPixelColor(uint16_t pix, uint32_t c);
|
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();
|
void show();
|
||||||
|
|
||||||
bool canShow() {
|
bool canShow() const {
|
||||||
// this should be a return value from UDP routine if it is still sending data out
|
// this should be a return value from UDP routine if it is still sending data out
|
||||||
return !_broadcastLock;
|
return !_broadcastLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getPins(uint8_t* pinArray);
|
uint8_t getPins(uint8_t* pinArray) const;
|
||||||
|
|
||||||
uint16_t getLength() {
|
uint16_t getLength() const {
|
||||||
return _len;
|
return _len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,36 +360,26 @@ class BusHub75Matrix : public Bus {
|
|||||||
public:
|
public:
|
||||||
BusHub75Matrix(BusConfig &bc);
|
BusHub75Matrix(BusConfig &bc);
|
||||||
|
|
||||||
uint16_t getMaxPixels() override { return 4096; };
|
uint16_t getMaxPixels() const override { return 4096; };
|
||||||
|
|
||||||
bool hasRGB() { return true; }
|
bool hasRGB() const override { return true; }
|
||||||
bool hasWhite() { return false; }
|
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() {
|
void show(void) override;
|
||||||
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 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;
|
pinArray[0] = mxconfig.chain_length;
|
||||||
return 1;
|
return 1;
|
||||||
} // Fake value due to keep finaliseInit happy
|
} // Fake value due to keep finaliseInit happy
|
||||||
|
|
||||||
void deallocatePins();
|
void deallocatePins();
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup(void) override;
|
||||||
deallocatePins();
|
|
||||||
fourScanPanel = nullptr;
|
|
||||||
// delete fourScanPanel;
|
|
||||||
delete display;
|
|
||||||
_valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~BusHub75Matrix() {
|
~BusHub75Matrix() {
|
||||||
cleanup();
|
cleanup();
|
||||||
@@ -377,8 +389,9 @@ class BusHub75Matrix : public Bus {
|
|||||||
MatrixPanel_I2S_DMA *display = nullptr;
|
MatrixPanel_I2S_DMA *display = nullptr;
|
||||||
VirtualMatrixPanel *fourScanPanel = nullptr;
|
VirtualMatrixPanel *fourScanPanel = nullptr;
|
||||||
HUB75_I2S_CFG mxconfig;
|
HUB75_I2S_CFG mxconfig;
|
||||||
uint8_t r, g, b, x, y;
|
unsigned _panelWidth = 0;
|
||||||
|
CRGB *_ledBuffer = nullptr;
|
||||||
|
byte *_ledsDirty = nullptr;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -387,7 +400,7 @@ class BusManager {
|
|||||||
BusManager() {};
|
BusManager() {};
|
||||||
|
|
||||||
//utility to get the approx. memory usage of a given BusConfig
|
//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);
|
int add(BusConfig &bc);
|
||||||
|
|
||||||
@@ -406,12 +419,12 @@ class BusManager {
|
|||||||
|
|
||||||
uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t pix); // WLEDMM attribute added
|
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())
|
//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) {
|
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
||||||
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||||
@@ -421,7 +434,7 @@ class BusManager {
|
|||||||
return colorOrderMap;
|
return colorOrderMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t getNumBusses() {
|
inline uint8_t getNumBusses() const {
|
||||||
return numBusses;
|
return numBusses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +447,7 @@ class BusManager {
|
|||||||
unsigned laststart = 0;
|
unsigned laststart = 0;
|
||||||
unsigned lastend = 0;
|
unsigned lastend = 0;
|
||||||
|
|
||||||
inline uint8_t getNumVirtualBusses() {
|
inline uint8_t getNumVirtualBusses() const {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||||
return j;
|
return j;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/*
|
/*
|
||||||
* color blend function
|
* 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(blend == 0) return color1;
|
||||||
if (color1 == color2) return color1; // WLEDMM shortcut
|
if (color1 == color2) return color1; // WLEDMM shortcut
|
||||||
const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
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
|
* 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
|
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)
|
// 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!
|
// 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()
|
//remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor()
|
||||||
static byte correctionRGB[4] = {0,0,0,0};
|
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);
|
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 (!gammaCorrectCol || (value == 0) || (value == 255)) return value;
|
||||||
if ((value == 0) || (value == 255)) return value;
|
if ((value == 0) || (value == 255)) return value;
|
||||||
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value;
|
if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value;
|
||||||
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal);
|
||||||
return gammaTinv[value];
|
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
|
// wleDMM end
|
||||||
|
|
||||||
uint8_t gamma8_cal(uint8_t b, float gamma)
|
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
|
// 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];
|
return gammaT[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for color gamma correction
|
// used for color gamma correction
|
||||||
uint32_t gamma32(uint32_t color)
|
uint32_t __attribute__((hot)) gamma32(uint32_t color)
|
||||||
{
|
{
|
||||||
if (!gammaCorrectCol) return color;
|
if (!gammaCorrectCol) return color;
|
||||||
uint8_t w = W(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_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
|
||||||
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
|
||||||
#define ERR_LOW_AJAX_MEM 36 // WLEDMM: low memory (oappend)
|
#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
|
// Timer mode types
|
||||||
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
|
||||||
@@ -480,7 +481,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
||||||
|
#if !defined(MIN_HEAP_SIZE)
|
||||||
#define MIN_HEAP_SIZE 8192
|
#define MIN_HEAP_SIZE 8192
|
||||||
|
#endif
|
||||||
|
|
||||||
// Maximum size of node map (list of other WLED instances)
|
// Maximum size of node map (list of other WLED instances)
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
|
|||||||
@@ -2008,6 +2008,9 @@ function readState(s,command=false)
|
|||||||
case 36:
|
case 36:
|
||||||
errstr = "Low Memory (oappend buffer).";
|
errstr = "Low Memory (oappend buffer).";
|
||||||
break;
|
break;
|
||||||
|
case 37:
|
||||||
|
errstr = "no memory for LEDs buffer.";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
showToast('Error ' + s.error + ": " + errstr, true);
|
showToast('Error ' + s.error + ": " + errstr, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ void DMXInput::updateInternal()
|
|||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) {
|
if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) {
|
||||||
if (!packet.err) {
|
if (!packet.err) {
|
||||||
|
if(!connected) {
|
||||||
|
USER_PRINTLN("DMX Input - connected");
|
||||||
|
}
|
||||||
connected = true;
|
connected = true;
|
||||||
identify = isIdentifyOn();
|
identify = isIdentifyOn();
|
||||||
if (!packet.is_rdm) {
|
if (!packet.is_rdm) {
|
||||||
@@ -199,6 +202,9 @@ void DMXInput::updateInternal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(connected) {
|
||||||
|
USER_PRINTLN("DMX Input - disconnected");
|
||||||
|
}
|
||||||
connected = false;
|
connected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ void calcGammaTable(float gamma);
|
|||||||
uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure
|
uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure
|
||||||
uint32_t __attribute__((pure)) gamma32(uint32_t); // 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
|
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
|
//dmx_output.cpp
|
||||||
void initDMXOutput();
|
void initDMXOutput();
|
||||||
@@ -249,7 +250,7 @@ void refreshNodeList();
|
|||||||
void sendSysInfoUDP();
|
void sendSysInfoUDP();
|
||||||
|
|
||||||
//network.cpp
|
//network.cpp
|
||||||
int getSignalQuality(int rssi);
|
int getSignalQuality(int rssi) __attribute__((const));
|
||||||
void WiFiEvent(WiFiEvent_t event);
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
|
|
||||||
//um_manager.cpp
|
//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 sappend(char stype, const char* key, int val);
|
||||||
void sappends(char stype, const char* key, char* val);
|
void sappends(char stype, const char* key, char* val);
|
||||||
void prepareHostname(char* hostname);
|
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);
|
bool requestJSONBufferLock(uint8_t module=255);
|
||||||
void releaseJSONBufferLock();
|
void releaseJSONBufferLock();
|
||||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||||
@@ -409,13 +410,14 @@ void clearEEPROM();
|
|||||||
//wled_math.cpp
|
//wled_math.cpp
|
||||||
#ifndef WLED_USE_REAL_MATH
|
#ifndef WLED_USE_REAL_MATH
|
||||||
template <typename T> T atan_t(T x);
|
template <typename T> T atan_t(T x);
|
||||||
float cos_t(float phi);
|
float cos_t(float phi) __attribute__((const));
|
||||||
float sin_t(float x);
|
float sin_t(float x) __attribute__((const));
|
||||||
float tan_t(float x);
|
float tan_t(float x) __attribute__((const));
|
||||||
float acos_t(float x);
|
float acos_t(float x);
|
||||||
float asin_t(float x);
|
float asin_t(float x);
|
||||||
float floor_t(float x);
|
float atan_t(float x) __attribute__((const));
|
||||||
float fmod_t(float num, float denom);
|
float floor_t(float x) __attribute__((const));
|
||||||
|
float fmod_t(float num, float denom) __attribute__((const));
|
||||||
#else
|
#else
|
||||||
#include <math.h> // WLEDMM use "float" variants
|
#include <math.h> // WLEDMM use "float" variants
|
||||||
#define sin_t sinf
|
#define sin_t sinf
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void toggleOnOff()
|
|||||||
|
|
||||||
|
|
||||||
//scales the brightness with the briMultiplier factor
|
//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
|
if (briMultiplier == 100) return(in); // WLEDMM shortcut
|
||||||
uint_fast16_t val = ((uint_fast16_t)in*(uint_fast16_t)briMultiplier)/100; // WLEDMM
|
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
|
// 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,
|
5, // eth_power,
|
||||||
23, // eth_mdc,
|
23, // eth_mdc,
|
||||||
18, // eth_mdio,
|
18, // eth_mdio,
|
||||||
|
|||||||
@@ -723,7 +723,7 @@ bool PinManagerClass::joinWire(int8_t pinSDA, int8_t pinSCL) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Check if supplied GPIO is ok to use
|
// 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
|
#ifdef ESP32
|
||||||
if (digitalPinIsValid(gpio)) {
|
if (digitalPinIsValid(gpio)) {
|
||||||
@@ -757,7 +757,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
|||||||
return false;
|
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 (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
|
||||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||||
return ownerTag[gpio];
|
return ownerTag[gpio];
|
||||||
|
|||||||
@@ -125,9 +125,9 @@ class PinManagerClass {
|
|||||||
// will return true for reserved pins
|
// will return true for reserved pins
|
||||||
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
||||||
// will return false for reserved pins
|
// 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
|
// WLEDMM begin
|
||||||
String getOwnerText(PinOwner tag); // WLEDMM - return PIN owner tag as text
|
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 */
|
/* low level functions to convert to and from system time */
|
||||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
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++"
|
} // extern "C++"
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|||||||
@@ -1220,7 +1220,7 @@ void WLED::handleConnection()
|
|||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
// 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 ((!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
|
uint32_t heap = ESP.getFreeHeap(); // WLEDMM works better on -S2
|
||||||
#else
|
#else
|
||||||
uint32_t heap = heap_caps_get_largest_free_block(0x1800); // WLEDMM: This is a better metric for free heap.
|
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)
|
// 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.
|
// 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_
|
#define _MoonModules_WLED_
|
||||||
@@ -928,9 +928,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// boot starts here
|
// boot starts here
|
||||||
void setup();
|
void setup() __attribute__((used));
|
||||||
|
|
||||||
void loop();
|
void loop() __attribute__((used));
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void beginStrip();
|
void beginStrip();
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ void esp_heap_trace_free_hook(void* ptr)
|
|||||||
unsigned long lastMillis = 0; //WLEDMM
|
unsigned long lastMillis = 0; //WLEDMM
|
||||||
unsigned long loopCounter = 0; //WLEDMM
|
unsigned long loopCounter = 0; //WLEDMM
|
||||||
|
|
||||||
|
void setup() __attribute__((used)); // needed for -flto
|
||||||
void setup() {
|
void setup() {
|
||||||
#ifdef WLED_DEBUG_HEAP
|
#ifdef WLED_DEBUG_HEAP
|
||||||
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
|
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
|
||||||
@@ -68,6 +69,7 @@ void setup() {
|
|||||||
WLED::instance().setup();
|
WLED::instance().setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loop() __attribute__((used)); // needed for -flto
|
||||||
void loop() {
|
void loop() {
|
||||||
//WLEDMM show loops per second
|
//WLEDMM show loops per second
|
||||||
loopCounter++;
|
loopCounter++;
|
||||||
|
|||||||
Reference in New Issue
Block a user