2020-03-31 02:38:08 +02:00
|
|
|
#include "wled.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* E1.31 handler
|
|
|
|
*/
|
|
|
|
|
2020-04-13 00:42:27 +02:00
|
|
|
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
|
2020-03-31 02:38:08 +02:00
|
|
|
//E1.31 protocol support
|
|
|
|
|
2020-04-13 00:42:27 +02:00
|
|
|
uint16_t uni = 0, dmxChannels = 0;
|
|
|
|
uint8_t* e131_data = nullptr;
|
|
|
|
uint8_t seq = 0, mde = REALTIME_MODE_E131;
|
|
|
|
|
|
|
|
if (isArtnet)
|
|
|
|
{
|
|
|
|
uni = p->art_universe;
|
|
|
|
dmxChannels = htons(p->art_length);
|
|
|
|
e131_data = p->art_data;
|
|
|
|
seq = p->art_sequence_number;
|
|
|
|
mde = REALTIME_MODE_ARTNET;
|
|
|
|
} else {
|
|
|
|
uni = htons(p->universe);
|
|
|
|
dmxChannels = htons(p->property_value_count) -1;
|
|
|
|
e131_data = p->property_values;
|
|
|
|
seq = p->sequence_number;
|
|
|
|
}
|
2020-03-31 02:38:08 +02:00
|
|
|
|
|
|
|
// only listen for universes we're handling & allocated memory
|
|
|
|
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
|
|
|
|
|
2020-04-13 00:42:27 +02:00
|
|
|
uint8_t previousUniverses = uni - e131Universe;
|
|
|
|
uint16_t possibleLEDsInCurrentUniverse;
|
|
|
|
|
2020-03-31 02:38:08 +02:00
|
|
|
if (e131SkipOutOfSequence)
|
2020-04-13 00:42:27 +02:00
|
|
|
if (seq < e131LastSequenceNumber[uni-e131Universe] && seq > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
|
2020-03-31 02:38:08 +02:00
|
|
|
DEBUG_PRINT("skipping E1.31 frame (last seq=");
|
|
|
|
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
|
|
|
|
DEBUG_PRINT(", current seq=");
|
2020-04-13 00:42:27 +02:00
|
|
|
DEBUG_PRINT(seq);
|
2020-03-31 02:38:08 +02:00
|
|
|
DEBUG_PRINT(", universe=");
|
|
|
|
DEBUG_PRINT(uni);
|
|
|
|
DEBUG_PRINTLN(")");
|
|
|
|
return;
|
|
|
|
}
|
2020-04-13 00:42:27 +02:00
|
|
|
e131LastSequenceNumber[uni-e131Universe] = seq;
|
2020-03-31 02:38:08 +02:00
|
|
|
|
|
|
|
// update status info
|
|
|
|
realtimeIP = clientIP;
|
2020-05-03 20:57:53 +02:00
|
|
|
byte wChannel = 0;
|
2020-03-31 02:38:08 +02:00
|
|
|
|
|
|
|
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;
|
2020-04-13 00:42:27 +02:00
|
|
|
realtimeLock(realtimeTimeoutMs, mde);
|
2020-04-30 01:52:36 +02:00
|
|
|
if (realtimeOverride) return;
|
2020-05-03 20:57:53 +02:00
|
|
|
wChannel = (dmxChannels-DMXAddress+1 > 3) ? e131_data[DMXAddress+3] : 0;
|
2020-03-31 02:38:08 +02:00
|
|
|
for (uint16_t i = 0; i < ledCount; i++)
|
2020-05-03 20:57:53 +02:00
|
|
|
setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel);
|
2020-03-31 02:38:08 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_MODE_SINGLE_DRGB:
|
|
|
|
if (uni != e131Universe) return;
|
|
|
|
if (dmxChannels-DMXAddress+1 < 4) return;
|
2020-04-13 00:42:27 +02:00
|
|
|
realtimeLock(realtimeTimeoutMs, mde);
|
2020-04-30 01:52:36 +02:00
|
|
|
if (realtimeOverride) return;
|
2020-05-03 20:57:53 +02:00
|
|
|
wChannel = (dmxChannels-DMXAddress+1 > 4) ? e131_data[DMXAddress+4] : 0;
|
2020-04-13 00:42:27 +02:00
|
|
|
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
|
|
|
DMXOldDimmer = e131_data[DMXAddress+0];
|
|
|
|
bri = e131_data[DMXAddress+0];
|
2020-03-31 02:38:08 +02:00
|
|
|
strip.setBrightness(bri);
|
|
|
|
}
|
|
|
|
for (uint16_t i = 0; i < ledCount; i++)
|
2020-05-03 20:57:53 +02:00
|
|
|
setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel);
|
2020-03-31 02:38:08 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_MODE_EFFECT:
|
|
|
|
if (uni != e131Universe) return;
|
|
|
|
if (dmxChannels-DMXAddress+1 < 11) return;
|
2020-04-13 00:42:27 +02:00
|
|
|
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
|
|
|
DMXOldDimmer = e131_data[DMXAddress+0];
|
|
|
|
bri = e131_data[DMXAddress+0];
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
2020-04-13 00:42:27 +02:00
|
|
|
if (e131_data[DMXAddress+1] < MODE_COUNT)
|
|
|
|
effectCurrent = e131_data[DMXAddress+ 1];
|
|
|
|
effectSpeed = e131_data[DMXAddress+ 2]; // flickers
|
|
|
|
effectIntensity = e131_data[DMXAddress+ 3];
|
|
|
|
effectPalette = e131_data[DMXAddress+ 4];
|
|
|
|
col[0] = e131_data[DMXAddress+ 5];
|
|
|
|
col[1] = e131_data[DMXAddress+ 6];
|
|
|
|
col[2] = e131_data[DMXAddress+ 7];
|
|
|
|
colSec[0] = e131_data[DMXAddress+ 8];
|
|
|
|
colSec[1] = e131_data[DMXAddress+ 9];
|
|
|
|
colSec[2] = e131_data[DMXAddress+10];
|
2020-03-31 02:38:08 +02:00
|
|
|
if (dmxChannels-DMXAddress+1 > 11)
|
|
|
|
{
|
2020-04-13 00:42:27 +02:00
|
|
|
col[3] = e131_data[DMXAddress+11]; //white
|
|
|
|
colSec[3] = e131_data[DMXAddress+12];
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
|
|
|
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:
|
2020-04-13 00:42:27 +02:00
|
|
|
realtimeLock(realtimeTimeoutMs, mde);
|
2020-04-30 01:52:36 +02:00
|
|
|
if (realtimeOverride) return;
|
2020-03-31 02:38:08 +02:00
|
|
|
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)
|
2020-04-13 00:42:27 +02:00
|
|
|
setRealtimePixel(i, e131_data[DMXAddress+i*3+0], e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], 0);
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
|
|
|
} 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)
|
2020-04-13 00:42:27 +02:00
|
|
|
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DMX_MODE_MULTIPLE_DRGB:
|
2020-04-13 00:42:27 +02:00
|
|
|
realtimeLock(realtimeTimeoutMs, mde);
|
2020-04-30 01:52:36 +02:00
|
|
|
if (realtimeOverride) return;
|
2020-03-31 02:38:08 +02:00
|
|
|
if (previousUniverses == 0) {
|
|
|
|
// first universe of this fixture
|
2020-04-13 00:42:27 +02:00
|
|
|
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
|
|
|
DMXOldDimmer = e131_data[DMXAddress+0];
|
|
|
|
bri = e131_data[DMXAddress+0];
|
2020-03-31 02:38:08 +02:00
|
|
|
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)
|
2020-04-13 00:42:27 +02:00
|
|
|
setRealtimePixel(i, e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], e131_data[DMXAddress+i*3+3], 0);
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
|
|
|
} 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)
|
2020-04-13 00:42:27 +02:00
|
|
|
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
2020-03-31 02:38:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DEBUG_PRINTLN("unknown E1.31 DMX mode");
|
|
|
|
return; // nothing to do
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
e131NewData = true;
|
|
|
|
}
|