WLED 2D matrix support.
- Added 2 sample effects to UI. - 2D segment details. - 1D effect upscaling to 2D. - 2D setPixelColorXY() and other utility functions - Arbitrary panel position & oritentation. - 2D settings with physical to logical mapping. - Bump version.
This commit is contained in:
parent
9f71a6ab18
commit
f0d36fd769
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.13.2-bl0",
|
||||
"version": "0.14.0-bl0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.13.2-bl0",
|
||||
"version": "0.14.0-bl0",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
|
@ -366,6 +366,18 @@ writeChunks(
|
||||
"</script><script src=\"/settings/s.js?p=8\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_2D.htm",
|
||||
name: "PAGE_settings_2D",
|
||||
method: "gzip",
|
||||
filter: "html-minify",
|
||||
mangle: (str) =>
|
||||
str
|
||||
.replace(
|
||||
/function GetV().*\<\/script\>/gms,
|
||||
"</script><script src=\"/settings/s.js?p=10\"></script>"
|
||||
)
|
||||
},
|
||||
{
|
||||
file: "settings_pin.htm",
|
||||
name: "PAGE_settings_pin",
|
||||
|
@ -2346,7 +2346,7 @@ uint16_t WS2812FX::mode_ripple_rainbow(void) {
|
||||
// incandescent bulbs change color as they get dim down.
|
||||
#define COOL_LIKE_INCANDESCENT 1
|
||||
|
||||
CRGB IRAM_ATTR WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat)
|
||||
CRGB WS2812FX::twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat)
|
||||
{
|
||||
// Overall twinkle speed (changed)
|
||||
uint16_t ticks = ms / SEGENV.aux0;
|
||||
@ -4227,3 +4227,70 @@ uint16_t WS2812FX::mode_aurora(void) {
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//*************************** 2D routines ***********************************
|
||||
|
||||
// sample 2D routine
|
||||
uint16_t WS2812FX::mode_2DBlackHole_A() { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
uint16_t dataSize = sizeof(CRGB) * w * h;
|
||||
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
CRGB *leds = reinterpret_cast<CRGB*>(SEGENV.data);
|
||||
|
||||
uint16_t x, y;
|
||||
|
||||
// initialize on first call
|
||||
if (SEGENV.call == 0) {
|
||||
for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
|
||||
leds[x + y * w] = CRGB::Black;
|
||||
}
|
||||
}
|
||||
|
||||
fadeToBlackBy(32, leds); // create fading trails
|
||||
float t = (float)(millis())/128;
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(10 , 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
leds[x + y * w] += CHSV(i*32, 255, 255);
|
||||
}
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.c2x>>3, w/4, w - 1 - w/4, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(SEGMENT.c3x>>3, h/4, h - 1 - h/4, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
leds[x + y * w] += CHSV(i*32, 255, 255);
|
||||
}
|
||||
leds[w/2 * (1 + h)] = CHSV(0,0,255);
|
||||
blur2d(16, leds);
|
||||
|
||||
for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
|
||||
uint16_t o = x + y * w;
|
||||
setPixelColorXY(x, y, leds[o]);
|
||||
}
|
||||
return FRAMETIME;
|
||||
} // mode_2DBlackHole()
|
||||
|
||||
// same as above not using leds[]
|
||||
uint16_t WS2812FX::mode_2DBlackHole_B() { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
uint16_t x, y;
|
||||
|
||||
fade_out2D(32); // create fading trails
|
||||
float t = (float)(millis())/128;
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(10 , 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x,y)) + CHSV(i*32, 255, 255));
|
||||
}
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
x = beatsin8(SEGMENT.c2x>>3, w/4, w - 1 - w/4, 0, ((i % 2) ? 128 : 0) + t * i);
|
||||
y = beatsin8(SEGMENT.c3x>>3, h/4, h - 1 - h/4, 0, ((i % 2) ? 192 : 64) + t * i);
|
||||
setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x,y)) + CHSV(i*32, 255, 255));
|
||||
}
|
||||
setPixelColorXY(w/2, h/2, WHITE);
|
||||
blur2d(16);
|
||||
return FRAMETIME;
|
||||
} // mode_2DBlackHole()
|
||||
|
||||
|
150
wled00/FX.h
150
wled00/FX.h
@ -38,6 +38,9 @@
|
||||
#define DEFAULT_SPEED (uint8_t)128
|
||||
#define DEFAULT_INTENSITY (uint8_t)128
|
||||
#define DEFAULT_COLOR (uint32_t)0xFFAA00
|
||||
#define DEFAULT_C1 (uint8_t)128
|
||||
#define DEFAULT_C2 (uint8_t)128
|
||||
#define DEFAULT_C3 (uint8_t)128
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@ -109,6 +112,9 @@
|
||||
// bit 0: segment is selected
|
||||
#define NO_OPTIONS (uint8_t)0x00
|
||||
#define TRANSITIONAL (uint8_t)0x80
|
||||
#define TRANSPOSED (uint8_t)0x40 // rotated 90deg & reversed
|
||||
#define REVERSE_Y_2D (uint8_t)0x20
|
||||
#define MIRROR_Y_2D (uint8_t)0x10
|
||||
#define MIRROR (uint8_t)0x08
|
||||
#define SEGMENT_ON (uint8_t)0x04
|
||||
#define REVERSE (uint8_t)0x02
|
||||
@ -118,8 +124,11 @@
|
||||
#define IS_SEGMENT_ON ((SEGMENT.options & SEGMENT_ON ) == SEGMENT_ON )
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
|
||||
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
|
||||
#define IS_REVERSE_Y_2D ((SEGMENT.options & REVERSE_Y_2D) == REVERSE_Y_2D)
|
||||
#define IS_MIRROR_Y_2D ((SEGMENT.options & MIRROR_Y_2D ) == MIRROR_Y_2D )
|
||||
#define IS_TRANSPOSED ((SEGMENT.options & TRANSPOSED ) == TRANSPOSED )
|
||||
|
||||
#define MODE_COUNT 118
|
||||
#define MODE_COUNT 120
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
@ -239,6 +248,8 @@
|
||||
#define FX_MODE_BLENDS 115
|
||||
#define FX_MODE_TV_SIMULATOR 116
|
||||
#define FX_MODE_DYNAMIC_SMOOTH 117
|
||||
#define FX_MODE_BLACK_HOLE_A 118
|
||||
#define FX_MODE_BLACK_HOLE_B 119
|
||||
|
||||
|
||||
class WS2812FX {
|
||||
@ -249,24 +260,35 @@ class WS2812FX {
|
||||
|
||||
static WS2812FX* instance;
|
||||
|
||||
// segment parameters
|
||||
public:
|
||||
typedef struct Segment { // 34 (35 in memory) bytes
|
||||
uint16_t start;
|
||||
uint16_t stop; //segment invalid if stop == 0
|
||||
|
||||
// segment parameters
|
||||
typedef struct Segment { // 35 (36 in memory) bytes
|
||||
uint16_t start; // start index / start X coordinate 2D (left)
|
||||
uint16_t stop; // stop index / stop X coordinate 2D (right); segment is invalid if stop == 0
|
||||
uint16_t offset;
|
||||
uint8_t speed;
|
||||
uint8_t intensity;
|
||||
uint8_t palette;
|
||||
uint8_t mode;
|
||||
uint8_t options; //bit pattern: msb first: transitional needspixelstate tbd tbd (paused) on reverse selected
|
||||
uint16_t options; //bit pattern: msb first: [transposed mirrorY reverseY] transitional (tbd) paused needspixelstate mirrored on reverse selected
|
||||
uint8_t grouping, spacing;
|
||||
uint8_t opacity;
|
||||
uint32_t colors[NUM_COLORS];
|
||||
uint8_t cct; //0==1900K, 255==10091K
|
||||
uint8_t _capabilities;
|
||||
uint8_t c1x, c2x, c3x; // custom FX parameters
|
||||
uint8_t c1x, c2x, c3x; // custom FX parameters
|
||||
uint16_t startY; // start Y coodrinate 2D (top)
|
||||
uint16_t stopY; // stop Y coordinate 2D (bottom)
|
||||
char *name;
|
||||
inline bool getOption(uint8_t n) { return ((options >> n) & 0x01); }
|
||||
inline bool isSelected() { return getOption(0); }
|
||||
inline bool isActive() { return stop > start; }
|
||||
inline uint16_t width() { return options & TRANSPOSED ? stopY - startY : stop - start; }
|
||||
inline uint16_t height() { return options & TRANSPOSED ? stop - start : stopY - startY; }
|
||||
inline uint16_t length() { return width(); }
|
||||
inline uint16_t groupLength() { return grouping + spacing; }
|
||||
inline uint8_t getLightCapabilities() { return _capabilities; }
|
||||
bool setColor(uint8_t slot, uint32_t c, uint8_t segn) { //returns true if changed
|
||||
if (slot >= NUM_COLORS || segn >= MAX_NUM_SEGMENTS) return false;
|
||||
if (c == colors[slot]) return false;
|
||||
@ -291,8 +313,7 @@ class WS2812FX {
|
||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
||||
opacity = o;
|
||||
}
|
||||
void setOption(uint8_t n, bool val, uint8_t segn = 255)
|
||||
{
|
||||
void setOption(uint8_t n, bool val, uint8_t segn = 255) {
|
||||
bool prevOn = false;
|
||||
if (n == SEG_OPTION_ON) {
|
||||
prevOn = getOption(SEG_OPTION_ON);
|
||||
@ -300,48 +321,31 @@ class WS2812FX {
|
||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (val) {
|
||||
options |= 0x01 << n;
|
||||
} else
|
||||
{
|
||||
options &= ~(0x01 << n);
|
||||
}
|
||||
|
||||
if (val) options |= 0x01 << n;
|
||||
else options &= ~(0x01 << n);
|
||||
if (n == SEG_OPTION_ON && val && !prevOn) { //fade on
|
||||
ColorTransition::startTransition(0, colors[0], instance->_transitionDur, segn, 0);
|
||||
}
|
||||
}
|
||||
bool getOption(uint8_t n)
|
||||
{
|
||||
return ((options >> n) & 0x01);
|
||||
uint16_t virtualWidth() {
|
||||
uint16_t groupLen = groupLength();
|
||||
uint16_t vWidth = (width() + groupLen - 1) / groupLen;
|
||||
if (options & MIRROR) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vWidth;
|
||||
}
|
||||
inline bool isSelected()
|
||||
{
|
||||
return getOption(0);
|
||||
uint16_t virtualHeight() {
|
||||
uint16_t groupLen = groupLength();
|
||||
uint16_t vHeight = (height() + groupLen - 1) / groupLen;
|
||||
if (options & MIRROR_Y_2D) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vHeight;
|
||||
}
|
||||
inline bool isActive()
|
||||
{
|
||||
return stop > start;
|
||||
}
|
||||
inline uint16_t length()
|
||||
{
|
||||
return stop - start;
|
||||
}
|
||||
inline uint16_t groupLength()
|
||||
{
|
||||
return grouping + spacing;
|
||||
}
|
||||
uint16_t virtualLength()
|
||||
{
|
||||
uint16_t virtualLength() {
|
||||
uint16_t groupLen = groupLength();
|
||||
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
||||
if (options & MIRROR)
|
||||
vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
if (options & MIRROR) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
return vLength;
|
||||
}
|
||||
uint8_t differs(Segment& b);
|
||||
inline uint8_t getLightCapabilities() {return _capabilities;}
|
||||
void refreshLightCapabilities();
|
||||
} segment;
|
||||
|
||||
@ -610,6 +614,8 @@ class WS2812FX {
|
||||
_mode[FX_MODE_BLENDS] = &WS2812FX::mode_blends;
|
||||
_mode[FX_MODE_TV_SIMULATOR] = &WS2812FX::mode_tv_simulator;
|
||||
_mode[FX_MODE_DYNAMIC_SMOOTH] = &WS2812FX::mode_dynamic_smooth;
|
||||
_mode[FX_MODE_BLACK_HOLE_A] = &WS2812FX::mode_2DBlackHole_A;
|
||||
_mode[FX_MODE_BLACK_HOLE_B] = &WS2812FX::mode_2DBlackHole_B;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
@ -637,7 +643,7 @@ class WS2812FX {
|
||||
setTransitionMode(bool t),
|
||||
calcGammaTable(float),
|
||||
trigger(void),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX, uint16_t startY=0, uint16_t stopY=0),
|
||||
setMainSegmentId(uint8_t n),
|
||||
restartRuntime(),
|
||||
resetSegments(),
|
||||
@ -835,6 +841,62 @@ class WS2812FX {
|
||||
mode_tv_simulator(void),
|
||||
mode_dynamic_smooth(void);
|
||||
|
||||
// 2D support (panels)
|
||||
bool
|
||||
isMatrix = false;
|
||||
|
||||
uint8_t
|
||||
hPanels = 1,
|
||||
vPanels = 1;
|
||||
|
||||
uint16_t
|
||||
panelH = 8,
|
||||
panelW = 8,
|
||||
matrixWidth = DEFAULT_LED_COUNT,
|
||||
matrixHeight = 1;
|
||||
|
||||
#define WLED_MAX_PANELS 64
|
||||
typedef struct panel_bitfield_t {
|
||||
unsigned char
|
||||
bottomStart : 1, // starts at bottom?
|
||||
rightStart : 1, // starts on right?
|
||||
vertical : 1, // is vertical?
|
||||
serpentine : 1; // is serpentine?
|
||||
} Panel;
|
||||
Panel
|
||||
matrix = {0,0,0,0},
|
||||
panel[WLED_MAX_PANELS] = {{0,0,0,0}};
|
||||
|
||||
void
|
||||
setUpMatrix(),
|
||||
setPixelColorXY(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
fill2D(uint32_t),
|
||||
blur1d(fract8 blur_amount, CRGB* leds=nullptr),
|
||||
blur2d(fract8 blur_amount, CRGB* leds=nullptr),
|
||||
blurRows(fract8 blur_amount, CRGB* leds=nullptr),
|
||||
blurColumns(fract8 blur_amount, CRGB* leds=nullptr),
|
||||
fill_solid(const struct CRGB& color, CRGB* leds=nullptr),
|
||||
fade_out2D(uint8_t r),
|
||||
fadeToBlackBy(uint8_t fadeBy, CRGB* leds=nullptr),
|
||||
nscale8(uint8_t scale, CRGB* leds=nullptr),
|
||||
setPixels(CRGB* leds);
|
||||
|
||||
inline void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColorXY(x, y, byte(c>>16), byte(c>>8), byte(c), byte(c>>24)); }
|
||||
inline void setPixelColorXY(uint16_t x, uint16_t y, CRGB &c) { setPixelColorXY(x, y, c.red, c.green, c.blue); }
|
||||
|
||||
uint16_t
|
||||
XY(uint16_t x, uint16_t y, uint8_t seg=255);
|
||||
|
||||
uint32_t
|
||||
getPixelColorXY(uint16_t, uint16_t);
|
||||
|
||||
// 2D modes
|
||||
uint16_t
|
||||
mode_2DBlackHole_A(),
|
||||
mode_2DBlackHole_B();
|
||||
|
||||
// end 2D support
|
||||
|
||||
private:
|
||||
uint32_t crgb_to_col(CRGB fastled);
|
||||
CRGB col_to_crgb(uint32_t);
|
||||
@ -905,9 +967,9 @@ class WS2812FX {
|
||||
uint8_t _segment_index_palette_last = 99;
|
||||
uint8_t _mainSegment;
|
||||
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element
|
||||
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[], capabilities
|
||||
{0, 7, 0, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, 0}
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 27 bytes per element
|
||||
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[], capabilities, custom 1, custom 2, custom 3
|
||||
{0, 7, 0, DEFAULT_SPEED, DEFAULT_INTENSITY, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}, 0, DEFAULT_C1, DEFAULT_C2, DEFAULT_C3, 0, 1}
|
||||
};
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
||||
friend class Segment_runtime;
|
||||
|
349
wled00/FX_2Dfcn.cpp
Normal file
349
wled00/FX_2Dfcn.cpp
Normal file
@ -0,0 +1,349 @@
|
||||
/*
|
||||
FX_2Dfcn.cpp contains all 2D utility functions
|
||||
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2022 Blaz Kristan (https://blaz.at/home)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Parts of the code adapted from WLED Sound Reactive
|
||||
*/
|
||||
#include "wled.h"
|
||||
#include "FX.h"
|
||||
#include "palettes.h"
|
||||
|
||||
// setUpMatrix() - constructs ledmap array from matrix of panels with WxH pixels
|
||||
// this converts physical (possibly irregular) LED arrangement into well defined
|
||||
// array of logical pixels: fist entry corresponds to left-topmost logical pixel
|
||||
// followed by horizontal pixels, when matrixWidth logical pixels are added they
|
||||
// are followed by next row (down) of matrixWidth pixels (and so forth)
|
||||
// note: matrix may be comprised of multiple panels each with different orientation
|
||||
// but ledmap takes care of that. ledmap is constructed upon initialization
|
||||
// so matrix should disable regular ledmap processing
|
||||
void WS2812FX::setUpMatrix() {
|
||||
// erase old ledmap, just in case.
|
||||
if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
customMappingTable = nullptr;
|
||||
customMappingSize = 0;
|
||||
|
||||
if (isMatrix) {
|
||||
matrixWidth = hPanels * panelW;
|
||||
matrixHeight = vPanels * panelH;
|
||||
|
||||
// safety check
|
||||
if (matrixWidth * matrixHeight > MAX_LEDS) {
|
||||
matrixWidth = getLengthTotal();
|
||||
matrixHeight = 1;
|
||||
isMatrix = false;
|
||||
return;
|
||||
}
|
||||
|
||||
customMappingSize = matrixWidth * matrixHeight;
|
||||
customMappingTable = new uint16_t[customMappingSize];
|
||||
|
||||
if (customMappingTable != nullptr) {
|
||||
uint16_t startL; // index in custom mapping array (logical strip)
|
||||
uint16_t startP; // position of 1st pixel of panel on (virtual) strip
|
||||
uint16_t x, y, offset;
|
||||
uint8_t h = matrix.vertical ? vPanels : hPanels;
|
||||
uint8_t v = matrix.vertical ? hPanels : vPanels;
|
||||
|
||||
for (uint8_t j=0, p=0; j<v; j++) {
|
||||
for (uint8_t i=0; i<h; i++, p++) {
|
||||
y = (matrix.vertical ? matrix.rightStart : matrix.bottomStart) ? v - j - 1 : j;
|
||||
x = (matrix.vertical ? matrix.bottomStart : matrix.rightStart) ? h - i - 1 : i;
|
||||
x = matrix.serpentine && j%2 ? h - x - 1 : x;
|
||||
|
||||
startL = (matrix.vertical ? y : x) * panelW + (matrix.vertical ? x : y) * matrixWidth * panelH; // logical index (top-left corner)
|
||||
startP = p * panelW * panelH; // physical index (top-left corner)
|
||||
|
||||
for (uint16_t l=0; l<panelH; l++) {
|
||||
y = panel[h*j + i].bottomStart ? (panelH - l - 1) : l;
|
||||
for (uint16_t k=0; k<panelW; k++) {
|
||||
x = panel[h*j + i].rightStart ? (panelW - k - 1) : k;
|
||||
if (panel[h*j + i].vertical) {
|
||||
y = (panel[h*j + i].serpentine && x%2) ? (panelH - y - 1) : y;
|
||||
offset = y + x * panelH;
|
||||
} else {
|
||||
x = (panel[h*j + i].serpentine && y%2) ? (panelW - x - 1) : x;
|
||||
offset = x + y * panelW;
|
||||
}
|
||||
customMappingTable[startL + k + l * matrixWidth] = startP + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("Matrix ledmap:"));
|
||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
||||
if (!(i%matrixWidth)) DEBUG_PRINTLN();
|
||||
DEBUG_PRINTF("%4d,", customMappingTable[i]);
|
||||
}
|
||||
DEBUG_PRINTLN();
|
||||
#endif
|
||||
} else {
|
||||
// memory allocation error
|
||||
matrixWidth = getLengthTotal();
|
||||
matrixHeight = 1;
|
||||
isMatrix = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// not a matrix set up
|
||||
matrixWidth = getLengthTotal();
|
||||
matrixHeight = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// XY(x,y,seg) - returns an index of segment pixel in a matrix layout
|
||||
// index still needs to undergo ledmap processing to represent actual physical pixel
|
||||
// matrix is always organized by matrixHeight number of matrixWidth pixels from top to bottom, left to right
|
||||
// so: pixel at XY(5,6) in a 2D segment with [start=10, stop=19, startY=20, stopY=29 : 10x10 pixels]
|
||||
// corresponds to pixel with logical index of 847 (0 based) if a 2D segment belongs to a 32x32 matrix.
|
||||
// math: (matrixWidth * (startY + y)) + start + x => (32 * (20+6)) + 10 + 5 = 847
|
||||
uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y, uint8_t seg) {
|
||||
if (seg == 255) seg = _segment_index;
|
||||
x %= _segments[seg].width(); // just in case constrain x (wrap around)
|
||||
y %= _segments[seg].height(); // just in case constrain y (wrap around)
|
||||
return ((_segments[seg].startY + y) * matrixWidth) + _segments[seg].start + x;
|
||||
}
|
||||
|
||||
void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
if (!isMatrix) return; // not a matrix set-up
|
||||
uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment;
|
||||
if (SEGLEN && _bri_t < 255) {
|
||||
r = scale8(r, _bri_t);
|
||||
g = scale8(g, _bri_t);
|
||||
b = scale8(b, _bri_t);
|
||||
w = scale8(w, _bri_t);
|
||||
}
|
||||
uint32_t col = RGBW32(r, g, b, w);
|
||||
|
||||
uint16_t width = _segments[segIdx].virtualWidth(); // segment width in logical pixels
|
||||
uint16_t height = _segments[segIdx].virtualHeight(); // segment height in logical pixels
|
||||
if (_segments[segIdx].options & MIRROR ) width = (width + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
if (_segments[segIdx].options & MIRROR_Y_2D) height = (height + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
if (_segments[segIdx].options & TRANSPOSED ) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||
|
||||
x *= _segments[segIdx].groupLength();
|
||||
y *= _segments[segIdx].groupLength();
|
||||
if (x >= width || y >= height) return; // if pixel would fall out of segment just exit
|
||||
|
||||
for (uint8_t j = 0; j < _segments[segIdx].grouping; j++) { // groupping vertically
|
||||
for (uint8_t g = 0; g < _segments[segIdx].grouping; g++) { // groupping horizontally
|
||||
uint16_t index, xX = (x+g), yY = (y+j);
|
||||
if (xX >= width || yY >= height) continue; // we have reached one dimension's end
|
||||
|
||||
if (_segments[segIdx].options & REVERSE ) xX = width - xX - 1;
|
||||
if (_segments[segIdx].options & REVERSE_Y_2D) yY = height - yY - 1;
|
||||
|
||||
index = XY(xX, yY, segIdx);
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
busses.setPixelColor(index, col);
|
||||
|
||||
if (_segments[segIdx].options & MIRROR) { //set the corresponding horizontally mirrored pixel
|
||||
index = XY(_segments[segIdx].stop - xX - 1, yY, segIdx);
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
busses.setPixelColor(index, col);
|
||||
}
|
||||
if (_segments[segIdx].options & MIRROR_Y_2D) { //set the corresponding vertically mirrored pixel
|
||||
index = XY(xX, _segments[segIdx].stopY - yY - 1, segIdx);
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
busses.setPixelColor(index, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y)
|
||||
{
|
||||
uint8_t segIdx = _segment_index;
|
||||
uint16_t width = _segments[segIdx].virtualWidth(); // segment width in logical pixels
|
||||
uint16_t height = _segments[segIdx].virtualHeight(); // segment height in logical pixels
|
||||
if (_segments[segIdx].options & MIRROR ) width = (width + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
if (_segments[segIdx].options & MIRROR_Y_2D) height = (height + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||
if (_segments[segIdx].options & TRANSPOSED ) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||
|
||||
x *= _segments[segIdx].groupLength();
|
||||
y *= _segments[segIdx].groupLength();
|
||||
if (x >= width || y >= height) return 0;
|
||||
|
||||
if (_segments[segIdx].options & REVERSE ) x = width - x - 1;
|
||||
if (_segments[segIdx].options & REVERSE_Y_2D) y = height - y - 1;
|
||||
|
||||
uint16_t index = XY(x, y, segIdx);
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
|
||||
return busses.getPixelColor(index);
|
||||
}
|
||||
|
||||
// blurRows: perform a blur1d on every row of a rectangular matrix
|
||||
void WS2812FX::blurRows(fract8 blur_amount, CRGB* leds)
|
||||
{
|
||||
uint16_t width = SEGMENT.virtualWidth();
|
||||
uint16_t height = SEGMENT.virtualHeight();
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for (uint16_t y = 0; y < height; y++) for (uint16_t x = 0; x < width; x++) {
|
||||
CRGB cur = leds ? leds[x + y * width] : col_to_crgb(getPixelColorXY(x,y));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if (x) {
|
||||
if (leds) leds[(x-1) + y * width] += part;
|
||||
else setPixelColorXY(x-1, y, col_to_crgb(getPixelColorXY(x-1, y)) + part);
|
||||
}
|
||||
if (leds) leds[x + y * width] = cur;
|
||||
else setPixelColorXY(x, y, cur);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
// blurColumns: perform a blur1d on each column of a rectangular matrix
|
||||
void WS2812FX::blurColumns(fract8 blur_amount, CRGB* leds)
|
||||
{
|
||||
uint16_t width = SEGMENT.virtualWidth();
|
||||
uint16_t height = SEGMENT.virtualHeight();
|
||||
// blur columns
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
for ( uint16_t x = 0; x < width; x++) {
|
||||
CRGB carryover = CRGB::Black;
|
||||
for ( uint16_t y = 0; y < height; y++) {
|
||||
CRGB cur = leds ? leds[x + y * width] : col_to_crgb(getPixelColorXY(x,y));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if (y) {
|
||||
if (leds) leds[x + (y-1) * width] += part;
|
||||
else setPixelColorXY(x, y-1, col_to_crgb(getPixelColorXY(x,y-1)) + part);
|
||||
}
|
||||
if (leds) leds[x + y * width] = cur;
|
||||
else setPixelColorXY(x, y, cur);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// blur1d: one-dimensional blur filter. Spreads light to 2 line neighbors.
|
||||
// blur2d: two-dimensional blur filter. Spreads light to 8 XY neighbors.
|
||||
//
|
||||
// 0 = no spread at all
|
||||
// 64 = moderate spreading
|
||||
// 172 = maximum smooth, even spreading
|
||||
//
|
||||
// 173..255 = wider spreading, but increasing flicker
|
||||
//
|
||||
// Total light is NOT entirely conserved, so many repeated
|
||||
// calls to 'blur' will also result in the light fading,
|
||||
// eventually all the way to black; this is by design so that
|
||||
// it can be used to (slowly) clear the LEDs to black.
|
||||
|
||||
void WS2812FX::blur1d(fract8 blur_amount, CRGB* leds)
|
||||
{
|
||||
blurRows(blur_amount, leds);
|
||||
}
|
||||
|
||||
void WS2812FX::blur2d(fract8 blur_amount, CRGB* leds)
|
||||
{
|
||||
blurRows(blur_amount, leds);
|
||||
blurColumns(blur_amount, leds);
|
||||
}
|
||||
|
||||
//ewowi20210628: new functions moved from colorutils: add segment awareness
|
||||
|
||||
/*
|
||||
* Fills segment with color
|
||||
*/
|
||||
void WS2812FX::fill2D(uint32_t c) {
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) {
|
||||
setPixelColorXY(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::fill_solid(const struct CRGB& color, CRGB* leds) {
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) {
|
||||
if (leds) leds[x + y * w] = color;
|
||||
else setPixelColorXY(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fade out function, higher rate = quicker fade
|
||||
* TODO: may be better to use approach of nscale8()
|
||||
*/
|
||||
void WS2812FX::fade_out2D(uint8_t rate) {
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
rate = (255-rate) >> 1;
|
||||
float mappedRate = float(rate) +1.1;
|
||||
|
||||
uint32_t color = SEGCOLOR(1); // target color
|
||||
int w2 = W(color);
|
||||
int r2 = R(color);
|
||||
int g2 = G(color);
|
||||
int b2 = B(color);
|
||||
|
||||
for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) {
|
||||
color = getPixelColorXY(x, y);
|
||||
int w1 = W(color);
|
||||
int r1 = R(color);
|
||||
int g1 = G(color);
|
||||
int b1 = B(color);
|
||||
|
||||
int wdelta = (w2 - w1) / mappedRate;
|
||||
int rdelta = (r2 - r1) / mappedRate;
|
||||
int gdelta = (g2 - g1) / mappedRate;
|
||||
int bdelta = (b2 - b1) / mappedRate;
|
||||
|
||||
// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
|
||||
wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1;
|
||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||
|
||||
setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::fadeToBlackBy(uint8_t fadeBy, CRGB* leds) {
|
||||
nscale8(255 - fadeBy, leds);
|
||||
}
|
||||
|
||||
void WS2812FX::nscale8(uint8_t scale, CRGB* leds) {
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
for(uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) {
|
||||
if (leds) leds[x + y * w].nscale8(scale);
|
||||
else setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x, y)).nscale8(scale));
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setPixels(CRGB* leds) {
|
||||
uint16_t w = SEGMENT.virtualWidth();
|
||||
uint16_t h = SEGMENT.virtualHeight();
|
||||
for (uint16_t y = 0; y < h; y++) for (uint16_t x = 0; x < w; x++) setPixelColorXY(x, y, leds[x + y*w]);
|
||||
}
|
@ -184,23 +184,27 @@ void WS2812FX::service() {
|
||||
|
||||
void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
uint8_t segIdx;
|
||||
uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment;
|
||||
if (isMatrix) {
|
||||
// map linear pixel into 2D segment area (even for 1D segments, expanding vertically)
|
||||
uint16_t h = _segments[segIdx].height(); // segment height in logical pixels
|
||||
uint8_t l = _segments[segIdx].groupLength();
|
||||
for (uint16_t y = 0; y < h; y += l) { // expand 1D effect vertically
|
||||
setPixelColorXY(i, y, r, g, b, w);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (SEGLEN) { // SEGLEN!=0 -> from segment/FX
|
||||
if (SEGLEN || (realtimeMode && useMainSegmentOnly)) {
|
||||
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
|
||||
if (_bri_t < 255) {
|
||||
if (SEGLEN && _bri_t < 255) { // SEGLEN!=0 -> from segment/FX
|
||||
r = scale8(r, _bri_t);
|
||||
g = scale8(g, _bri_t);
|
||||
b = scale8(b, _bri_t);
|
||||
w = scale8(w, _bri_t);
|
||||
}
|
||||
segIdx = _segment_index;
|
||||
} else // from live/realtime
|
||||
segIdx = _mainSegment;
|
||||
|
||||
if (SEGLEN || (realtimeMode && useMainSegmentOnly)) {
|
||||
uint32_t col = RGBW32(r, g, b, w);
|
||||
uint16_t len = _segments[segIdx].length();
|
||||
uint16_t len = _segments[segIdx].length(); // length of segment in number of pixels
|
||||
|
||||
// get physical pixel address (taking into account start, grouping, spacing [and offset])
|
||||
i = i * _segments[segIdx].groupLength();
|
||||
@ -211,7 +215,7 @@ void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte
|
||||
i = (len - 1) - i;
|
||||
}
|
||||
}
|
||||
i += _segments[segIdx].start;
|
||||
i += _segments[segIdx].start; // starting pixel in a group
|
||||
|
||||
// set all the pixels in the group
|
||||
for (uint16_t j = 0; j < _segments[segIdx].grouping; j++) {
|
||||
@ -221,15 +225,13 @@ void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte
|
||||
if (_segments[segIdx].options & MIRROR) { //set the corresponding mirrored pixel
|
||||
uint16_t indexMir = _segments[segIdx].stop - indexSet + _segments[segIdx].start - 1;
|
||||
indexMir += _segments[segIdx].offset; // offset/phase
|
||||
|
||||
if (indexMir >= _segments[segIdx].stop) indexMir -= len;
|
||||
if (indexMir >= _segments[segIdx].stop) indexMir -= len; // wrap
|
||||
if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir];
|
||||
|
||||
busses.setPixelColor(indexMir, col);
|
||||
}
|
||||
indexSet += _segments[segIdx].offset; // offset/phase
|
||||
|
||||
if (indexSet >= _segments[segIdx].stop) indexSet -= len;
|
||||
if (indexSet >= _segments[segIdx].stop) indexSet -= len; // wrap
|
||||
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
||||
|
||||
busses.setPixelColor(indexSet, col);
|
||||
@ -496,6 +498,8 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
if (isMatrix) return getPixelColorXY(i, 0);
|
||||
|
||||
// get physical pixel
|
||||
i = i * SEGMENT.groupLength();;
|
||||
if (IS_REVERSE) {
|
||||
@ -566,14 +570,13 @@ uint8_t WS2812FX::Segment::differs(Segment& b) {
|
||||
if (c1x != b.c1x) d |= SEG_DIFFERS_FX;
|
||||
if (c2x != b.c2x) d |= SEG_DIFFERS_FX;
|
||||
if (c3x != b.c3x) d |= SEG_DIFFERS_FX;
|
||||
if (startY != b.startY) d |= SEG_DIFFERS_BOUNDS;
|
||||
if (stopY != b.stopY) d |= SEG_DIFFERS_BOUNDS;
|
||||
|
||||
if ((options & 0b00101110) != (b.options & 0b00101110)) d |= SEG_DIFFERS_OPT;
|
||||
if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL;
|
||||
if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL;
|
||||
|
||||
for (uint8_t i = 0; i < NUM_COLORS; i++)
|
||||
{
|
||||
if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
||||
}
|
||||
for (uint8_t i = 0; i < NUM_COLORS; i++) if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
||||
|
||||
return d;
|
||||
}
|
||||
@ -640,12 +643,15 @@ bool WS2812FX::hasCCTBus(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset) {
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing, uint16_t offset, uint16_t startY, uint16_t stopY) {
|
||||
if (n >= MAX_NUM_SEGMENTS) return;
|
||||
Segment& seg = _segments[n];
|
||||
|
||||
//return if neither bounds nor grouping have changed
|
||||
bool boundsUnchanged = (seg.start == i1 && seg.stop == i2);
|
||||
if (isMatrix) {
|
||||
boundsUnchanged &= (seg.startY == startY && seg.stopY == stopY);
|
||||
}
|
||||
if (boundsUnchanged
|
||||
&& (!grouping || (seg.grouping == grouping && seg.spacing == spacing))
|
||||
&& (offset == UINT16_MAX || offset == seg.offset)) return;
|
||||
@ -662,9 +668,17 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
|
||||
if (n == _mainSegment) setMainSegmentId(0);
|
||||
return;
|
||||
}
|
||||
if (i1 < _length) seg.start = i1;
|
||||
seg.stop = i2;
|
||||
if (i2 > _length) seg.stop = _length;
|
||||
if (isMatrix) {
|
||||
if (i1 < matrixWidth) seg.start = i1;
|
||||
seg.stop = i2 > matrixWidth ? matrixWidth : i2;
|
||||
if (startY < matrixHeight) seg.startY = startY;
|
||||
seg.stopY = stopY > matrixHeight ? matrixHeight : MAX(1,stopY);
|
||||
} else {
|
||||
if (i1 < _length) seg.start = i1;
|
||||
seg.stop = i2 > _length ? _length : i2;
|
||||
seg.startY = 0;
|
||||
seg.stopY = 1;
|
||||
}
|
||||
if (grouping) {
|
||||
seg.grouping = grouping;
|
||||
seg.spacing = spacing;
|
||||
@ -1157,6 +1171,8 @@ uint32_t IRAM_ATTR WS2812FX::color_from_palette(uint16_t i, bool mapping, bool w
|
||||
|
||||
//load custom mapping table from JSON file (called from finalizeInit() or deserializeState())
|
||||
void WS2812FX::deserializeMap(uint8_t n) {
|
||||
if (isMatrix) return; // 2D support creates its own ledmap
|
||||
|
||||
char fileName[32];
|
||||
strcpy_P(fileName, PSTR("/ledmap"));
|
||||
if (n) sprintf(fileName +7, "%d", n);
|
||||
@ -1399,7 +1415,9 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Candy Cane@!,Width;;",
|
||||
"Blends@Shift speed,Blend speed;1,2,3,!",
|
||||
"TV Simulator",
|
||||
"Dynamic Smooth"
|
||||
"Dynamic Smooth",
|
||||
"2D Black Hole A@!,!,C1,C2,C3;!;!",
|
||||
"2D Black Hole B@!,!,C1,C2,C3;!;!"
|
||||
])=====";
|
||||
|
||||
const char JSON_palette_names[] PROGMEM = R"=====([
|
||||
|
@ -91,6 +91,41 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
||||
|
||||
// 2D Matrix Settings
|
||||
JsonObject matrix = hw_led[F("matrix")];
|
||||
if (!matrix.isNull()) {
|
||||
strip.isMatrix = true;
|
||||
CJSON(strip.panelH, matrix[F("ph")]);
|
||||
CJSON(strip.panelW, matrix[F("pw")]);
|
||||
CJSON(strip.hPanels, matrix[F("mph")]);
|
||||
CJSON(strip.vPanels, matrix[F("mpv")]);
|
||||
CJSON(strip.matrix.bottomStart, matrix[F("pb")]);
|
||||
CJSON(strip.matrix.rightStart, matrix[F("pr")]);
|
||||
CJSON(strip.matrix.vertical, matrix[F("pv")]);
|
||||
CJSON(strip.matrix.serpentine, matrix[F("ps")]);
|
||||
|
||||
JsonArray panels = matrix[F("panels")];
|
||||
uint8_t s = 0;
|
||||
if (!panels.isNull()) {
|
||||
for (JsonObject pnl : panels) {
|
||||
CJSON(strip.panel[s].bottomStart, pnl["b"]);
|
||||
CJSON(strip.panel[s].rightStart, pnl["r"]);
|
||||
CJSON(strip.panel[s].vertical, pnl["v"]);
|
||||
CJSON(strip.panel[s].serpentine, pnl["s"]);
|
||||
if (++s >= WLED_MAX_PANELS) break; // max panels reached
|
||||
}
|
||||
}
|
||||
// clear remaining panels
|
||||
for (; s<WLED_MAX_PANELS; s++) {
|
||||
strip.panel[s].bottomStart = 0;
|
||||
strip.panel[s].rightStart = 0;
|
||||
strip.panel[s].vertical = 0;
|
||||
strip.panel[s].serpentine = 0;
|
||||
}
|
||||
|
||||
strip.setUpMatrix();
|
||||
}
|
||||
|
||||
JsonArray ins = hw_led["ins"];
|
||||
|
||||
if (fromFS || !ins.isNull()) {
|
||||
@ -583,6 +618,28 @@ void serializeConfig() {
|
||||
hw_led["fps"] = strip.getTargetFps();
|
||||
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
||||
|
||||
// 2D Matrix Settings
|
||||
if (strip.isMatrix) {
|
||||
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
||||
matrix[F("ph")] = strip.panelH;
|
||||
matrix[F("pw")] = strip.panelW;
|
||||
matrix[F("mph")] = strip.hPanels;
|
||||
matrix[F("mpv")] = strip.vPanels;
|
||||
matrix[F("pb")] = strip.matrix.bottomStart;
|
||||
matrix[F("pr")] = strip.matrix.rightStart;
|
||||
matrix[F("pv")] = strip.matrix.vertical;
|
||||
matrix[F("ps")] = strip.matrix.serpentine;
|
||||
|
||||
JsonArray panels = matrix.createNestedArray(F("panels"));
|
||||
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) {
|
||||
JsonObject pnl = panels.createNestedObject();
|
||||
pnl["b"] = strip.panel[i].bottomStart;
|
||||
pnl["r"] = strip.panel[i].rightStart;
|
||||
pnl["v"] = strip.panel[i].vertical;
|
||||
pnl["s"] = strip.panel[i].serpentine;
|
||||
}
|
||||
}
|
||||
|
||||
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
||||
|
||||
for (uint8_t s = 0; s < busses.getNumBusses(); s++) {
|
||||
|
@ -223,6 +223,9 @@
|
||||
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
|
||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||
#define SEG_OPTION_TRANSITIONAL 7
|
||||
#define SEG_OPTION_REVERSED_Y 8
|
||||
#define SEG_OPTION_MIRROR_Y 9
|
||||
#define SEG_OPTION_TRANSPOSE 10
|
||||
|
||||
//Segment differs return byte
|
||||
#define SEG_DIFFERS_BRI 0x01
|
||||
|
@ -972,6 +972,11 @@ textarea {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
TD .revchkl {
|
||||
padding: 0 0 0 32px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.check input, .radio input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
@ -1041,6 +1046,10 @@ textarea {
|
||||
background: var(--c-f);
|
||||
}
|
||||
|
||||
TD .checkmark, TD .radiomark {
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.h {
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
|
@ -20,6 +20,7 @@ var pJson = {}, eJson = {}, lJson = {};
|
||||
var pN = "", pI = 0, pNum = 0;
|
||||
var pmt = 1, pmtLS = 0, pmtLast = 0;
|
||||
var lastinfo = {};
|
||||
var isM = false, mw = 0, mh=0;
|
||||
var ws, cpick, ranges;
|
||||
var cfg = {
|
||||
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
||||
@ -599,6 +600,10 @@ function parseInfo(i) {
|
||||
syncTglRecv = i.str;
|
||||
maxSeg = i.leds.maxseg;
|
||||
pmt = i.fs.pmt;
|
||||
// do we have a matrix set-up
|
||||
mw = i.leds.matrix ? i.leds.matrix.w : 0;
|
||||
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
||||
isM = mw>0 && mh>0;
|
||||
}
|
||||
|
||||
function populateInfo(i)
|
||||
@ -665,6 +670,13 @@ function populateSegments(s)
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark schk"></span></label>`;
|
||||
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark schk"></span></label>`;
|
||||
let rvYck = "", miYck ="";
|
||||
if (isM) {
|
||||
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark schk"></span></label>`;
|
||||
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark schk"></span></label>`;
|
||||
}
|
||||
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}">
|
||||
<label class="check schkl">
|
||||
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
||||
@ -681,19 +693,25 @@ function populateSegments(s)
|
||||
<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
|
||||
<table class="infot segt">
|
||||
<tr>
|
||||
<td>Start LED</td>
|
||||
<td>${cfg.comp.seglen?"LED count":"Stop LED"}</td>
|
||||
<td>Offset</td>
|
||||
<td>${isM?'Start X':'Start LED'}</td>
|
||||
<td>${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
|
||||
<td>${isM?'':'Offset'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${ledCount-1}" value="${inst.start}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM?mw:ledCount)-1}" value="${inst.start}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM?mw:ledCount)-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td style="text-align:revert;">${isM?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
|
||||
</tr>
|
||||
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
|
||||
'<tr>'+
|
||||
'<td><input class="noslide segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+inst.startY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+(mh-(cfg.comp.seglen?inst.startY:0))+'" value="'+(inst.stopY-(cfg.comp.seglen?inst.start:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+
|
||||
'</tr>':''}
|
||||
<tr>
|
||||
<td>Grouping</td>
|
||||
<td>Spacing</td>
|
||||
<td>Apply</td>
|
||||
<td><!--Apply--></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
@ -702,14 +720,10 @@ function populateSegments(s)
|
||||
</tr>
|
||||
</table>
|
||||
<div class="h bp" id="seg${i}len"></div>
|
||||
${!isM?rvXck:''}
|
||||
<label class="check revchkl">
|
||||
Reverse direction
|
||||
<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev ? "checked":""}>
|
||||
<span class="checkmark schk"></span>
|
||||
</label>
|
||||
<label class="check revchkl">
|
||||
Mirror effect
|
||||
<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi ? "checked":""}>
|
||||
${isM?'Transpose':'Mirror effect'}
|
||||
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
|
||||
<span class="checkmark schk"></span>
|
||||
</label>
|
||||
<div class="del">
|
||||
@ -736,7 +750,7 @@ function populateSegments(s)
|
||||
if (!gId(`seg${i}sel`).checked) gId(`selall`).checked = false;
|
||||
}
|
||||
if (segCount < 2) gId(`segd${lSeg}`).style.display = "none";
|
||||
if (!noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).style.display = "inline";
|
||||
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).style.display = "inline";
|
||||
gId('rsbtn').style.display = (segCount > 1) ? "inline":"none";
|
||||
}
|
||||
|
||||
@ -966,6 +980,11 @@ function updateLen(s)
|
||||
var start = parseInt(gId(`seg${s}s`).value);
|
||||
var stop = parseInt(gId(`seg${s}e`).value);
|
||||
var len = stop - (cfg.comp.seglen?0:start);
|
||||
if (isM) {
|
||||
start = parseInt(gId(`seg${s}sY`).value);
|
||||
stop = parseInt(gId(`seg${s}eY`).value);
|
||||
len *= (stop-(cfg.comp.seglen?0:start));
|
||||
}
|
||||
var out = "(delete)";
|
||||
if (len > 1) {
|
||||
out = `${len} LEDs`;
|
||||
@ -1280,7 +1299,7 @@ function setSliderAndColorControl(idx, applyDef=false)
|
||||
var v = Math.max(0,Math.min(255,parseInt(slOnOff[i].substr(dPos+1))));
|
||||
if (i==0) { if (applyDef) gId("sliderSpeed").value = v; obj.seg.sx = v; }
|
||||
else if (i==1) { if (applyDef) gId("sliderIntensity").value = v; obj.seg.ix = v; }
|
||||
else { if (applyDef) gId("sliderC"+(i-1)).value = v; obj.seg["C"+(i-1)] = v}
|
||||
else { if (applyDef) gId("sliderC"+(i-1)).value = v; obj.seg["c"+(i-1)+"x"] = v}
|
||||
slOnOff[i] = slOnOff[i].substring(0,dPos);
|
||||
}
|
||||
if (slOnOff.length>i && slOnOff[i]!="!") label.innerHTML = slOnOff[i];
|
||||
@ -1501,6 +1520,7 @@ function makeSeg()
|
||||
{
|
||||
var ns = 0;
|
||||
var lu = lowestUnused;
|
||||
let li = lastinfo;
|
||||
if (lu > 0) {
|
||||
var pend = parseInt(gId(`seg${lu -1}e`).value,10) + (cfg.comp.seglen?parseInt(gId(`seg${lu -1}s`).value,10):0);
|
||||
if (pend < ledCount) ns = pend;
|
||||
@ -1515,14 +1535,19 @@ function makeSeg()
|
||||
<input type="text" class="noslide" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>
|
||||
<table class="segt">
|
||||
<tr>
|
||||
<td width="38%">Start LED</td>
|
||||
<td width="38%">${cfg.comp.seglen?"LED count":"Stop LED"}</td>
|
||||
<td width="38%">${isM?'Start X':'Start LED'}</td>
|
||||
<td width="38%">${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${lu}s" type="number" min="0" max="${ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><button class="btn btn-xs" onclick="setSeg(${lu});resetUtil();"><i class="icons bth-icon" id="segc${lu}"></i></button></td>
|
||||
</tr>
|
||||
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td></tr>'+
|
||||
'<tr>'+
|
||||
'<td><input class="noslide segn" id="seg'+lu+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+0+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
|
||||
'<td><input class="noslide segn" id="seg'+lu+'eY" type="number" min="0" max="'+mh+'" value="'+mh+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
|
||||
'</tr>':''}
|
||||
</table>
|
||||
<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div>
|
||||
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>
|
||||
@ -1813,6 +1838,7 @@ function selSeg(s)
|
||||
|
||||
function rptSeg(s)
|
||||
{
|
||||
//TODO: 2D support
|
||||
var name = gId(`seg${s}t`).value;
|
||||
var start = parseInt(gId(`seg${s}s`).value);
|
||||
var stop = parseInt(gId(`seg${s}e`).value);
|
||||
@ -1842,6 +1868,12 @@ function setSeg(s)
|
||||
var stop = parseInt(gId(`seg${s}e`).value);
|
||||
if ((cfg.comp.seglen && stop == 0) || (!cfg.comp.seglen && stop <= start)) {delSeg(s); return;}
|
||||
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
|
||||
if (isM) {
|
||||
var startY = parseInt(gId(`seg${s}sY`).value);
|
||||
var stopY = parseInt(gId(`seg${s}eY`).value);
|
||||
obj.seg.startY = startY;
|
||||
obj.seg.stopY = (cfg.comp.seglen?startY:0)+stopY;
|
||||
}
|
||||
if (gId(`seg${s}grp`)) {
|
||||
var grp = parseInt(gId(`seg${s}grp`).value);
|
||||
var spc = parseInt(gId(`seg${s}spc`).value);
|
||||
@ -1871,6 +1903,13 @@ function setRev(s)
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setRevY(s)
|
||||
{
|
||||
var rev = gId(`seg${s}rY`).checked;
|
||||
var obj = {"seg": {"id": s, "rY": rev}};
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setMi(s)
|
||||
{
|
||||
var mi = gId(`seg${s}mi`).checked;
|
||||
@ -1878,6 +1917,20 @@ function setMi(s)
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setMiY(s)
|
||||
{
|
||||
var mi = gId(`seg${s}mY`).checked;
|
||||
var obj = {"seg": {"id": s, "mY": mi}};
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setTp(s)
|
||||
{
|
||||
var tp = gId(`seg${s}tp`).checked;
|
||||
var obj = {"seg": {"id": s, "tp": tp}};
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setSegPwr(s)
|
||||
{
|
||||
var pwr = gId(`seg${s}pwr`).classList.contains("act");
|
||||
|
@ -18,31 +18,33 @@
|
||||
margin: 0;
|
||||
}
|
||||
html {
|
||||
--h: 10.2vh;
|
||||
--h: 9vh;
|
||||
}
|
||||
button {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
display: inline-block;
|
||||
display: block;
|
||||
border: 1px solid #333;
|
||||
border-radius: var(--h);
|
||||
font-size: 6vmin;
|
||||
height: var(--h);
|
||||
width: calc(100% - 40px);
|
||||
margin-top: 2vh;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form action="/"><button type=submit id="b">Back</button></form>
|
||||
<form action="/settings/wifi"><button type="submit">WiFi Setup</button></form>
|
||||
<form action="/settings/leds"><button type="submit">LED Preferences</button></form>
|
||||
<form action="/settings/ui"><button type="submit">User Interface</button></form>
|
||||
<form action="/settings/dmx"><button id="dmxbtn" style="display: none;" type="submit">DMX Output</button></form>
|
||||
<form action="/settings/sync"><button type="submit">Sync Interfaces</button></form>
|
||||
<form action="/settings/time"><button type="submit">Time & Macros</button></form>
|
||||
<form action="/settings/um"><button type="submit">Usermods</button></form>
|
||||
<form action="/settings/sec"><button type="submit">Security & Updates</button></form>
|
||||
<button type=submit id="b" onclick="window.location='/'">Back</button>
|
||||
<button type="submit" onclick="window.location='./settings/wifi'">WiFi Setup</button>
|
||||
<button type="submit" onclick="window.location='./settings/leds'">LED Preferences</button>
|
||||
<button type="submit" onclick="window.location='./settings/2D'">2D Configuration</button>
|
||||
<button type="submit" onclick="window.location='./settings/ui'">User Interface</button>
|
||||
<button id="dmxbtn" style="display: none;" type="submit" onclick="window.location='./settings/dmx'">DMX Output</button>
|
||||
<button type="submit" onclick="window.location='./settings/sync'">Sync Interfaces</button>
|
||||
<button type="submit" onclick="window.location='./settings/time'">Time & Macros</button>
|
||||
<button type="submit" onclick="window.location='./settings/um'">Usermods</button>
|
||||
<button type="submit" onclick="window.location='./settings/sec'">Security & Updates</button>
|
||||
</body>
|
||||
</html>
|
126
wled00/data/settings_2D.htm
Normal file
126
wled00/data/settings_2D.htm
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>2D Set-up</title>
|
||||
<script>
|
||||
var d=document;
|
||||
function H(){window.open("https://kno.wled.ge/features/2D");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
|
||||
var maxPanels=64;
|
||||
function UI(change=false)
|
||||
{
|
||||
if (gId("somp").value === "0") {
|
||||
gId("mpdiv").style.display = "none";
|
||||
resetPanels();
|
||||
return;
|
||||
}
|
||||
|
||||
gId("mpdiv").style.display = "block";
|
||||
maxPanels = parseInt(d.Sf.MPH.value) * parseInt(d.Sf.MPV.value);
|
||||
|
||||
let i = gId("panels").children.length;
|
||||
if (i<maxPanels) for (let j=i; j<maxPanels; j++) addPanel(j);
|
||||
if (i>maxPanels) for (let j=i; j>maxPanels; j--) remPanel();
|
||||
//btnPanel(gId("panels").children.length);
|
||||
}
|
||||
|
||||
function addPanels() {
|
||||
let h = parseInt(d.Sf.MPH.value);
|
||||
let v = parseInt(d.Sf.MPV.value);
|
||||
for (let i=0; i<h*v; i++) addPanel(i);
|
||||
}
|
||||
|
||||
function addPanel(i=0) {
|
||||
let p = gId("panels");
|
||||
if (p.children.length >= maxPanels) return;
|
||||
let b = `<div id="pnl${i}">${i===0?"":'<hr style="width:260px">'}Panel ${i}<br>1<sup>st</sup> LED: <select name="P${i}B">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="P${i}R">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="P${i}V">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="P${i}S"></div>`;
|
||||
p.insertAdjacentHTML("beforeend", b);
|
||||
}
|
||||
|
||||
function remPanel() {
|
||||
let p = gId("panels").children;
|
||||
var i = p.length;
|
||||
if (i <= 1) return;
|
||||
p[i-1].remove();
|
||||
}
|
||||
|
||||
function resetPanels() {
|
||||
d.Sf.MPH.value = 1;
|
||||
d.Sf.MPV.value = 1;
|
||||
for (let e of gId("panels").children) e.remove();
|
||||
}
|
||||
|
||||
function btnPanel(i) {
|
||||
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
|
||||
gId("pnl_rem").style.display = (i>1) ? "inline":"none";
|
||||
}
|
||||
|
||||
function S() {GetV();UI()}
|
||||
//values injected by server while sending HTML
|
||||
function GetV() {}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
</div>
|
||||
<h2>2D setup</h2>
|
||||
Strip or panel:
|
||||
<select id="somp" name="SOMP" onchange="resetPanels();addPanels();UI();" >
|
||||
<option value="0">1D Strip</option>
|
||||
<option value="1">2D Matrix</option>
|
||||
</select><br>
|
||||
<div id="mpdiv" style="display:none;">
|
||||
<h3>2D Matrix</h3>
|
||||
Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br>
|
||||
Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1" oninput="UI()">
|
||||
Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1" oninput="UI()"><br>
|
||||
1<sup>st</sup> panel: <select name="PB">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="PR">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="PV">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="PS">
|
||||
<hr style="width:260px">
|
||||
<i>A matrix is made of 1 or more physical led panels of the same dimensions.<br>
|
||||
Panels should be arranged from top-left to bottom-right order, starting with lower panel number on the left (or top if transposed).<br>
|
||||
Each panel can have different orientation and/or starting point and/or layout.</i><br>
|
||||
<hr style="width:260px">
|
||||
<h3>2D Panel layout</h3>
|
||||
<div id="panels">
|
||||
</div>
|
||||
<!--
|
||||
<button type="button" class="xs" id="pnl_add" onclick="addPanel()">+</button>
|
||||
<button type="button" class="xs" id="pnl_rem" onclick="remPanel()">-</button>
|
||||
-->
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -64,50 +64,52 @@ const uint8_t PAGE_settingsCss[] PROGMEM = {
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/settings.htm, do not edit!!
|
||||
const uint16_t PAGE_settings_length = 669;
|
||||
const uint16_t PAGE_settings_length = 694;
|
||||
const uint8_t PAGE_settings[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x8d, 0x94, 0xdb, 0x6e, 0xdb, 0x30,
|
||||
0x0c, 0x86, 0xef, 0xfd, 0x14, 0x9a, 0x8b, 0x0d, 0x09, 0x10, 0x37, 0x6d, 0x3a, 0x0c, 0x83, 0x0f,
|
||||
0x19, 0xd0, 0xb5, 0xdd, 0x0a, 0xac, 0x68, 0x81, 0x9e, 0xb6, 0x4b, 0x59, 0xa2, 0x13, 0xae, 0x96,
|
||||
0x64, 0x48, 0x74, 0x1a, 0x2f, 0xc8, 0xbb, 0x4f, 0x76, 0xb2, 0xb4, 0x6b, 0x17, 0x2c, 0x37, 0x06,
|
||||
0x48, 0x51, 0x3f, 0xc9, 0x8f, 0x94, 0xd3, 0x37, 0x27, 0x97, 0x9f, 0x6f, 0x7e, 0x5c, 0x9d, 0xb2,
|
||||
0x29, 0xa9, 0x72, 0x9c, 0xb6, 0x5f, 0x56, 0x72, 0x3d, 0xc9, 0x42, 0xd0, 0xa1, 0xb7, 0x81, 0xcb,
|
||||
0x71, 0xaa, 0x80, 0x38, 0x13, 0x53, 0x6e, 0x1d, 0x50, 0x16, 0xde, 0xde, 0x9c, 0x45, 0x1f, 0xc3,
|
||||
0xb5, 0x37, 0x10, 0x46, 0x13, 0x68, 0xef, 0x7e, 0x44, 0x49, 0xd3, 0x4c, 0xc2, 0x0c, 0x05, 0x44,
|
||||
0x9d, 0x31, 0x40, 0x8d, 0x84, 0xbc, 0x8c, 0x9c, 0xe0, 0x25, 0x64, 0x87, 0x03, 0xc5, 0xe7, 0xa8,
|
||||
0x6a, 0xb5, 0xb1, 0x6b, 0x07, 0xb6, 0x33, 0x78, 0xee, 0x6d, 0x6d, 0x42, 0x16, 0x68, 0xae, 0x20,
|
||||
0x0b, 0x67, 0x08, 0x8f, 0x95, 0xb1, 0xe4, 0xb3, 0x10, 0x52, 0x09, 0xe3, 0xfb, 0x6f, 0xa7, 0x27,
|
||||
0xec, 0x1a, 0x88, 0x50, 0x4f, 0x5c, 0x3a, 0x5c, 0x39, 0x53, 0x27, 0x2c, 0x56, 0x34, 0x0e, 0x66,
|
||||
0xdc, 0x32, 0x99, 0x49, 0x23, 0x6a, 0xe5, 0x4b, 0x49, 0x8a, 0x5a, 0x0b, 0x42, 0xa3, 0xd9, 0xe4,
|
||||
0x5c, 0xf6, 0x74, 0x7f, 0x61, 0x81, 0x6a, 0xab, 0x99, 0xdc, 0x9f, 0x00, 0x9d, 0x96, 0xd0, 0xc6,
|
||||
0x1c, 0x37, 0xdd, 0xd1, 0x72, 0x13, 0x7a, 0xdd, 0xeb, 0x2f, 0xbe, 0x00, 0xdd, 0xf5, 0xfa, 0xcb,
|
||||
0x20, 0x1d, 0xae, 0x85, 0xd7, 0x09, 0x98, 0xb3, 0x22, 0x0b, 0x87, 0x6e, 0x9d, 0x7e, 0xe8, 0xf6,
|
||||
0x7f, 0xba, 0x4f, 0x55, 0x76, 0xe0, 0xab, 0x7b, 0x8a, 0xa4, 0xc6, 0x57, 0x14, 0xe4, 0x46, 0x36,
|
||||
0x0b, 0x82, 0x39, 0x45, 0xbc, 0xc4, 0x89, 0x8e, 0x85, 0xcf, 0x05, 0x36, 0xc9, 0xb9, 0x78, 0x98,
|
||||
0x58, 0x53, 0x6b, 0x19, 0xef, 0x8d, 0x46, 0xa3, 0x64, 0x0a, 0x38, 0x99, 0x52, 0x7c, 0x78, 0x70,
|
||||
0x50, 0xcd, 0x13, 0xc5, 0xed, 0x04, 0x75, 0x7c, 0xb0, 0x6c, 0xe1, 0x2f, 0xa2, 0x68, 0xea, 0xfd,
|
||||
0xfb, 0xa3, 0xd9, 0x74, 0x99, 0xd7, 0x44, 0x46, 0x2f, 0x9e, 0x5f, 0x3e, 0x3a, 0x3a, 0x4a, 0x84,
|
||||
0x29, 0x8d, 0x8d, 0xf7, 0x8a, 0xa2, 0x48, 0x0a, 0x0f, 0x3f, 0x2a, 0xb8, 0xc2, 0xb2, 0x89, 0xef,
|
||||
0xc0, 0x4a, 0xae, 0xf9, 0xe0, 0x2b, 0x94, 0x33, 0x20, 0x14, 0x7c, 0xe0, 0xb8, 0x76, 0x91, 0x47,
|
||||
0x8c, 0x45, 0x22, 0xd1, 0x55, 0x25, 0x6f, 0x62, 0xd4, 0x25, 0x6a, 0x88, 0xf2, 0xd2, 0x88, 0x87,
|
||||
0x24, 0x37, 0x56, 0x82, 0x8d, 0x0f, 0xab, 0x39, 0x73, 0xa6, 0x44, 0xc9, 0x3a, 0xf9, 0x95, 0x37,
|
||||
0xb2, 0x5c, 0x62, 0xed, 0x62, 0x8f, 0xb6, 0xe7, 0x4b, 0xea, 0xaf, 0x52, 0x39, 0xfc, 0x05, 0xf1,
|
||||
0x87, 0x99, 0x42, 0xfd, 0xa7, 0x85, 0xcd, 0x79, 0x37, 0xf1, 0xd8, 0xcf, 0x52, 0xf4, 0x7c, 0x5b,
|
||||
0x6f, 0x59, 0xc4, 0xde, 0xfb, 0xe6, 0xfa, 0xeb, 0xee, 0x22, 0x32, 0x55, 0xdc, 0xf6, 0xd4, 0xc2,
|
||||
0xed, 0x50, 0xa5, 0xc3, 0xd5, 0x6e, 0xb5, 0xc4, 0x98, 0xd1, 0xa5, 0xe1, 0x32, 0x0b, 0xfd, 0x14,
|
||||
0x3c, 0xd4, 0xc2, 0x58, 0xc5, 0x78, 0x37, 0x17, 0x8f, 0xdd, 0x3b, 0x56, 0x20, 0x18, 0x35, 0x95,
|
||||
0xdf, 0x0d, 0x57, 0xe7, 0x0a, 0x29, 0x64, 0xe8, 0xe3, 0xf3, 0x70, 0x1c, 0x1c, 0x7b, 0x3c, 0xe9,
|
||||
0x70, 0x15, 0xe2, 0x55, 0xdb, 0xcb, 0x2f, 0x25, 0x36, 0x93, 0x7b, 0xc4, 0x02, 0xb7, 0xe8, 0x8d,
|
||||
0x83, 0x7b, 0x3c, 0xc3, 0x76, 0xc7, 0xea, 0x6a, 0x57, 0xb9, 0x12, 0xa4, 0xdb, 0x2a, 0xd7, 0x6e,
|
||||
0xec, 0x95, 0x85, 0x02, 0x2c, 0x68, 0x01, 0x6e, 0x57, 0xcd, 0xfa, 0x59, 0x81, 0xc1, 0xdf, 0x92,
|
||||
0xb7, 0x7e, 0x96, 0xec, 0xbc, 0x5d, 0xa8, 0x82, 0x0b, 0xd8, 0x55, 0x50, 0xaa, 0xf9, 0x46, 0x31,
|
||||
0xe8, 0xa8, 0x79, 0x4f, 0x4e, 0x3a, 0x64, 0xdd, 0x20, 0xbc, 0xb9, 0xde, 0x0d, 0x6d, 0x34, 0x84,
|
||||
0x2f, 0xba, 0x38, 0xb9, 0xf8, 0xce, 0x2e, 0x6b, 0xaa, 0x6a, 0xfa, 0x77, 0xba, 0xe0, 0x75, 0x3e,
|
||||
0xd7, 0x68, 0xb1, 0x0d, 0xca, 0xb5, 0x3f, 0x7b, 0xea, 0xe0, 0x15, 0x93, 0x60, 0x5b, 0x0f, 0x84,
|
||||
0x0a, 0xb6, 0x69, 0xde, 0xf8, 0x33, 0xf6, 0x8e, 0x5d, 0x70, 0x61, 0xcd, 0x93, 0x62, 0xf0, 0x3f,
|
||||
0xcc, 0x6a, 0x9b, 0x5e, 0x4b, 0x59, 0x19, 0xb9, 0xbb, 0x94, 0x83, 0xed, 0xfd, 0x82, 0xa8, 0x2d,
|
||||
0x52, 0xe3, 0xeb, 0xbb, 0xad, 0x24, 0x27, 0x70, 0xc1, 0x2b, 0x8e, 0xc3, 0xf6, 0x05, 0xb4, 0xcf,
|
||||
0xa1, 0xfd, 0x01, 0xff, 0x06, 0x3e, 0x6a, 0x2c, 0x53, 0x90, 0x05, 0x00, 0x00
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x55, 0x6d, 0x6f, 0xd3, 0x30,
|
||||
0x10, 0xfe, 0xde, 0x5f, 0x61, 0x32, 0xc1, 0x5a, 0xa9, 0x69, 0xbb, 0x0e, 0x21, 0xc8, 0x4b, 0x91,
|
||||
0xb6, 0x6e, 0x30, 0x89, 0x69, 0x93, 0xf6, 0x06, 0x1f, 0x1d, 0xfb, 0x92, 0x1c, 0x4b, 0xec, 0xc8,
|
||||
0x76, 0xfa, 0x42, 0xd5, 0xff, 0xce, 0x25, 0x2d, 0xdb, 0x10, 0x13, 0x4c, 0xa8, 0x5f, 0xe2, 0xdc,
|
||||
0xd9, 0x79, 0xee, 0xb9, 0xe7, 0x39, 0x2b, 0xd1, 0xab, 0xe9, 0xc5, 0xf1, 0xf5, 0xb7, 0xcb, 0x13,
|
||||
0x96, 0xbb, 0xb2, 0x98, 0x44, 0xcd, 0x93, 0x15, 0x5c, 0x65, 0xb1, 0x07, 0xca, 0xa3, 0x18, 0xb8,
|
||||
0x9c, 0x44, 0x25, 0x38, 0xce, 0x44, 0xce, 0x8d, 0x05, 0x17, 0x7b, 0x37, 0xd7, 0xa7, 0xfe, 0x7b,
|
||||
0x6f, 0x9b, 0xed, 0x08, 0xad, 0x1c, 0x28, 0x4a, 0xcf, 0x51, 0xba, 0x3c, 0x96, 0x30, 0x43, 0x01,
|
||||
0x7e, 0x1b, 0xf4, 0x51, 0xa1, 0x43, 0x5e, 0xf8, 0x56, 0xf0, 0x02, 0xe2, 0x83, 0x7e, 0xc9, 0x17,
|
||||
0x58, 0xd6, 0xe5, 0x43, 0x5c, 0x5b, 0x30, 0x6d, 0xc0, 0x13, 0x8a, 0x95, 0xf6, 0x58, 0x47, 0xf1,
|
||||
0x12, 0x62, 0x6f, 0x86, 0x30, 0xaf, 0xb4, 0x71, 0x54, 0xc5, 0xa1, 0x2b, 0x60, 0x72, 0xf7, 0xe5,
|
||||
0x64, 0xca, 0xae, 0xc0, 0x39, 0x54, 0x99, 0x8d, 0x86, 0x9b, 0x64, 0x64, 0x85, 0xc1, 0xca, 0x4d,
|
||||
0x3a, 0x33, 0x6e, 0x98, 0x8c, 0xa5, 0x16, 0x75, 0x49, 0x54, 0xc2, 0xb4, 0x56, 0xc2, 0xa1, 0x56,
|
||||
0x2c, 0x3b, 0x93, 0x5d, 0xd5, 0x5b, 0x19, 0x70, 0xb5, 0x51, 0x4c, 0x0e, 0x32, 0x70, 0x27, 0x05,
|
||||
0x34, 0x67, 0x8e, 0x96, 0xed, 0xd6, 0xfa, 0xe1, 0xe8, 0x55, 0xb7, 0xb7, 0xfa, 0x04, 0xee, 0xb6,
|
||||
0xdb, 0x5b, 0x77, 0xa2, 0xe1, 0x16, 0x78, 0x5b, 0x80, 0x59, 0x23, 0x62, 0x6f, 0x68, 0xb7, 0xe5,
|
||||
0x87, 0x76, 0xf0, 0xdd, 0x7e, 0xac, 0xe2, 0x11, 0xb1, 0x7b, 0x3c, 0xe9, 0x96, 0xc4, 0xa8, 0x93,
|
||||
0x68, 0xb9, 0x5c, 0x39, 0x58, 0x38, 0x9f, 0x17, 0x98, 0xa9, 0x40, 0x50, 0x2d, 0x30, 0x61, 0xc2,
|
||||
0xc5, 0x7d, 0x66, 0x74, 0xad, 0x64, 0xb0, 0x37, 0x1e, 0x8f, 0xc3, 0x1c, 0x30, 0xcb, 0x5d, 0x70,
|
||||
0x30, 0x1a, 0x55, 0x8b, 0xb0, 0xe4, 0x26, 0x43, 0x15, 0x8c, 0xd6, 0x8d, 0xf8, 0x2b, 0xdf, 0xcf,
|
||||
0x83, 0x0f, 0xb3, 0x7c, 0x9d, 0xd4, 0xce, 0x69, 0xb5, 0x7a, 0xfa, 0xe5, 0xe1, 0xe1, 0x61, 0x28,
|
||||
0x74, 0xa1, 0x4d, 0xb0, 0x97, 0xa6, 0x69, 0x98, 0x92, 0xf2, 0x7e, 0xca, 0x4b, 0x2c, 0x96, 0xc1,
|
||||
0x2d, 0x18, 0xc9, 0x15, 0xef, 0x7f, 0x86, 0x62, 0x06, 0x0e, 0x05, 0xef, 0x5b, 0xae, 0xac, 0x4f,
|
||||
0xfa, 0x62, 0x1a, 0x4a, 0xb4, 0x55, 0xc1, 0x97, 0x41, 0x52, 0x68, 0x71, 0x1f, 0x26, 0xda, 0x48,
|
||||
0x30, 0xc1, 0x41, 0xb5, 0x60, 0x56, 0x17, 0x28, 0x59, 0x8b, 0xbb, 0xc9, 0xfa, 0x86, 0x4b, 0xac,
|
||||
0x6d, 0x40, 0x82, 0x76, 0x89, 0x48, 0x6f, 0x53, 0xc3, 0xe2, 0x0f, 0x08, 0xde, 0xcd, 0x4a, 0x54,
|
||||
0xbf, 0x88, 0x3f, 0xec, 0xb7, 0x3e, 0x07, 0xe4, 0xa0, 0xe8, 0x52, 0x33, 0xaf, 0x99, 0xcf, 0xde,
|
||||
0x52, 0x4b, 0xbd, 0x6d, 0x4f, 0xbe, 0xd3, 0x55, 0x30, 0x9e, 0xe5, 0xa1, 0xa8, 0x8d, 0x25, 0xda,
|
||||
0x95, 0xc6, 0x46, 0x8e, 0x56, 0xe1, 0x56, 0xaf, 0x68, 0xb8, 0x19, 0xb0, 0x46, 0x36, 0xa6, 0x55,
|
||||
0xa1, 0xb9, 0x8c, 0x3d, 0xb2, 0x82, 0x94, 0xdd, 0xf4, 0xcf, 0xdc, 0xb2, 0xa2, 0x79, 0xb0, 0x75,
|
||||
0x52, 0xa2, 0xf3, 0x18, 0xd2, 0x76, 0x42, 0x53, 0xa2, 0x95, 0x28, 0x50, 0xdc, 0xc7, 0xfb, 0x73,
|
||||
0x54, 0x52, 0xcf, 0x07, 0xd4, 0x18, 0x6f, 0x6c, 0x24, 0x97, 0xbc, 0xfd, 0xc9, 0x11, 0x69, 0x16,
|
||||
0x0d, 0x37, 0x00, 0x13, 0xf6, 0x3c, 0xd2, 0x5f, 0x20, 0x06, 0x8f, 0x4e, 0xcf, 0x31, 0x45, 0x02,
|
||||
0xbc, 0xc3, 0x53, 0x6c, 0xa6, 0xaf, 0xae, 0xfe, 0x84, 0xed, 0xfc, 0x8e, 0xfb, 0x22, 0xd8, 0x02,
|
||||
0xa4, 0x25, 0xd8, 0x66, 0xa6, 0x2f, 0x0d, 0xa4, 0x60, 0x40, 0x09, 0xb0, 0x9d, 0x7f, 0x71, 0x7e,
|
||||
0x11, 0xf6, 0x78, 0x4a, 0xc8, 0x9d, 0xf1, 0x94, 0x1d, 0x6b, 0x95, 0x62, 0x56, 0x9b, 0xf6, 0xc8,
|
||||
0x6e, 0xe4, 0xa8, 0x1b, 0x31, 0x6e, 0x68, 0xa8, 0xd8, 0x59, 0xe3, 0x63, 0xca, 0x05, 0x3c, 0x23,
|
||||
0x48, 0x63, 0x92, 0x2c, 0x17, 0x89, 0x53, 0x1e, 0x6b, 0x6d, 0xa6, 0x70, 0x3b, 0x81, 0x4a, 0x2b,
|
||||
0xf0, 0xfe, 0xab, 0x34, 0x01, 0x52, 0xed, 0xe9, 0xf9, 0x57, 0x76, 0x51, 0xbb, 0xaa, 0x76, 0xbb,
|
||||
0x31, 0xc2, 0x2e, 0x95, 0x20, 0xd8, 0x2b, 0x5a, 0x1e, 0x5b, 0xda, 0x91, 0x11, 0x0e, 0x4b, 0x68,
|
||||
0xac, 0xb8, 0xa6, 0x95, 0xbd, 0x61, 0xe7, 0x5c, 0x18, 0x6d, 0x77, 0xe4, 0x43, 0xb9, 0xf5, 0xa1,
|
||||
0xd4, 0xd2, 0xee, 0x48, 0x09, 0x68, 0x85, 0x00, 0xba, 0xa9, 0xe8, 0x96, 0xc4, 0xf7, 0xa6, 0x92,
|
||||
0xdc, 0x3d, 0xd5, 0x82, 0x5e, 0xe8, 0x96, 0x36, 0x57, 0xb6, 0xf9, 0x53, 0xfc, 0x04, 0xe7, 0xc3,
|
||||
0x64, 0x44, 0x39, 0x06, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
@ -1548,6 +1550,103 @@ const uint8_t PAGE_settings_um[] PROGMEM = {
|
||||
};
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/settings_2D.htm, do not edit!!
|
||||
const uint16_t PAGE_settings_2D_length = 1453;
|
||||
const uint8_t PAGE_settings_2D[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x8d, 0x57, 0x6d, 0x6f, 0xdb, 0x36,
|
||||
0x10, 0xfe, 0xae, 0x5f, 0xc1, 0x12, 0x05, 0x6a, 0xb5, 0xb6, 0x15, 0x67, 0x5b, 0x51, 0xc4, 0x92,
|
||||
0xb2, 0x7a, 0x09, 0xe6, 0x02, 0x0d, 0x1a, 0xd4, 0x5d, 0x8a, 0x61, 0x1d, 0x5a, 0x59, 0x3a, 0x47,
|
||||
0x6c, 0x28, 0x52, 0x20, 0x29, 0x3b, 0x99, 0x9b, 0xff, 0xbe, 0x23, 0x25, 0x5b, 0xb6, 0x63, 0xa7,
|
||||
0xf9, 0x12, 0x99, 0x2f, 0xf7, 0x7e, 0xf7, 0x3c, 0x4c, 0xf8, 0xec, 0xec, 0xc3, 0x1f, 0x9f, 0xfe,
|
||||
0xbe, 0x3c, 0x27, 0xb9, 0x29, 0x78, 0x1c, 0xda, 0xbf, 0x84, 0x27, 0xe2, 0x3a, 0xa2, 0x20, 0x28,
|
||||
0xae, 0x21, 0xc9, 0xe2, 0xb0, 0x00, 0x93, 0x90, 0x34, 0x4f, 0x94, 0x06, 0x13, 0xd1, 0xca, 0xcc,
|
||||
0x7a, 0x6f, 0x68, 0xb3, 0xeb, 0x89, 0xa4, 0x80, 0x88, 0xce, 0x19, 0x2c, 0x4a, 0xa9, 0x0c, 0x25,
|
||||
0xa9, 0x14, 0x06, 0x04, 0x5e, 0x5b, 0xb0, 0xcc, 0xe4, 0xd1, 0x6f, 0x47, 0x47, 0xeb, 0xab, 0x3b,
|
||||
0x47, 0x19, 0xcc, 0x59, 0x0a, 0x3d, 0xb7, 0xe8, 0x32, 0xc1, 0x0c, 0x4b, 0x78, 0x4f, 0xa7, 0x09,
|
||||
0x87, 0x68, 0xd0, 0x2d, 0x92, 0x5b, 0x56, 0x54, 0xc5, 0x7a, 0x5d, 0x69, 0x50, 0x6e, 0x91, 0x4c,
|
||||
0x71, 0x2d, 0x24, 0x7d, 0x60, 0x39, 0x0e, 0x0d, 0x33, 0x1c, 0xe2, 0xe3, 0x33, 0x32, 0x01, 0xd3,
|
||||
0xab, 0xca, 0x30, 0xa8, 0x37, 0x42, 0x9d, 0x2a, 0x56, 0x9a, 0xd8, 0x9b, 0x27, 0x8a, 0x64, 0x51,
|
||||
0x26, 0xd3, 0xaa, 0x40, 0x37, 0x86, 0xb3, 0x4a, 0xa4, 0x86, 0x49, 0x41, 0xc6, 0x1d, 0x7f, 0xb9,
|
||||
0x60, 0x22, 0x93, 0x8b, 0xbe, 0x2c, 0x41, 0x74, 0x68, 0x6e, 0x4c, 0xa9, 0x4f, 0x82, 0xe0, 0x46,
|
||||
0xc8, 0xfe, 0x82, 0x43, 0xd6, 0xbf, 0x86, 0x60, 0x06, 0x89, 0xa9, 0x14, 0xe8, 0xe0, 0xf8, 0x8c,
|
||||
0xfa, 0xf7, 0x6b, 0xd9, 0xd1, 0xae, 0x6c, 0x80, 0x39, 0x32, 0x4c, 0x5c, 0x6b, 0xda, 0xa5, 0x5f,
|
||||
0x35, 0xf0, 0xd9, 0xe6, 0xed, 0xeb, 0x77, 0x59, 0x07, 0xfc, 0xa5, 0x02, 0x54, 0x25, 0x88, 0xd5,
|
||||
0x6b, 0xce, 0x39, 0x58, 0x6f, 0x46, 0x77, 0xee, 0xe8, 0xde, 0xfa, 0x88, 0xb1, 0x5f, 0x26, 0x02,
|
||||
0xb8, 0x8e, 0x5e, 0xff, 0xda, 0x7a, 0xf9, 0xd7, 0xbb, 0x0e, 0x44, 0xcf, 0x06, 0xfe, 0x92, 0xcd,
|
||||
0x3a, 0xf4, 0x88, 0x46, 0x51, 0x64, 0xb5, 0x51, 0x2d, 0x8b, 0x92, 0xfa, 0xfd, 0x79, 0xc2, 0x2b,
|
||||
0xf0, 0x1b, 0xc5, 0xee, 0xa0, 0x28, 0x33, 0x36, 0xc7, 0x13, 0x6d, 0xee, 0x38, 0xf4, 0x33, 0xa6,
|
||||
0x4b, 0x9e, 0xdc, 0x45, 0x54, 0x48, 0x01, 0xb4, 0x3b, 0x97, 0x2c, 0x23, 0x18, 0x0d, 0x98, 0xda,
|
||||
0x52, 0xc7, 0x1f, 0x3e, 0x26, 0x34, 0xe5, 0x32, 0xbd, 0xa1, 0xdd, 0xd6, 0xb1, 0xd2, 0xf6, 0xc2,
|
||||
0x3b, 0x61, 0x3a, 0x59, 0x7f, 0x32, 0xeb, 0x5f, 0x5c, 0x8e, 0x1b, 0x07, 0x5e, 0xee, 0x1e, 0x5c,
|
||||
0x35, 0x07, 0x43, 0x0e, 0x86, 0x88, 0xda, 0xe5, 0xd2, 0xe9, 0x40, 0x2b, 0x69, 0xce, 0x78, 0xa6,
|
||||
0x40, 0xf4, 0x39, 0x88, 0x6b, 0x93, 0x0f, 0x31, 0x32, 0x11, 0xae, 0x8d, 0xf8, 0x33, 0xa9, 0x3a,
|
||||
0x56, 0x0c, 0xeb, 0x3d, 0x84, 0x76, 0x7f, 0x08, 0xaf, 0x5e, 0xf9, 0x49, 0x96, 0xb9, 0x15, 0xe6,
|
||||
0xcc, 0x89, 0xc5, 0x07, 0xc4, 0xe2, 0x0d, 0xb1, 0x5e, 0x0f, 0x13, 0x54, 0xd4, 0x62, 0x1b, 0x45,
|
||||
0x59, 0xa9, 0xc2, 0x24, 0x2c, 0x6b, 0xb9, 0x43, 0xd1, 0x75, 0x45, 0x74, 0x30, 0xbe, 0x95, 0x55,
|
||||
0x13, 0x1d, 0x0d, 0x4d, 0x08, 0x2f, 0xc5, 0xd0, 0x6c, 0xba, 0x69, 0xf6, 0x18, 0xc4, 0x7a, 0x1e,
|
||||
0xd5, 0x26, 0x77, 0x12, 0xe3, 0x22, 0xda, 0xcd, 0x4e, 0x1c, 0xb5, 0x21, 0xd6, 0x75, 0x1e, 0xd6,
|
||||
0xf6, 0xbe, 0x85, 0x58, 0x33, 0xc2, 0xb2, 0x88, 0x96, 0x82, 0x3f, 0x5f, 0xc2, 0x3d, 0x8d, 0x9f,
|
||||
0x2f, 0x8f, 0xb0, 0x3f, 0xe0, 0x94, 0xd2, 0x93, 0x17, 0x61, 0xae, 0x88, 0x2b, 0x67, 0x33, 0x77,
|
||||
0x27, 0xc7, 0xaf, 0x8f, 0xca, 0x5b, 0x1a, 0xbf, 0xb8, 0x77, 0xca, 0x88, 0x95, 0x08, 0xa7, 0x2a,
|
||||
0x1e, 0x84, 0xba, 0x2a, 0x63, 0x6d, 0xc2, 0xc0, 0x7e, 0xc9, 0xfb, 0xf3, 0xb3, 0x13, 0x12, 0x62,
|
||||
0x03, 0x43, 0x8a, 0xfe, 0xb9, 0x51, 0xbb, 0xb4, 0x57, 0x47, 0x34, 0xfe, 0x22, 0xbe, 0x98, 0x50,
|
||||
0x96, 0x2e, 0x16, 0x17, 0x7d, 0x84, 0xfd, 0x18, 0x7f, 0x92, 0x38, 0x71, 0xf5, 0xee, 0xbe, 0x1b,
|
||||
0x03, 0x1a, 0x8f, 0xa4, 0x31, 0xb2, 0xd8, 0xb8, 0x84, 0xa6, 0x9c, 0xfe, 0x78, 0x8f, 0x9d, 0x8f,
|
||||
0x87, 0xec, 0xbc, 0x87, 0x99, 0xf9, 0x89, 0xa1, 0x8f, 0xec, 0x3a, 0x37, 0x7b, 0xed, 0x60, 0x9c,
|
||||
0x5f, 0xc4, 0x07, 0xc5, 0x70, 0xe2, 0x12, 0x7b, 0xb8, 0x37, 0xc4, 0xab, 0x43, 0xa6, 0xc7, 0x52,
|
||||
0xb1, 0xff, 0x10, 0xc4, 0x12, 0xfe, 0x13, 0x07, 0xae, 0x40, 0x19, 0x96, 0x6e, 0x5d, 0xdb, 0xf1,
|
||||
0x61, 0x02, 0x0a, 0xe1, 0x02, 0x81, 0x02, 0xd0, 0x05, 0x26, 0xca, 0x0a, 0x2b, 0x79, 0x57, 0xa2,
|
||||
0x74, 0x9a, 0x43, 0x7a, 0x33, 0x95, 0xb7, 0x74, 0xd3, 0xa3, 0x09, 0xa2, 0x5b, 0x80, 0x55, 0x8e,
|
||||
0xbf, 0x0d, 0x45, 0x9f, 0x09, 0xc4, 0x42, 0xf3, 0x36, 0xfb, 0x9e, 0xa4, 0xa8, 0x61, 0xfc, 0xe9,
|
||||
0xe2, 0x7d, 0x87, 0x4e, 0x01, 0xfb, 0x0f, 0x40, 0x64, 0xb4, 0xbb, 0xd9, 0x69, 0x6d, 0xbb, 0x37,
|
||||
0x9d, 0xbd, 0x7f, 0xfe, 0x86, 0x16, 0x75, 0x44, 0x04, 0xab, 0x39, 0x14, 0x61, 0x34, 0xf8, 0xf1,
|
||||
0x03, 0xfe, 0x11, 0xbd, 0xc1, 0xbf, 0x7d, 0xd4, 0x21, 0xe7, 0xd0, 0xd9, 0xd2, 0xba, 0x81, 0x1b,
|
||||
0xcb, 0xed, 0x19, 0x41, 0xa8, 0xde, 0x9e, 0x8c, 0x68, 0xb0, 0x1e, 0x0d, 0x20, 0x72, 0x46, 0xf6,
|
||||
0x7b, 0xe0, 0xc3, 0x1e, 0x3b, 0x53, 0x23, 0x56, 0x33, 0xbe, 0xac, 0xc5, 0x04, 0xff, 0x8a, 0xc3,
|
||||
0xf3, 0x00, 0x9f, 0x36, 0xc0, 0xe1, 0x94, 0x32, 0xc1, 0x31, 0xab, 0xf4, 0xa4, 0x41, 0xba, 0xb5,
|
||||
0x20, 0xea, 0x7f, 0x28, 0x18, 0x0f, 0x76, 0x05, 0x5a, 0xf3, 0x13, 0x0c, 0xee, 0x4f, 0x30, 0x57,
|
||||
0x1d, 0xbf, 0x8b, 0xd8, 0xeb, 0xdf, 0x7b, 0x58, 0xc2, 0x9a, 0x49, 0x1a, 0x46, 0x21, 0x5a, 0xa5,
|
||||
0x51, 0x0b, 0xf8, 0x81, 0xee, 0x7f, 0xd7, 0xa7, 0x65, 0x34, 0xb0, 0x8c, 0xd7, 0x5e, 0xb5, 0x06,
|
||||
0x63, 0xef, 0x77, 0x56, 0x58, 0x96, 0x22, 0x95, 0xe2, 0x88, 0xd9, 0xce, 0x89, 0x54, 0xdb, 0x51,
|
||||
0xc7, 0x9b, 0xee, 0x46, 0x18, 0xd4, 0x5c, 0x3b, 0x95, 0xd9, 0x1d, 0x91, 0x82, 0xcb, 0x04, 0x07,
|
||||
0x1a, 0x5d, 0x40, 0x5d, 0x98, 0xbf, 0xc2, 0xcd, 0xb7, 0xfd, 0xf1, 0x55, 0xaf, 0xa9, 0x6f, 0x32,
|
||||
0xa3, 0x04, 0x99, 0x35, 0x97, 0x76, 0xf4, 0xa5, 0xb6, 0x14, 0x68, 0x91, 0x20, 0xe5, 0x89, 0xd6,
|
||||
0x11, 0x35, 0xb2, 0x54, 0x72, 0xb1, 0xbd, 0x97, 0x03, 0x2f, 0x71, 0x80, 0xc3, 0x69, 0x85, 0x93,
|
||||
0x28, 0x88, 0x57, 0xb7, 0x5c, 0xbd, 0xa2, 0x68, 0x35, 0xe5, 0x2c, 0xbd, 0x89, 0xe8, 0xd8, 0x9a,
|
||||
0x3d, 0x0d, 0x83, 0xfa, 0xa0, 0x69, 0xbd, 0x95, 0xd0, 0x01, 0x99, 0x91, 0x95, 0xf1, 0x46, 0x49,
|
||||
0x7a, 0xd3, 0xca, 0x6d, 0x49, 0xe8, 0x6a, 0x5a, 0x30, 0xf4, 0x71, 0x92, 0xcc, 0xa1, 0xbd, 0x92,
|
||||
0xab, 0x95, 0xfa, 0xfc, 0xd8, 0x52, 0x37, 0x26, 0xd3, 0x32, 0x37, 0x2e, 0xbc, 0x89, 0xc1, 0x0c,
|
||||
0x12, 0xa9, 0x88, 0xeb, 0x96, 0x76, 0x52, 0x6d, 0x26, 0x1c, 0xeb, 0x35, 0x13, 0x32, 0xf9, 0x70,
|
||||
0x71, 0x89, 0x39, 0x41, 0x4f, 0x72, 0x7c, 0xb8, 0xe0, 0xc6, 0x56, 0x7f, 0x76, 0x37, 0xe0, 0xdd,
|
||||
0xd5, 0x11, 0xc3, 0x7f, 0x30, 0xd8, 0x03, 0x7c, 0x33, 0x58, 0x6b, 0xeb, 0x79, 0xf5, 0x1e, 0xce,
|
||||
0x34, 0x3a, 0x77, 0x91, 0xe0, 0xa5, 0xdb, 0xf5, 0xa5, 0xad, 0x91, 0x5e, 0x83, 0x70, 0x4d, 0xa1,
|
||||
0xc4, 0x6b, 0x30, 0xb7, 0x69, 0xb5, 0x13, 0xd7, 0x5c, 0x18, 0xe5, 0x2f, 0x9b, 0x8a, 0x70, 0x55,
|
||||
0x83, 0x70, 0xc6, 0xf0, 0x11, 0xa0, 0x51, 0xa9, 0x26, 0x9d, 0xcf, 0xb7, 0x63, 0x7f, 0x0d, 0x0a,
|
||||
0x0d, 0x08, 0x7c, 0xa6, 0xab, 0x62, 0x89, 0xaa, 0x98, 0x82, 0xc2, 0xc2, 0x33, 0x61, 0xdd, 0xb2,
|
||||
0x8f, 0x05, 0xfc, 0x1e, 0xbf, 0xa1, 0x2b, 0x57, 0xf1, 0x69, 0x46, 0x6e, 0x77, 0xc4, 0xc7, 0x94,
|
||||
0x6c, 0x4b, 0x7b, 0x8f, 0x89, 0xdb, 0x70, 0x5a, 0xa8, 0xab, 0xd3, 0xaf, 0x77, 0x3c, 0xba, 0xb0,
|
||||
0x3a, 0x1f, 0x73, 0xa9, 0xd5, 0x38, 0xb0, 0x5d, 0xe2, 0x64, 0x23, 0x5a, 0x17, 0x80, 0xac, 0xf0,
|
||||
0x71, 0x57, 0xb7, 0xb7, 0x52, 0x7e, 0xb5, 0xeb, 0xf0, 0x93, 0x75, 0x6f, 0x52, 0x99, 0xd7, 0x70,
|
||||
0xd9, 0x4e, 0x03, 0x35, 0x49, 0x19, 0xed, 0xeb, 0x84, 0x4d, 0x16, 0x7b, 0xd8, 0x03, 0xde, 0x0e,
|
||||
0x85, 0x1d, 0x22, 0xb0, 0x8f, 0xfb, 0x54, 0x6f, 0x11, 0x57, 0x73, 0xec, 0x1d, 0x64, 0xad, 0xad,
|
||||
0xe6, 0x7a, 0x8c, 0xb1, 0xae, 0x5a, 0x5b, 0xde, 0xa3, 0x54, 0xf5, 0x04, 0x9a, 0xda, 0x32, 0xea,
|
||||
0x3d, 0x9d, 0xa3, 0x2c, 0x3f, 0x1d, 0x78, 0x66, 0x84, 0x2c, 0xf6, 0xde, 0x62, 0xd9, 0x6c, 0xc3,
|
||||
0x13, 0xa6, 0xf1, 0x57, 0xe6, 0x78, 0x60, 0x60, 0x27, 0xbb, 0x40, 0xd2, 0x22, 0x65, 0x7e, 0xa7,
|
||||
0x5d, 0x33, 0xe0, 0x4b, 0xbb, 0x69, 0x08, 0x7b, 0xc1, 0xe4, 0x40, 0x34, 0xaa, 0xdf, 0x98, 0x8d,
|
||||
0xbe, 0x73, 0xab, 0x9e, 0x66, 0xa2, 0x73, 0x59, 0xf1, 0x8c, 0x4c, 0x81, 0x24, 0x4a, 0xd9, 0xc1,
|
||||
0xcf, 0xc8, 0x4c, 0xc9, 0x82, 0x20, 0xee, 0xf5, 0x38, 0xa6, 0x1a, 0x7f, 0x90, 0xa9, 0x2b, 0x57,
|
||||
0x4f, 0xd9, 0xcc, 0xa2, 0xbd, 0x0c, 0x54, 0x17, 0x9d, 0x4c, 0x94, 0xc5, 0x6b, 0xb2, 0x60, 0x26,
|
||||
0x27, 0x5c, 0x2e, 0xa0, 0x41, 0x18, 0x52, 0xf7, 0x1a, 0xb1, 0x88, 0x85, 0xb6, 0x9d, 0x8e, 0x0e,
|
||||
0x3a, 0x89, 0x0a, 0x09, 0x43, 0x7f, 0xd0, 0x88, 0x46, 0x98, 0x85, 0xcc, 0xef, 0x7b, 0xce, 0x91,
|
||||
0xf3, 0x24, 0xcd, 0x1b, 0xd1, 0x34, 0x11, 0x24, 0x47, 0x60, 0x43, 0x67, 0x67, 0x33, 0x40, 0x42,
|
||||
0xb3, 0xe6, 0xd6, 0x35, 0x23, 0x89, 0xc8, 0x02, 0xa9, 0x5a, 0xd3, 0xa5, 0x64, 0x78, 0xa3, 0xd9,
|
||||
0x45, 0x74, 0x90, 0x95, 0x41, 0x9d, 0x01, 0xab, 0x91, 0xe4, 0x50, 0x26, 0x6b, 0xec, 0xa8, 0x01,
|
||||
0xa3, 0x16, 0x72, 0x08, 0xd2, 0x3e, 0xff, 0x6a, 0x56, 0x6d, 0x00, 0xd5, 0x5b, 0xe1, 0xaa, 0x7a,
|
||||
0x12, 0x74, 0xef, 0x45, 0x6e, 0xef, 0x31, 0xe8, 0x0e, 0x2c, 0x1d, 0xe1, 0xc7, 0x32, 0x96, 0xa5,
|
||||
0x2f, 0xfb, 0x0f, 0xe4, 0xff, 0x77, 0x44, 0x75, 0x1f, 0x50, 0x0e, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/settings_pin.htm, do not edit!!
|
||||
const uint16_t PAGE_settings_pin_length = 471;
|
||||
const uint8_t PAGE_settings_pin[] PROGMEM = {
|
||||
|
3463
wled00/html_ui.h
3463
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
uint16_t len = elem["len"];
|
||||
stop = (len > 0) ? start + len : seg.stop;
|
||||
}
|
||||
// 2D segments
|
||||
uint16_t startY = elem["startY"] | seg.startY;
|
||||
uint16_t stopY = elem["stopY"] | seg.stopY;
|
||||
|
||||
//repeat, multiplies segment until all LEDs are used, or max segments reached
|
||||
bool repeat = elem["rpt"] | false;
|
||||
@ -31,6 +34,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
for (byte i=id+1; i<strip.getMaxSegments(); i++) {
|
||||
start = start + len;
|
||||
if (start >= strip.getLengthTotal()) break;
|
||||
//TODO: add support for 2D
|
||||
elem["start"] = start;
|
||||
elem["stop"] = start + len;
|
||||
elem["rev"] = !elem["rev"]; // alternate reverse on even/odd segments
|
||||
@ -78,7 +82,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
of = offsetAbs;
|
||||
}
|
||||
if (stop > start && of > len -1) of = len -1;
|
||||
strip.setSegment(id, start, stop, grp, spc, of);
|
||||
strip.setSegment(id, start, stop, grp, spc, of, startY, stopY);
|
||||
|
||||
byte segbri = 0;
|
||||
if (getVal(elem["bri"], &segbri)) {
|
||||
@ -146,6 +150,10 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||
// 2D options
|
||||
seg.setOption(SEG_OPTION_REVERSED_Y, elem[F("rY")] | seg.getOption(SEG_OPTION_REVERSED_Y));
|
||||
seg.setOption(SEG_OPTION_MIRROR_Y , elem[F("mY")] | seg.getOption(SEG_OPTION_MIRROR_Y ));
|
||||
seg.setOption(SEG_OPTION_TRANSPOSE , elem[F("tp")] | seg.getOption(SEG_OPTION_TRANSPOSE ));
|
||||
|
||||
byte fx = seg.mode;
|
||||
if (getVal(elem["fx"], &fx, 1, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 1-255 exact value)
|
||||
@ -189,7 +197,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
set = 2;
|
||||
}
|
||||
} else { //color
|
||||
int rgbw[] = {0,0,0,0};
|
||||
uint8_t rgbw[] = {0,0,0,0};
|
||||
JsonArray icol = iarr[i];
|
||||
if (!icol.isNull()) { //array, e.g. [255,0,0]
|
||||
byte sz = icol.size();
|
||||
@ -386,6 +394,10 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
if (segmentBounds) {
|
||||
root["start"] = seg.start;
|
||||
root["stop"] = seg.stop;
|
||||
if (strip.isMatrix) {
|
||||
root[F("startY")] = seg.startY;
|
||||
root[F("stopY")] = seg.stopY;
|
||||
}
|
||||
}
|
||||
if (!forPreset) root["len"] = seg.stop - seg.start;
|
||||
root["grp"] = seg.grouping;
|
||||
@ -427,6 +439,11 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
root[F("sel")] = seg.isSelected();
|
||||
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
||||
root[F("mi")] = seg.getOption(SEG_OPTION_MIRROR);
|
||||
if (strip.isMatrix) {
|
||||
root[F("rY")] = seg.getOption(SEG_OPTION_REVERSED_Y);
|
||||
root[F("mY")] = seg.getOption(SEG_OPTION_MIRROR_Y);
|
||||
root[F("tp")] = seg.getOption(SEG_OPTION_TRANSPOSE);
|
||||
}
|
||||
}
|
||||
|
||||
void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segmentBounds)
|
||||
@ -495,6 +512,12 @@ void serializeInfo(JsonObject root)
|
||||
leds[F("maxseg")] = strip.getMaxSegments();
|
||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||
|
||||
if (strip.isMatrix) {
|
||||
JsonObject matrix = leds.createNestedObject("matrix");
|
||||
matrix["w"] = strip.matrixWidth;
|
||||
matrix["h"] = strip.matrixHeight;
|
||||
}
|
||||
|
||||
uint8_t totalLC = 0;
|
||||
JsonArray lcarr = leds.createNestedArray(F("seglc"));
|
||||
uint8_t nSegs = strip.getLastActiveSegmentId();
|
||||
|
@ -15,8 +15,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
return;
|
||||
}
|
||||
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods
|
||||
if (subPage <1 || subPage >8 || !correctPIN) return;
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods 9: N/A 10: 2D
|
||||
if (subPage <1 || subPage >10 || !correctPIN) return;
|
||||
|
||||
//WIFI SETTINGS
|
||||
if (subPage == 1)
|
||||
@ -547,6 +547,30 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
//2D panels
|
||||
if (subPage == 10)
|
||||
{
|
||||
strip.isMatrix = request->arg(F("SOMP")).toInt();
|
||||
strip.panelH = MAX(1,MIN(128,request->arg(F("PH")).toInt()));
|
||||
strip.panelW = MAX(1,MIN(128,request->arg(F("PW")).toInt()));
|
||||
strip.hPanels = MAX(1,MIN(8,request->arg(F("MPH")).toInt()));
|
||||
strip.vPanels = MAX(1,MIN(8,request->arg(F("MPV")).toInt()));
|
||||
strip.matrix.bottomStart = request->arg(F("PB")).toInt();
|
||||
strip.matrix.rightStart = request->arg(F("PR")).toInt();
|
||||
strip.matrix.vertical = request->arg(F("PV")).toInt();
|
||||
strip.matrix.serpentine = request->hasArg(F("PS"));
|
||||
for (uint8_t i=0; i<WLED_MAX_PANELS; i++) {
|
||||
char pO[8]; sprintf_P(pO, PSTR("P%d"), i);
|
||||
uint8_t l = strlen(pO); pO[l+1] = 0;
|
||||
pO[l] = 'B'; if (!request->hasArg(pO)) break;
|
||||
pO[l] = 'B'; strip.panel[i].bottomStart = request->arg(pO).toInt();
|
||||
pO[l] = 'R'; strip.panel[i].rightStart = request->arg(pO).toInt();
|
||||
pO[l] = 'V'; strip.panel[i].vertical = request->arg(pO).toInt();
|
||||
pO[l] = 'S'; strip.panel[i].serpentine = request->hasArg(pO);
|
||||
}
|
||||
strip.setUpMatrix(); // will check limits
|
||||
}
|
||||
|
||||
lastEditTime = millis();
|
||||
if (subPage != 2 && !doReboot) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||
if (subPage == 4) alexaInit();
|
||||
|
@ -476,7 +476,7 @@ void serveSettingsJS(AsyncWebServerRequest* request)
|
||||
char buf[SETTINGS_STACK_BUF_SIZE+37];
|
||||
buf[0] = 0;
|
||||
byte subPage = request->arg(F("p")).toInt();
|
||||
if (subPage > 9) {
|
||||
if (subPage > 10) {
|
||||
strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');"));
|
||||
request->send(501, "application/javascript", buf);
|
||||
return;
|
||||
@ -510,6 +510,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
else if (url.indexOf("sec") > 0) subPage = 6;
|
||||
else if (url.indexOf("dmx") > 0) subPage = 7;
|
||||
else if (url.indexOf("um") > 0) subPage = 8;
|
||||
else if (url.indexOf("2D") > 0) subPage = 10;
|
||||
else if (url.indexOf("lock") > 0) subPage = 251;
|
||||
}
|
||||
else if (url.indexOf("/update") >= 0) subPage = 9; // update page, for PIN check
|
||||
@ -542,6 +543,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
case 6: strcpy_P(s, PSTR("Security")); if (doReboot) strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break;
|
||||
case 7: strcpy_P(s, PSTR("DMX")); break;
|
||||
case 8: strcpy_P(s, PSTR("Usermods")); break;
|
||||
case 10: strcpy_P(s, PSTR("2D")); break;
|
||||
case 252: strcpy_P(s, correctPIN ? PSTR("PIN accepted") : PSTR("PIN rejected")); break;
|
||||
}
|
||||
|
||||
@ -572,6 +574,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post)
|
||||
case 7: response = request->beginResponse_P(200, "text/html", PAGE_settings_dmx, PAGE_settings_dmx_length); break;
|
||||
case 8: response = request->beginResponse_P(200, "text/html", PAGE_settings_um, PAGE_settings_um_length); break;
|
||||
case 9: response = request->beginResponse_P(200, "text/html", PAGE_update, PAGE_update_length); break;
|
||||
case 10: response = request->beginResponse_P(200, "text/html", PAGE_settings_2D, PAGE_settings_2D_length); break;
|
||||
case 251: {
|
||||
correctPIN = !strlen(settingsPIN); // lock if a pin is set
|
||||
createEditHandler(correctPIN);
|
||||
|
@ -177,7 +177,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
obuf = dest;
|
||||
olen = 0;
|
||||
|
||||
if (subPage <0 || subPage >9) return;
|
||||
if (subPage <0 || subPage >10) return;
|
||||
|
||||
if (subPage == 0)
|
||||
{
|
||||
@ -631,4 +631,33 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappendi(VERSION);
|
||||
oappend(SET_F(")\";"));
|
||||
}
|
||||
|
||||
if (subPage == 10) // 2D matrices
|
||||
{
|
||||
sappend('v',SET_F("SOMP"),strip.isMatrix);
|
||||
oappend(SET_F("resetPanels();"));
|
||||
if (strip.isMatrix) {
|
||||
sappend('v',SET_F("PH"),strip.panelH);
|
||||
sappend('v',SET_F("PW"),strip.panelW);
|
||||
sappend('v',SET_F("MPH"),strip.hPanels);
|
||||
sappend('v',SET_F("MPV"),strip.vPanels);
|
||||
sappend('v',SET_F("PB"),strip.matrix.bottomStart);
|
||||
sappend('v',SET_F("PR"),strip.matrix.rightStart);
|
||||
sappend('v',SET_F("PV"),strip.matrix.vertical);
|
||||
sappend('c',SET_F("PS"),strip.matrix.serpentine);
|
||||
// panels
|
||||
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) {
|
||||
char n[5];
|
||||
oappend(SET_F("addPanel("));
|
||||
oappend(itoa(i,n,10));
|
||||
oappend(SET_F(");"));
|
||||
char pO[8]; sprintf_P(pO, PSTR("P%d"), i);
|
||||
uint8_t l = strlen(pO); pO[l+1] = 0;
|
||||
pO[l] = 'B'; sappend('v',pO,strip.panel[i].bottomStart);
|
||||
pO[l] = 'R'; sappend('v',pO,strip.panel[i].rightStart);
|
||||
pO[l] = 'V'; sappend('v',pO,strip.panel[i].vertical);
|
||||
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user