Refactored DMX effect mode + new segement controls (#2325)
This commit is contained in:
parent
43582b6319
commit
84628bd9fc
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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,38 +162,67 @@ 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);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bri != e131_data[dataOffset+0]) {
|
|
||||||
bri = e131_data[dataOffset+0];
|
|
||||||
}
|
|
||||||
if (e131_data[dataOffset+1] < strip.getModeCount())
|
|
||||||
effectCurrent = e131_data[dataOffset+ 1];
|
|
||||||
effectSpeed = e131_data[dataOffset+ 2]; // flickers
|
|
||||||
effectIntensity = e131_data[dataOffset+ 3];
|
|
||||||
effectPalette = e131_data[dataOffset+ 4];
|
|
||||||
col[0] = e131_data[dataOffset+ 5];
|
|
||||||
col[1] = e131_data[dataOffset+ 6];
|
|
||||||
col[2] = e131_data[dataOffset+ 7];
|
|
||||||
colSec[0] = e131_data[dataOffset+ 8];
|
|
||||||
colSec[1] = e131_data[dataOffset+ 9];
|
|
||||||
colSec[2] = e131_data[dataOffset+10];
|
|
||||||
if (availDMXLen > 11)
|
|
||||||
{
|
|
||||||
col[3] = e131_data[dataOffset+11]; //white
|
|
||||||
colSec[3] = e131_data[dataOffset+12];
|
|
||||||
}
|
|
||||||
transitionDelayTemp = 0; // act fast
|
|
||||||
colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP
|
|
||||||
return; // don't activate realtime live mode
|
|
||||||
break;
|
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;
|
||||||
|
|
||||||
|
if (e131_data[dataOffset+1] < strip.getModeCount())
|
||||||
|
effectCurrent = e131_data[dataOffset+ 1];
|
||||||
|
effectSpeed = e131_data[dataOffset+ 2]; // flickers
|
||||||
|
effectIntensity = e131_data[dataOffset+ 3];
|
||||||
|
effectPalette = e131_data[dataOffset+ 4];
|
||||||
|
col[0] = e131_data[dataOffset+ 5];
|
||||||
|
col[1] = e131_data[dataOffset+ 6];
|
||||||
|
col[2] = e131_data[dataOffset+ 7];
|
||||||
|
colSec[0] = e131_data[dataOffset+ 8];
|
||||||
|
colSec[1] = e131_data[dataOffset+ 9];
|
||||||
|
colSec[2] = e131_data[dataOffset+10];
|
||||||
|
if (dmxEffectChannels == 13) {
|
||||||
|
col[3] = e131_data[dataOffset+11]; // white
|
||||||
|
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
|
||||||
|
colorUpdated(CALL_MODE_NOTIFICATION); // don't send UDP
|
||||||
|
return; // don't activate realtime live mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (segmentUpdated) {
|
||||||
|
transitionDelayTemp = 0;
|
||||||
|
stateUpdated(CALL_MODE_NOTIFICATION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DMX_MODE_MULTIPLE_DRGB:
|
case DMX_MODE_MULTIPLE_DRGB:
|
||||||
case DMX_MODE_MULTIPLE_RGB:
|
case DMX_MODE_MULTIPLE_RGB:
|
||||||
case DMX_MODE_MULTIPLE_RGBW:
|
case DMX_MODE_MULTIPLE_RGBW:
|
||||||
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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"));
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user