Refactored DMX effect mode + new segement controls (#2325)

This commit is contained in:
mxklb 2022-11-19 14:10:40 +01:00
parent 43582b6319
commit 84628bd9fc
9 changed files with 100 additions and 33 deletions

View File

@ -379,6 +379,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]); CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
CJSON(DMXAddress, if_live_dmx[F("addr")]); CJSON(DMXAddress, if_live_dmx[F("addr")]);
if (!DMXAddress || DMXAddress > 510) DMXAddress = 1; if (!DMXAddress || DMXAddress > 510) DMXAddress = 1;
CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]);
if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0;
CJSON(DMXMode, if_live_dmx["mode"]); CJSON(DMXMode, if_live_dmx["mode"]);
tdd = if_live[F("timeout")] | -1; tdd = if_live[F("timeout")] | -1;
@ -837,6 +839,7 @@ void serializeConfig() {
if_live_dmx[F("uni")] = e131Universe; if_live_dmx[F("uni")] = e131Universe;
if_live_dmx[F("seqskip")] = e131SkipOutOfSequence; if_live_dmx[F("seqskip")] = e131SkipOutOfSequence;
if_live_dmx[F("addr")] = DMXAddress; if_live_dmx[F("addr")] = DMXAddress;
if_live_dmx[F("dss")] = DMXSegmentSpacing;
if_live_dmx["mode"] = DMXMode; if_live_dmx["mode"] = DMXMode;
if_live[F("timeout")] = realtimeTimeoutMs / 100; if_live[F("timeout")] = realtimeTimeoutMs / 100;

View File

@ -147,9 +147,13 @@
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels) #define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels) #define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels) #define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_EFFECT_W 7 //trigger standalone effects of WLED (13 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 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_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) #define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels)
#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (11 channels per segement)
#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (13 channels per segement)
#define DMX_MODE_PRESET 10 //apply presets (1 channel)
//Light capability byte (unused) 0bRCCCTTTT //Light capability byte (unused) 0bRCCCTTTT
//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 //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

View File

@ -148,15 +148,20 @@ Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
<i>Reboot required.</i> Check out <a href="https://github.com/LedFx/LedFx" target="_blank">LedFx</a>!<br> <i>Reboot required.</i> Check out <a href="https://github.com/LedFx/LedFx" target="_blank">LedFx</a>!<br>
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br> Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
DMX start address: <input name="DA" type="number" min="1" max="510" required><br> DMX start address: <input name="DA" type="number" min="1" max="510" required><br>
DMX segment spacing: <input name="XX" type="number" min="0" max="150" required><br>
DMX mode: DMX mode:
<select name=DM> <select name=DM>
<option value=0>Disabled</option> <option value=0>Disabled</option>
<option value=1>Single RGB</option> <option value=1>Single RGB</option>
<option value=2>Single DRGB</option> <option value=2>Single DRGB</option>
<option value=3>Effect</option> <option value=3>Effect</option>
<option value=7>Effect + White</option>
<option value=8>Effect Segment</option>
<option value=9>Effect Segment + White</option>
<option value=4>Multi RGB</option> <option value=4>Multi RGB</option>
<option value=5>Dimmer + Multi RGB</option> <option value=5>Dimmer + Multi RGB</option>
<option value=6>Multi RGBW</option> <option value=6>Multi RGBW</option>
<option value=10>Preset</option>
</select><br> </select><br>
<a href="https://kno.wled.ge/interfaces/e1.31-dmx/" target="_blank">E1.31 info</a><br> <a href="https://kno.wled.ge/interfaces/e1.31-dmx/" target="_blank">E1.31 info</a><br>
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br> Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>

View File

@ -132,7 +132,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
return; // nothing to do return; // nothing to do
break; break;
case DMX_MODE_SINGLE_RGB: // RGB only case DMX_MODE_SINGLE_RGB: // 3 channel: [R,G,B]
if (uni != e131Universe) return; if (uni != e131Universe) return;
if (availDMXLen < 3) return; if (availDMXLen < 3) return;
@ -145,7 +145,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
setRealtimePixel(i, e131_data[dataOffset+0], e131_data[dataOffset+1], e131_data[dataOffset+2], wChannel); setRealtimePixel(i, e131_data[dataOffset+0], e131_data[dataOffset+1], e131_data[dataOffset+2], wChannel);
break; break;
case DMX_MODE_SINGLE_DRGB: // Dimmer + RGB case DMX_MODE_SINGLE_DRGB: // 4 channel: [Dimmer,R,G,B]
if (uni != e131Universe) return; if (uni != e131Universe) return;
if (availDMXLen < 4) return; if (availDMXLen < 4) return;
@ -162,17 +162,33 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
setRealtimePixel(i, e131_data[dataOffset+1], e131_data[dataOffset+2], e131_data[dataOffset+3], wChannel); setRealtimePixel(i, e131_data[dataOffset+1], e131_data[dataOffset+2], e131_data[dataOffset+3], wChannel);
break; break;
case DMX_MODE_EFFECT: // Length 1: Apply Preset ID, length 11-13: apply effect config case DMX_MODE_PRESET: // 1 channel: WLED Preset number [#]
if (uni != e131Universe) return; if (uni != e131Universe || availDMXLen < 1) return;
if (availDMXLen < 11) { applyPreset(e131_data[dataOffset], CALL_MODE_NOTIFICATION);
if (availDMXLen > 1) return; return;
applyPreset(e131_data[dataOffset+0], CALL_MODE_NOTIFICATION); break;
case DMX_MODE_EFFECT: // 11 channels [bri,effectCurrent,effectSpeed,effectIntensity,effectPalette,R,G,B,R2,G2,B2]
case DMX_MODE_EFFECT_W: // 13 channels, same as above but with extra +2 white channels [..,W,W2]
case DMX_MODE_EFFECT_SEGMENT: // 11 channels per segment; max[#] = floor[512/(11+DMXSegmentSpacing)] = 46,42,39, ..
case DMX_MODE_EFFECT_SEGMENT_W: // 13 Channels per segment; max[#] = floor[512/(13+DMXSegmentSpacing)] = 39,36,34,32, ..
{
if (uni != e131Universe) return;
bool segmentUpdated = false;
bool isSegmentMode = DMXMode == DMX_MODE_EFFECT_SEGMENT || DMXMode == DMX_MODE_EFFECT_SEGMENT_W;
uint8_t dmxEffectChannels = (DMXMode == DMX_MODE_EFFECT || DMXMode == DMX_MODE_EFFECT_SEGMENT) ? 11 : 13;
for (uint8_t seg = 0; seg < strip.getSegmentsNum(); seg++) {
if (isSegmentMode)
dataOffset = DMXAddress + seg * (dmxEffectChannels + DMXSegmentSpacing);
else
dataOffset = DMXAddress;
// Modify address for Art-Net data
if (protocol == P_ARTNET && dataOffset > 0)
dataOffset--;
// Skip out of universe addresses
if (dataOffset > dmxChannels - dmxEffectChannels)
return; return;
}
if (bri != e131_data[dataOffset+0]) {
bri = e131_data[dataOffset+0];
}
if (e131_data[dataOffset+1] < strip.getModeCount()) if (e131_data[dataOffset+1] < strip.getModeCount())
effectCurrent = e131_data[dataOffset+ 1]; effectCurrent = e131_data[dataOffset+ 1];
effectSpeed = e131_data[dataOffset+ 2]; // flickers effectSpeed = e131_data[dataOffset+ 2]; // flickers
@ -184,15 +200,28 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
colSec[0] = e131_data[dataOffset+ 8]; colSec[0] = e131_data[dataOffset+ 8];
colSec[1] = e131_data[dataOffset+ 9]; colSec[1] = e131_data[dataOffset+ 9];
colSec[2] = e131_data[dataOffset+10]; colSec[2] = e131_data[dataOffset+10];
if (availDMXLen > 11) if (dmxEffectChannels == 13) {
{ col[3] = e131_data[dataOffset+11]; // white
col[3] = e131_data[dataOffset+11]; //white
colSec[3] = e131_data[dataOffset+12]; colSec[3] = e131_data[dataOffset+12];
} }
if (isSegmentMode) {
opacity = e131_data[dataOffset+ 0];
segmentUpdated |= applyValuesToSegment(seg);
} else {
if (bri != e131_data[dataOffset+0])
bri = e131_data[dataOffset+0];
transitionDelayTemp = 0; // act fast transitionDelayTemp = 0; // act fast
colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode return; // don't activate realtime live mode
}
}
if (segmentUpdated) {
transitionDelayTemp = 0;
stateUpdated(CALL_MODE_NOTIFICATION);
return;
}
break; break;
}
case DMX_MODE_MULTIPLE_DRGB: case DMX_MODE_MULTIPLE_DRGB:
case DMX_MODE_MULTIPLE_RGB: case DMX_MODE_MULTIPLE_RGB:
@ -279,7 +308,11 @@ void handleArtnetPollReply(IPAddress ipAddress) {
case DMX_MODE_SINGLE_RGB: case DMX_MODE_SINGLE_RGB:
case DMX_MODE_SINGLE_DRGB: case DMX_MODE_SINGLE_DRGB:
case DMX_MODE_PRESET:
case DMX_MODE_EFFECT: case DMX_MODE_EFFECT:
case DMX_MODE_EFFECT_W:
case DMX_MODE_EFFECT_SEGMENT:
case DMX_MODE_EFFECT_SEGMENT_W:
break; // 1 universe is enough break; // 1 universe is enough
case DMX_MODE_MULTIPLE_DRGB: case DMX_MODE_MULTIPLE_DRGB:

View File

@ -153,6 +153,7 @@ void toggleOnOff();
void applyBri(); void applyBri();
void applyFinalBri(); void applyFinalBri();
void applyValuesToSelectedSegs(); void applyValuesToSelectedSegs();
bool applyValuesToSegment(uint8_t i);
void colorUpdated(byte callMode); void colorUpdated(byte callMode);
void stateUpdated(byte callMode); void stateUpdated(byte callMode);
void updateInterfaces(uint8_t callMode); void updateInterfaces(uint8_t callMode);

View File

@ -46,6 +46,22 @@ void applyValuesToSelectedSegs()
} }
} }
// applies global legacy values to segment i (opacity, col, colSec, effectCurrent...)
bool applyValuesToSegment(uint8_t i)
{
if (i >= strip.getSegmentsNum()) {return false;}
Segment& seg = strip.getSegment(i);
if (opacity != seg.opacity) {seg.setOpacity(opacity); stateChanged = true;}
if (effectSpeed != seg.speed) {seg.speed = effectSpeed; stateChanged = true;}
if (effectIntensity != seg.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
if (effectPalette != seg.palette) {seg.palette = effectPalette; stateChanged = true;}
if (effectCurrent != seg.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
if (col0 != seg.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
if (col1 != seg.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
return stateChanged;
}
void resetTimebase() void resetTimebase()
{ {

View File

@ -266,8 +266,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (t >= 0 && t <= 63999) e131Universe = t; if (t >= 0 && t <= 63999) e131Universe = t;
t = request->arg(F("DA")).toInt(); t = request->arg(F("DA")).toInt();
if (t >= 0 && t <= 510) DMXAddress = t; if (t >= 0 && t <= 510) DMXAddress = t;
t = request->arg(F("XX")).toInt();
if (t >= 0 && t <= 150) DMXSegmentSpacing = t;
t = request->arg(F("DM")).toInt(); t = request->arg(F("DM")).toInt();
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_RGBW) DMXMode = t; if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_PRESET) DMXMode = t;
t = request->arg(F("ET")).toInt(); t = request->arg(F("ET")).toInt();
if (t > 99 && t <= 65000) realtimeTimeoutMs = t; if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
arlsForceMaxBri = request->hasArg(F("FB")); arlsForceMaxBri = request->hasArg(F("FB"));

View File

@ -388,6 +388,7 @@ WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings fo
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454 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_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 uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
WLED_GLOBAL uint16_t DMXSegmentSpacing _INIT(0); // Number of void/unused channels between each segments DMX channels
WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss
WLED_GLOBAL bool e131Multicast _INIT(false); // multicast or unicast WLED_GLOBAL bool e131Multicast _INIT(false); // multicast or unicast
WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering
@ -496,6 +497,7 @@ WLED_GLOBAL byte briOld _INIT(0); // global brightnes w
WLED_GLOBAL byte briT _INIT(0); // global brightness during transition WLED_GLOBAL byte briT _INIT(0); // global brightness during transition
WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
WLED_GLOBAL byte opacity _INIT(128); // global segment opacity (set)
// button // button
WLED_GLOBAL bool buttonPublishMqtt _INIT(false); WLED_GLOBAL bool buttonPublishMqtt _INIT(false);

View File

@ -501,6 +501,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("EM"),e131Multicast); sappend('c',SET_F("EM"),e131Multicast);
sappend('v',SET_F("EU"),e131Universe); sappend('v',SET_F("EU"),e131Universe);
sappend('v',SET_F("DA"),DMXAddress); sappend('v',SET_F("DA"),DMXAddress);
sappend('v',SET_F("XX"),DMXSegmentSpacing);
sappend('v',SET_F("DM"),DMXMode); sappend('v',SET_F("DM"),DMXMode);
sappend('v',SET_F("ET"),realtimeTimeoutMs); sappend('v',SET_F("ET"),realtimeTimeoutMs);
sappend('c',SET_F("FB"),arlsForceMaxBri); sappend('c',SET_F("FB"),arlsForceMaxBri);