From 3d89588eb11b6569dcb4275563b3ab20418b8a54 Mon Sep 17 00:00:00 2001 From: sunbowch Date: Fri, 27 Nov 2020 11:37:39 +0100 Subject: [PATCH 1/2] mutiple RGBW leds support for DMX control RGBW leds can be individually adressed through E1.31 control. -Added option 'Multi RGBW' to the settings -Modified e131.cpp accordingly -Tuned other parameters to make it work --- wled00/const.h | 1 + wled00/data/settings_sync.htm | 1 + wled00/e131.cpp | 22 ++++++++++++++++++++++ wled00/set.cpp | 2 +- wled00/wled.h | 2 +- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/wled00/const.h b/wled00/const.h index 8dc1a286..d7148a57 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -71,6 +71,7 @@ #define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels) #define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels) #define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels) +#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels) //Light capability byte (unused) 0bRRCCTTTT //bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 89030c3c..bd34c75f 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -64,6 +64,7 @@ DMX mode: +
E1.31 info
Timeout: ms
diff --git a/wled00/e131.cpp b/wled00/e131.cpp index b4252d34..af0ae770 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -185,6 +185,28 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ } break; } + case DMX_MODE_MULTIPLE_RGBW: //Implementation of RGBW leds + { + const byte dmxChannelsperLed=4; //4 DMX Channels/Led + const byte ledsPerUniverse=128; //Max.128 leds/Universe + realtimeLock(realtimeTimeoutMs, mde); + if (realtimeOverride) return; + uint16_t previousLeds, dmxOffset; + if (previousUniverses == 0) { + if (dmxChannels-DMXAddress < 1) return; + dmxOffset = DMXAddress; + previousLeds = 0; + } else{ + dmxOffset = (protocol == P_ARTNET) ? 0 : 1; + uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / dmxChannelsperLed; + previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * ledsPerUniverse; // Max leds/universe is only 128 with 4 Ch./led + } + uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / dmxChannelsperLed; + for (uint16_t i = previousLeds; i < ledsTotal; i++) { + setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++]); + } + break; + } default: DEBUG_PRINTLN(F("unknown E1.31 DMX mode")); return; // nothing to do diff --git a/wled00/set.cpp b/wled00/set.cpp index 96e0b85f..2e9eff3a 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -152,7 +152,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) t = request->arg(F("DA")).toInt(); if (t >= 0 && t <= 510) DMXAddress = t; t = request->arg(F("DM")).toInt(); - if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_DRGB) DMXMode = t; + if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_RGBW) DMXMode = t; t = request->arg(F("ET")).toInt(); if (t > 99 && t <= 65000) realtimeTimeoutMs = t; arlsForceMaxBri = request->hasArg(F("FB")); diff --git a/wled00/wled.h b/wled00/wled.h index e2add60b..61ff6a38 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -262,7 +262,7 @@ WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this #endif WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes) WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454 -WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.) +WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGBW-1); // DMX mode (s.a.) WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol] WLED_GLOBAL byte DMXOldDimmer _INIT(0); // only update brightness on change WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss From 88e0da765c768c48bc93855c0e2107ef25cab05d Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 1 Dec 2020 14:40:00 +0100 Subject: [PATCH 2/2] Remove code duplication for RGBW --- wled00/e131.cpp | 45 ++++++++++++++++-------------------------- wled00/html_settings.h | 3 ++- wled00/wled.h | 2 +- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/wled00/e131.cpp b/wled00/e131.cpp index af0ae770..58d63779 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -1,6 +1,7 @@ #include "wled.h" -#define MAX_LEDS_PER_UNIVERSE 170 +#define MAX_3_CH_LEDS_PER_UNIVERSE 170 +#define MAX_4_CH_LEDS_PER_UNIVERSE 128 #define MAX_CHANNELS_PER_UNIVERSE 512 /* @@ -161,8 +162,12 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ case DMX_MODE_MULTIPLE_DRGB: case DMX_MODE_MULTIPLE_RGB: + case DMX_MODE_MULTIPLE_RGBW: { realtimeLock(realtimeTimeoutMs, mde); + bool is4Chan = (DMXMode == DMX_MODE_MULTIPLE_RGBW); + const uint16_t dmxChannelsPerLed = is4Chan ? 4 : 3; + const uint16_t ledsPerUniverse = is4Chan ? MAX_4_CH_LEDS_PER_UNIVERSE : MAX_3_CH_LEDS_PER_UNIVERSE; if (realtimeOverride) return; uint16_t previousLeds, dmxOffset; if (previousUniverses == 0) { @@ -176,37 +181,21 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ } else { // All subsequent universes start at the first channel. dmxOffset = (protocol == P_ARTNET) ? 0 : 1; - uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / 3; - previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * MAX_LEDS_PER_UNIVERSE; + uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / dmxChannelsPerLed; + previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * ledsPerUniverse; } - uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / 3; - for (uint16_t i = previousLeds; i < ledsTotal; i++) { - setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], 0); + uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / dmxChannelsPerLed; + if (!is4Chan) { + for (uint16_t i = previousLeds; i < ledsTotal; i++) { + setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], 0); + } + } else { + for (uint16_t i = previousLeds; i < ledsTotal; i++) { + setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++]); + } } break; } - case DMX_MODE_MULTIPLE_RGBW: //Implementation of RGBW leds - { - const byte dmxChannelsperLed=4; //4 DMX Channels/Led - const byte ledsPerUniverse=128; //Max.128 leds/Universe - realtimeLock(realtimeTimeoutMs, mde); - if (realtimeOverride) return; - uint16_t previousLeds, dmxOffset; - if (previousUniverses == 0) { - if (dmxChannels-DMXAddress < 1) return; - dmxOffset = DMXAddress; - previousLeds = 0; - } else{ - dmxOffset = (protocol == P_ARTNET) ? 0 : 1; - uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / dmxChannelsperLed; - previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * ledsPerUniverse; // Max leds/universe is only 128 with 4 Ch./led - } - uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / dmxChannelsperLed; - for (uint16_t i = previousLeds; i < ledsTotal; i++) { - setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++]); - } - break; - } default: DEBUG_PRINTLN(F("unknown E1.31 DMX mode")); return; // nothing to do diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 183a9e11..23b840ca 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -238,7 +238,8 @@ type="checkbox" name="ES">
DMX start address:
DMX mode:

E1.31 info
Timeout: ms
Force max brightness:
diff --git a/wled00/wled.h b/wled00/wled.h index 61ff6a38..e2add60b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -262,7 +262,7 @@ WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this #endif WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes) WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454 -WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGBW-1); // DMX mode (s.a.) +WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.) WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol] WLED_GLOBAL byte DMXOldDimmer _INIT(0); // only update brightness on change WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss