kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Refactored DMX effect mode + new segement controls (#2325)
							rodzic
							
								
									43582b6319
								
							
						
					
					
						commit
						84628bd9fc
					
				|  | @ -379,6 +379,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; | ||||
|  | @ -837,6 +839,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; | ||||
|  |  | |||
|  | @ -147,9 +147,13 @@ | |||
| #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_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_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 (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
 | ||||
| //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> | ||||
|  |  | |||
|  | @ -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,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); | ||||
|       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); | ||||
|         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
 | ||||
|     case DMX_MODE_PRESET:       // 1 channel: WLED Preset number [#]
 | ||||
|       if (uni != e131Universe || availDMXLen < 1) return; | ||||
|       applyPreset(e131_data[dataOffset], CALL_MODE_NOTIFICATION); | ||||
|       return; | ||||
|       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_RGB: | ||||
|     case DMX_MODE_MULTIPLE_RGBW: | ||||
|  | @ -279,7 +308,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: | ||||
|  |  | |||
|  | @ -153,6 +153,7 @@ void toggleOnOff(); | |||
| void applyBri(); | ||||
| void applyFinalBri(); | ||||
| void applyValuesToSelectedSegs(); | ||||
| bool applyValuesToSegment(uint8_t i); | ||||
| void colorUpdated(byte callMode); | ||||
| void stateUpdated(byte 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() | ||||
| { | ||||
|  |  | |||
|  | @ -266,8 +266,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")); | ||||
|  |  | |||
|  | @ -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 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
 | ||||
|  | @ -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 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 opacity             _INIT(128);           // global segment opacity (set)
 | ||||
| 
 | ||||
| // button
 | ||||
| WLED_GLOBAL bool buttonPublishMqtt                            _INIT(false); | ||||
|  |  | |||
|  | @ -501,6 +501,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); | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 mxklb
						mxklb