Merge pull request #1738 from blazoncek/dynamic-led-map

Dynamic LED map creation from JSON file
This commit is contained in:
Aircoookie 2021-02-13 01:07:52 +01:00 committed by GitHub
commit d56ab6c971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 24 deletions

View File

@ -24,6 +24,8 @@
Modified for WLED Modified for WLED
*/ */
#include "wled.h"
#ifndef WS2812FX_h #ifndef WS2812FX_h
#define WS2812FX_h #define WS2812FX_h
@ -847,7 +849,11 @@ class WS2812FX {
void void
blendPixelColor(uint16_t n, uint32_t color, uint8_t blend), blendPixelColor(uint16_t n, uint32_t color, uint8_t blend),
startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot); startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot),
deserializeMap(void);
uint16_t* customMappingTable = nullptr;
uint16_t customMappingSize = 0;
uint32_t _lastPaletteChange = 0; uint32_t _lastPaletteChange = 0;
uint32_t _lastShow = 0; uint32_t _lastShow = 0;

View File

@ -27,27 +27,26 @@
#include "FX.h" #include "FX.h"
#include "palettes.h" #include "palettes.h"
//enable custom per-LED mapping. This can allow for better effects on matrices or special displays
//#define WLED_CUSTOM_LED_MAPPING
#ifdef WLED_CUSTOM_LED_MAPPING
//this is just an example (30 LEDs). It will first set all even, then all uneven LEDs.
const uint16_t customMappingTable[] = {
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29};
//another example. Switches direction every 5 LEDs.
/*const uint16_t customMappingTable[] = {
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25};*/
const uint16_t customMappingSize = sizeof(customMappingTable)/sizeof(uint16_t); //30 in example
#endif
#ifndef PWM_INDEX #ifndef PWM_INDEX
#define PWM_INDEX 0 #define PWM_INDEX 0
#endif #endif
/*
Custom per-LED mapping has moved!
Create a file "ledmap.json" using the edit page.
this is just an example (30 LEDs). It will first set all even, then all uneven LEDs.
{"map":[
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]}
another example. Switches direction every 5 LEDs.
{"map":[
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]
*/
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst) void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
{ {
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return; if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
@ -63,6 +62,8 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
_lengthRaw += LED_SKIP_AMOUNT; _lengthRaw += LED_SKIP_AMOUNT;
} }
deserializeMap();
bus->Begin((NeoPixelType)ty, _lengthRaw); bus->Begin((NeoPixelType)ty, _lengthRaw);
_segments[0].start = 0; _segments[0].start = 0;
@ -189,9 +190,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
int16_t indexSet = realIndex + (reversed ? -j : j); int16_t indexSet = realIndex + (reversed ? -j : j);
int16_t indexSetRev = indexSet; int16_t indexSetRev = indexSet;
if (reverseMode) indexSetRev = REV(indexSet); if (reverseMode) indexSetRev = REV(indexSet);
#ifdef WLED_CUSTOM_LED_MAPPING
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
#endif
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) { if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) {
bus->SetPixelColor(indexSet + skip, col); bus->SetPixelColor(indexSet + skip, col);
if (IS_MIRROR) { //set the corresponding mirrored pixel if (IS_MIRROR) { //set the corresponding mirrored pixel
@ -205,9 +204,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
} }
} else { //live data, etc. } else { //live data, etc.
if (reverseMode) i = REV(i); if (reverseMode) i = REV(i);
#ifdef WLED_CUSTOM_LED_MAPPING
if (i < customMappingSize) i = customMappingTable[i]; if (i < customMappingSize) i = customMappingTable[i];
#endif
bus->SetPixelColor(i + skip, col); bus->SetPixelColor(i + skip, col);
} }
if (skip && i == 0) { if (skip && i == 0) {
@ -482,9 +479,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
{ {
i = realPixelIndex(i); i = realPixelIndex(i);
#ifdef WLED_CUSTOM_LED_MAPPING
if (i < customMappingSize) i = customMappingTable[i]; if (i < customMappingSize) i = customMappingTable[i];
#endif
if (_skipFirstMode) i += LED_SKIP_AMOUNT; if (_skipFirstMode) i += LED_SKIP_AMOUNT;
@ -1006,6 +1001,31 @@ void WS2812FX::setRgbwPwm(void) {
void WS2812FX::setRgbwPwm() {} void WS2812FX::setRgbwPwm() {}
#endif #endif
//load custom mapping table from JSON file
void WS2812FX::deserializeMap(void) {
if (!WLED_FS.exists("/ledmap.json")) return;
DynamicJsonDocument doc(JSON_BUFFER_SIZE); // full sized buffer for larger maps
DEBUG_PRINTLN(F("Reading LED map from /ledmap.json..."));
if (!readObjectFromFile("/ledmap.json", nullptr, &doc)) return; //if file does not exist just exit
if (customMappingTable != nullptr) {
delete[] customMappingTable;
customMappingTable = nullptr;
customMappingSize = 0;
}
JsonArray map = doc[F("map")];
if (!map.isNull() && map.size()) { // not an empty map
customMappingSize = map.size();
customMappingTable = new uint16_t[customMappingSize];
for (uint16_t i=0; i<customMappingSize; i++) {
customMappingTable[i] = (uint16_t) map[i];
}
}
}
//gamma 2.8 lookup table used for color correction //gamma 2.8 lookup table used for color correction
byte gammaT[] = { byte gammaT[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,