WLED/wled00/e131.cpp
2020-04-10 12:30:08 +02:00

145 lines
6.5 KiB
C++

#include "wled.h"
/*
* E1.31 handler
*/
void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
//E1.31 protocol support
uint16_t uni = htons(p->universe);
uint8_t previousUniverses = uni - e131Universe;
uint16_t possibleLEDsInCurrentUniverse;
uint16_t dmxChannels = htons(p->property_value_count) -1;
// only listen for universes we're handling & allocated memory
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
if (e131SkipOutOfSequence)
if (p->sequence_number < e131LastSequenceNumber[uni-e131Universe] && p->sequence_number > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
DEBUG_PRINT("skipping E1.31 frame (last seq=");
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
DEBUG_PRINT(", current seq=");
DEBUG_PRINT(p->sequence_number);
DEBUG_PRINT(", universe=");
DEBUG_PRINT(uni);
DEBUG_PRINTLN(")");
return;
}
e131LastSequenceNumber[uni-e131Universe] = p->sequence_number;
// update status info
realtimeIP = clientIP;
switch (DMXMode) {
case DMX_MODE_DISABLED:
return; // nothing to do
break;
case DMX_MODE_SINGLE_RGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 3) return;
arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, p->property_values[DMXAddress+0], p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], 0);
break;
case DMX_MODE_SINGLE_DRGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 4) return;
arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
strip.setBrightness(bri);
}
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], p->property_values[DMXAddress+3], 0);
break;
case DMX_MODE_EFFECT:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 11) return;
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
}
if (p->property_values[DMXAddress+1] < MODE_COUNT)
effectCurrent = p->property_values[DMXAddress+ 1];
effectSpeed = p->property_values[DMXAddress+ 2]; // flickers
effectIntensity = p->property_values[DMXAddress+ 3];
effectPalette = p->property_values[DMXAddress+ 4];
col[0] = p->property_values[DMXAddress+ 5];
col[1] = p->property_values[DMXAddress+ 6];
col[2] = p->property_values[DMXAddress+ 7];
colSec[0] = p->property_values[DMXAddress+ 8];
colSec[1] = p->property_values[DMXAddress+ 9];
colSec[2] = p->property_values[DMXAddress+10];
if (dmxChannels-DMXAddress+1 > 11)
{
col[3] = p->property_values[DMXAddress+11]; //white
colSec[3] = p->property_values[DMXAddress+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode
break;
case DMX_MODE_MULTIPLE_RGB:
arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
if (previousUniverses == 0) {
// first universe of this fixture
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[DMXAddress+i*3+0], p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
}
}
break;
case DMX_MODE_MULTIPLE_DRGB:
arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
if (previousUniverses == 0) {
// first universe of this fixture
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
strip.setBrightness(bri);
}
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], p->property_values[DMXAddress+i*3+3], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
}
}
break;
default:
DEBUG_PRINTLN("unknown E1.31 DMX mode");
return; // nothing to do
break;
}
e131NewData = true;
}