kopia lustrzana https://github.com/Aircoookie/WLED
implement different DMX modes for E1.31:
DISABLED: don't act on packets SINGLE_RGB: treat all LEDs the same and controll them using 3 channels: RGB SINGLE_DRGB: as above, but has an additional first channel for Dimmer EFFECT: not a realtime mode. disables fadeTransition to reduce delay. just exposes parameters as 11 channels to trigger effects locally: Dimmer Effect Speed Intensity Palette PriRed PriGreen PriBlue SecRed SecGreen SecBlue MULTIPLE_RGB: legacy mode. address each LED individually with 3 channels: RGB. MULTIPLE_DRGB as above, but has an additional first channel for master Dimmer add client stats (IP + user agent) add support for DMX address (so you don't need a whole universe per fixture) skip out-of-order packetspull/665/head
rodzic
d69a2f1514
commit
76f704b060
|
@ -179,8 +179,20 @@ bool receiveDirect = true; //receive UDP realtime
|
|||
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
|
||||
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
|
||||
|
||||
uint16_t e131Universe = 1; //settings for E1.31 (sACN) protocol
|
||||
bool e131Multicast = false;
|
||||
uint16_t e131Universe = 1; //settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
|
||||
#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_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)
|
||||
uint8_t DMXMode; //DMX mode (s.a.)
|
||||
uint16_t DMXAddress; //DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
|
||||
uint8_t DMXOldDimmer = 0; //only update brightness on change
|
||||
uint8_t e131LastSequenceNumber = 0; //to detect packet loss
|
||||
bool e131Multicast = false; //multicast or unicast
|
||||
IPAddress e131ClientIP; //E1.31 client IP
|
||||
String e131ClientUA; //E1.31 client User Agent
|
||||
|
||||
bool mqttEnabled = false;
|
||||
char mqttDeviceTopic[33] = ""; //main MQTT topic (individual per device, default is wled/mac)
|
||||
|
|
|
@ -89,23 +89,130 @@ void arlsLock(uint32_t timeoutMs)
|
|||
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
|
||||
//E1.31 protocol support
|
||||
uint16_t uni = htons(p->universe);
|
||||
if (uni < e131Universe || uni >= e131Universe + E131_MAX_UNIVERSE_COUNT) return;
|
||||
|
||||
uint16_t len = htons(p->property_value_count) -1;
|
||||
len /= 3; //one LED is 3 DMX channels
|
||||
|
||||
uint16_t multipacketOffset = (uni - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
||||
if (ledCount <= multipacketOffset) return;
|
||||
// skip out-of-sequence packets
|
||||
if (p->sequence_number < e131LastSequenceNumber && p->sequence_number - e131LastSequenceNumber > -20){
|
||||
DEBUG_PRINT("skipping E1.31 frame (last seq=");
|
||||
DEBUG_PRINT(e131LastSequenceNumber);
|
||||
DEBUG_PRINT(", current seq=");
|
||||
DEBUG_PRINT(p->sequence_number);
|
||||
DEBUG_PRINTLN(")");
|
||||
e131LastSequenceNumber = p->sequence_number;
|
||||
return;
|
||||
}
|
||||
e131LastSequenceNumber = p->sequence_number;
|
||||
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
||||
// update status info
|
||||
e131ClientIP = clientIP;
|
||||
e131ClientUA = String((char *)p->source_name);
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
int j = i * 3 +1;
|
||||
setRealtimePixel(i + multipacketOffset, p->property_values[j], p->property_values[j+1], p->property_values[j+2], 0);
|
||||
uint16_t uni = htons(p->universe);
|
||||
uint8_t previousUniverses = uni - e131Universe;
|
||||
uint16_t possibleLEDsInCurrentUniverse;
|
||||
uint16_t dmxChannels = htons(p->property_value_count) -1;
|
||||
|
||||
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;
|
||||
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;
|
||||
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];
|
||||
strip.setBrightness(bri);
|
||||
}
|
||||
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];
|
||||
fadeTransition = false; // act fast
|
||||
colorUpdated(5); // don't send UDP
|
||||
return; // don't activate realtime live mode
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_RGB:
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
e131NewData = true;
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue