Merge pull request #2891 from mxklb/pr_fxsegs
Refactored DMX effect mode + new segment controls
This commit is contained in:
commit
39edb1ad37
@ -404,6 +404,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
|
||||
CJSON(DMXAddress, if_live_dmx[F("addr")]);
|
||||
if (!DMXAddress || DMXAddress > 510) DMXAddress = 1;
|
||||
CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]);
|
||||
if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0;
|
||||
CJSON(DMXMode, if_live_dmx["mode"]);
|
||||
|
||||
tdd = if_live[F("timeout")] | -1;
|
||||
@ -864,6 +866,7 @@ void serializeConfig() {
|
||||
if_live_dmx[F("uni")] = e131Universe;
|
||||
if_live_dmx[F("seqskip")] = e131SkipOutOfSequence;
|
||||
if_live_dmx[F("addr")] = DMXAddress;
|
||||
if_live_dmx[F("dss")] = DMXSegmentSpacing;
|
||||
if_live_dmx["mode"] = DMXMode;
|
||||
|
||||
if_live[F("timeout")] = realtimeTimeoutMs / 100;
|
||||
|
@ -169,10 +169,14 @@
|
||||
#define DMX_MODE_DISABLED 0 //not used
|
||||
#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_EFFECT 3 //trigger standalone effects of WLED (11 channels)
|
||||
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (15 channels)
|
||||
#define DMX_MODE_EFFECT_W 7 //trigger standalone effects of WLED (18 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)
|
||||
#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (15 channels per segement)
|
||||
#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (18 channels per segement)
|
||||
#define DMX_MODE_PRESET 10 //apply presets (1 channel)
|
||||
|
||||
//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
|
||||
|
@ -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>
|
||||
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 segment spacing: <input name="XX" type="number" min="0" max="150" required><br>
|
||||
DMX mode:
|
||||
<select name=DM>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>Single RGB</option>
|
||||
<option value=2>Single DRGB</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=5>Dimmer + Multi RGB</option>
|
||||
<option value=6>Multi RGBW</option>
|
||||
<option value=10>Preset</option>
|
||||
</select><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>
|
||||
|
105
wled00/e131.cpp
105
wled00/e131.cpp
@ -132,7 +132,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
|
||||
return; // nothing to do
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_RGB: // RGB only
|
||||
case DMX_MODE_SINGLE_RGB: // 3 channel: [R,G,B]
|
||||
if (uni != e131Universe) 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);
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_DRGB: // Dimmer + RGB
|
||||
case DMX_MODE_SINGLE_DRGB: // 4 channel: [Dimmer,R,G,B]
|
||||
if (uni != e131Universe) return;
|
||||
if (availDMXLen < 4) return;
|
||||
|
||||
@ -162,38 +162,77 @@ 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);
|
||||
break;
|
||||
|
||||
case DMX_MODE_EFFECT: // Length 1: Apply Preset ID, length 11-13: apply effect config
|
||||
if (uni != e131Universe) return;
|
||||
if (availDMXLen < 11) {
|
||||
if (availDMXLen > 1) return;
|
||||
applyPreset(e131_data[dataOffset+0], CALL_MODE_NOTIFICATION);
|
||||
case DMX_MODE_PRESET: // 2 channel: [Dimmer,Preset]
|
||||
if (uni != e131Universe || availDMXLen < 2) return;
|
||||
applyPreset(e131_data[dataOffset+1], CALL_MODE_NOTIFICATION);
|
||||
if (bri != e131_data[dataOffset]) {
|
||||
bri = e131_data[dataOffset];
|
||||
strip.setBrightness(bri, true);
|
||||
}
|
||||
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;
|
||||
|
||||
case DMX_MODE_EFFECT: // 15 channels [bri,effectCurrent,effectSpeed,effectIntensity,effectPalette,effectOption,R,G,B,R2,G2,B2,R3,G3,B3]
|
||||
case DMX_MODE_EFFECT_W: // 18 channels, same as above but with extra +3 white channels [..,W,W2,W3]
|
||||
case DMX_MODE_EFFECT_SEGMENT: // 15 channels per segment;
|
||||
case DMX_MODE_EFFECT_SEGMENT_W: // 18 Channels per segment;
|
||||
{
|
||||
if (uni != e131Universe) return;
|
||||
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) ? 15 : 18;
|
||||
for (uint8_t id = 0; id < strip.getSegmentsNum(); id++) {
|
||||
Segment& seg = strip.getSegment(id);
|
||||
if (isSegmentMode)
|
||||
dataOffset = DMXAddress + id * (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 + 1)
|
||||
return;
|
||||
|
||||
if (e131_data[dataOffset+1] < strip.getModeCount())
|
||||
if (e131_data[dataOffset+1] != seg.mode) seg.setMode( e131_data[dataOffset+1]);
|
||||
if (e131_data[dataOffset+2] != seg.speed) seg.speed = e131_data[dataOffset+2];
|
||||
if (e131_data[dataOffset+3] != seg.intensity) seg.intensity = e131_data[dataOffset+3];
|
||||
if (e131_data[dataOffset+4] != seg.palette) seg.setPalette(e131_data[dataOffset+4]);
|
||||
|
||||
uint8_t segOption = (uint8_t)floor(e131_data[dataOffset+5]/64.0);
|
||||
if (segOption == 0 && (seg.mirror || seg.reverse )) {seg.setOption(SEG_OPTION_MIRROR, false); seg.setOption(SEG_OPTION_REVERSED, false);}
|
||||
if (segOption == 1 && (seg.mirror || !seg.reverse)) {seg.setOption(SEG_OPTION_MIRROR, false); seg.setOption(SEG_OPTION_REVERSED, true);}
|
||||
if (segOption == 2 && (!seg.mirror || seg.reverse )) {seg.setOption(SEG_OPTION_MIRROR, true); seg.setOption(SEG_OPTION_REVERSED, false);}
|
||||
if (segOption == 3 && (!seg.mirror || !seg.reverse)) {seg.setOption(SEG_OPTION_MIRROR, true); seg.setOption(SEG_OPTION_REVERSED, true);}
|
||||
|
||||
uint32_t colors[3];
|
||||
byte whites[3] = {0,0,0};
|
||||
if (dmxEffectChannels == 18) {
|
||||
whites[0] = e131_data[dataOffset+15];
|
||||
whites[1] = e131_data[dataOffset+16];
|
||||
whites[2] = e131_data[dataOffset+17];
|
||||
}
|
||||
colors[0] = RGBW32(e131_data[dataOffset+ 6], e131_data[dataOffset+ 7], e131_data[dataOffset+ 8], whites[0]);
|
||||
colors[1] = RGBW32(e131_data[dataOffset+ 9], e131_data[dataOffset+10], e131_data[dataOffset+11], whites[1]);
|
||||
colors[2] = RGBW32(e131_data[dataOffset+12], e131_data[dataOffset+13], e131_data[dataOffset+14], whites[2]);
|
||||
if (colors[0] != seg.colors[0]) seg.setColor(0, colors[0]);
|
||||
if (colors[1] != seg.colors[1]) seg.setColor(1, colors[1]);
|
||||
if (colors[2] != seg.colors[2]) seg.setColor(2, colors[2]);
|
||||
|
||||
// Set segment opacity or global brightness
|
||||
if (isSegmentMode) {
|
||||
if (e131_data[dataOffset] != seg.opacity) seg.setOpacity(e131_data[dataOffset]);
|
||||
} else if ( id == strip.getSegmentsNum()-1 ) {
|
||||
if (bri != e131_data[dataOffset]) {
|
||||
bri = e131_data[dataOffset];
|
||||
strip.setBrightness(bri, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
case DMX_MODE_MULTIPLE_DRGB:
|
||||
case DMX_MODE_MULTIPLE_RGB:
|
||||
case DMX_MODE_MULTIPLE_RGBW:
|
||||
@ -279,7 +318,11 @@ void handleArtnetPollReply(IPAddress ipAddress) {
|
||||
|
||||
case DMX_MODE_SINGLE_RGB:
|
||||
case DMX_MODE_SINGLE_DRGB:
|
||||
case DMX_MODE_PRESET:
|
||||
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
|
||||
|
||||
case DMX_MODE_MULTIPLE_DRGB:
|
||||
|
@ -284,8 +284,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t >= 0 && t <= 63999) e131Universe = t;
|
||||
t = request->arg(F("DA")).toInt();
|
||||
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();
|
||||
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();
|
||||
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
|
||||
arlsForceMaxBri = request->hasArg(F("FB"));
|
||||
|
@ -405,6 +405,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 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 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 bool e131Multicast _INIT(false); // multicast or unicast
|
||||
WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering
|
||||
|
@ -508,6 +508,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',SET_F("EM"),e131Multicast);
|
||||
sappend('v',SET_F("EU"),e131Universe);
|
||||
sappend('v',SET_F("DA"),DMXAddress);
|
||||
sappend('v',SET_F("XX"),DMXSegmentSpacing);
|
||||
sappend('v',SET_F("DM"),DMXMode);
|
||||
sappend('v',SET_F("ET"),realtimeTimeoutMs);
|
||||
sappend('c',SET_F("FB"),arlsForceMaxBri);
|
||||
|
Loading…
Reference in New Issue
Block a user