Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new mapping mode "Waterfall" #197

Draft
wants to merge 6 commits into
base: mdev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ typedef enum mapping1D2D {
M12_jMap = 4, //WLEDMM jMap
M12_sCircle = 5, //WLEDMM Circle
M12_sBlock = 6, //WLEDMM Block
M12_sPinwheel = 7 //WLEDMM Pinwheel
M12_sPinwheel = 7, //WLEDMM Pinwheel
M12_sWaterfall = 8 //WLEDMM Waterfall
} mapping1D2D_t;

// segment, 72 bytes
Expand Down Expand Up @@ -424,6 +425,8 @@ typedef struct Segment {

bool _isSimpleSegment = false; // simple = no grouping or spacing - mirror, transpose or reverse allowed
bool _isSuperSimpleSegment = false; // superSimple = no grouping or spacing, no mirror - only transpose or reverse allowed
bool _is2Deffect = false; // tells us if the strip is running a real 2D effect

#ifdef WLEDMM_FASTPATH
// WLEDMM cache some values that won't change while drawing a frame
bool _isValid2D = false;
Expand Down
22 changes: 22 additions & 0 deletions wled00/FX_2Dfcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,29 @@ void Segment::startFrame(void) {
#if 0 && defined(WLED_ENABLE_HUB75MATRIX)
_firstFill = true; // dirty HACK
#endif
#else
uint16_t _2dHeight = calc_virtualHeight();
uint16_t _2dWidth = is2D() ? calc_virtualWidth() : calc_virtualLength();
#endif

// WLEDMM Make sure we don't scroll any real 2D effect
if (!isActive()) _is2Deffect = is2D();
else {
_is2Deffect = (strstr(strip.getModeData(mode), ";2") != nullptr); // effect data string contains ";2" --> 2d
if (is2D() && (strstr(strip.getModeData(mode),";12") != nullptr)) _is2Deffect = true;// effect data string contains ";12" --> 1d 2d --> maybe 2D
if (is2D() && ((mode == 0) || (mode >= strip.getModeCount()))) _is2Deffect = true;
if (is2D() && nrOfVStrips() > 1) _is2Deffect = true; // 1.5d effect on virtual strips => 2D
if (!strip.isMatrix) _is2Deffect = false; // not running in 2D mode
}

// WLEDMM Waterfall mapping
if (!_is2Deffect && (map1D2D == M12_pBar) && reverse) { // WLEDMM Waterfall = bar + reverse
if (!ledsrgb || (ledsrgbSize == 0)) setUpLeds(); // create segment buffer if not set up already ==> 30% faster, and prevents interference with other segments.
for (unsigned myRow = _2dHeight-1; myRow > 0; myRow--)
for (unsigned myCol = 0; myCol < _2dWidth; myCol++) {
setPixelColorXY(myCol, myRow, getPixelColorXY(int(myCol), int(myRow)-1));
}
}
}
// WLEDMM end

Expand Down
62 changes: 49 additions & 13 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,11 @@ uint16_t Segment::nrOfVStrips() const {
uint16_t vLen = 1;
#ifndef WLED_DISABLE_2D
if (is2D()) {
switch (map1D2D) {

mapping1D2D_t map1d2d = mapping1D2D_t(map1D2D);
if ((map1d2d == M12_pBar) && reverse) map1d2d = M12_sWaterfall; // WLEDMM hack to support waterfall mapping (= "Bar" + "reverse")

switch (map1d2d) {
case M12_pBar:
vLen = calc_virtualWidth();
break;
Expand All @@ -654,6 +658,9 @@ uint16_t Segment::nrOfVStrips() const {
case M12_sBlock: //WLEDMM
vLen = (calc_virtualWidth() + calc_virtualHeight()) / 8; // take half of the average width
break;
default:
vLen = 1; // WLEDMM other modes do not support virtual strips
break;
}
}
#endif
Expand Down Expand Up @@ -865,7 +872,14 @@ uint16_t Segment::calc_virtualLength() const {
uint16_t vW = calc_virtualWidth();
uint16_t vH = calc_virtualHeight();
uint16_t vLen = vW * vH; // use all pixels from segment
switch (map1D2D) {

mapping1D2D_t map1d2d = mapping1D2D_t(map1D2D);
if ((map1d2d == M12_pBar) && reverse) map1d2d = M12_sWaterfall; // WLEDMM hack to support waterfall mapping (= "Bar" + "reverse")

switch (map1d2d) {
case M12_sWaterfall:
vLen = vW;
break;
case M12_pBar:
vLen = vH;
break;
Expand Down Expand Up @@ -896,6 +910,9 @@ uint16_t Segment::calc_virtualLength() const {
case M12_sPinwheel:
vLen = getPinwheelLength(vW, vH);
break;
default: // M12_Pixels uses all available pixels
vLen = vW * vH; // use all pixels from segment
break;
}
return vLen;
}
Expand Down Expand Up @@ -946,7 +963,14 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co
if (is2D()) {
uint16_t vH = virtualHeight(); // segment height in logical pixels
uint16_t vW = virtualWidth();
switch (map1D2D) {

mapping1D2D_t map1d2d = mapping1D2D_t(map1D2D);
if ((map1d2d == M12_pBar) && reverse) map1d2d = M12_sWaterfall; // WLEDMM hack to support waterfall mapping (= "Bar" + "reverse")

switch (map1d2d) {
case M12_sWaterfall:
setPixelColorXY(i % vW, 0, col); // only set first row
break;
case M12_Pixels:
// use all available pixels as a long strip
setPixelColorXY(i % vW, i / vW, col);
Expand Down Expand Up @@ -1218,7 +1242,14 @@ uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const
if (is2D()) {
uint16_t vH = virtualHeight(); // segment height in logical pixels
uint16_t vW = virtualWidth();
switch (map1D2D) {

mapping1D2D_t map1d2d = mapping1D2D_t(map1D2D);
if ((map1d2d == M12_pBar) && reverse) map1d2d = M12_sWaterfall; // WLEDMM hack to support waterfall mapping (= "Bar" + "reverse")

switch (map1d2d) {
case M12_sWaterfall:
return getPixelColorXY(i % vW, 0); // only use first row
break;
case M12_Pixels:
return getPixelColorXY(i % vW, i / vW);
break;
Expand Down Expand Up @@ -1414,7 +1445,8 @@ void __attribute__((hot)) Segment::fill(uint32_t c) {
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D

if (is2D()) {
bool reallyIs2D = _is2Deffect || (is2D() && !(map1D2D == M12_pBar && reverse)); // WLEDMM switch to "1D" mode for Waterfall
if (is2D() && reallyIs2D) {
// pre-calculate scaled color
uint32_t scaled_col = c;
bool simpleSegment = (grouping == 1) && (spacing == 0);
Expand Down Expand Up @@ -1470,8 +1502,9 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) {
*/
void __attribute__((hot)) Segment::fade_out(uint8_t rate) {
if (!isActive()) return; // not active
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
bool reallyIs2D = _is2Deffect || (is2D() && !(map1D2D == M12_pBar && reverse)); // WLEDMM switch to "1D" mode for Bar or waterfall
const uint_fast16_t cols = reallyIs2D ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = reallyIs2D ? virtualHeight() : 1; // must be 1 for 1D

uint_fast8_t fadeRate = (255-rate) >> 1;
float mappedRate_r = 1.0f / (float(fadeRate) +1.1f); // WLEDMM use reciprocal 1/mappedRate -> faster on non-FPU chips
Expand All @@ -1483,7 +1516,7 @@ void __attribute__((hot)) Segment::fade_out(uint8_t rate) {
int b2 = B(color2);

for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
uint32_t color = is2D() ? getPixelColorXY(int(x), int(y)) : getPixelColor(int(x));
uint32_t color = reallyIs2D ? getPixelColorXY(int(x), int(y)) : getPixelColor(int(x));
if (color == color2) continue; // WLEDMM speedup - pixel color = target color, so nothing to do
int w1 = W(color);
int r1 = R(color);
Expand All @@ -1503,7 +1536,7 @@ void __attribute__((hot)) Segment::fade_out(uint8_t rate) {
uint32_t colorNew = RGBW32(r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta); // WLEDMM

if (colorNew != color) { // WLEDMM speedup - do not repaint the same color
if (is2D()) setPixelColorXY(int(x), int(y), colorNew);
if (reallyIs2D) setPixelColorXY(int(x), int(y), colorNew);
else setPixelColor(int(x), colorNew);
}
}
Expand All @@ -1512,12 +1545,14 @@ void __attribute__((hot)) Segment::fade_out(uint8_t rate) {
// fades all pixels to black using nscale8()
void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) {
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D
bool reallyIs2D = _is2Deffect || (is2D() && !(map1D2D == M12_pBar && reverse)); // WLEDMM switch to "1D" mode for Bar or waterfall
const uint_fast16_t cols = reallyIs2D ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = reallyIs2D ? virtualHeight() : 1; // must be 1 for 1D

const uint_fast8_t scaledown = 255-fadeBy; // WLEDMM faster to pre-compute this

// WLEDMM minor optimization
if(is2D()) {
if(reallyIs2D) {
for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
uint32_t cc = getPixelColorXY(int(x),int(y)); // WLEDMM avoid RGBW32 -> CRGB -> RGBW32 conversion
uint32_t cc2 = color_fade(cc, scaledown); // fade
Expand All @@ -1539,7 +1574,8 @@ void __attribute__((hot)) Segment::fadeToBlackBy(uint8_t fadeBy) {
void __attribute__((hot)) Segment::blur(uint8_t blur_amount, bool smear) {
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
#ifndef WLED_DISABLE_2D
if (is2D()) {
bool reallyIs2D = _is2Deffect || (is2D() && !(map1D2D == M12_pBar && reverse)); // WLEDMM switch to "1D" mode for Bar or waterfall
if (reallyIs2D) {
// compatibility with 2D
const uint_fast32_t cols = virtualWidth();
const uint_fast32_t rows = virtualHeight();
Expand Down
3 changes: 3 additions & 0 deletions wled00/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
uint16_t of = seg.offset;
uint8_t soundSim = elem["si"] | seg.soundSim;
uint8_t map1D2D = elem["m12"] | seg.map1D2D;
if (map1D2D > 7) map1D2D = M12_pBar; // WLEDMM fix for "waterfall" mapping which is out of range 0-7

//WLEDMM jMap
if (map1D2D == M12_jMap && !seg.jMap)
Expand Down Expand Up @@ -327,6 +328,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
uint8_t oldMap1D2D = seg.map1D2D;
if (oldMap1D2D > 7) oldMap1D2D = M12_pBar; // WLEDMM fix for "waterfall" mapping which is out of range 0-7

seg.map1D2D = M12_Pixels; // no mapping
// WLEDMM begin - we need to init segment caches before putting any pixels
if (strip.isServicing()) {
Expand Down
Loading