Art-Net transmit support for network LEDs

Like DDP, this allows WLED to address network systems using the Art-Net protocol.

Universe starts at zero, because that's the first universe in Art-Net.

Works with RGB. It's coded to also work with RGBW, but I couldn't find a great place to enable it without mucking with things I don't understand.
This commit is contained in:
TroyHacks 2023-03-10 13:29:00 -05:00
parent 2713573b9b
commit a4fcbb9f67
3 changed files with 68 additions and 17 deletions

View File

@ -383,24 +383,24 @@ uint8_t BusOnOff::getPins(uint8_t* pinArray) {
BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false; _valid = false;
// switch (bc.type) { switch (bc.type) {
// case TYPE_NET_ARTNET_RGB: case TYPE_NET_ARTNET_RGB:
// _rgbw = false; _rgbw = false;
// _UDPtype = 2; _UDPtype = 2;
// break; break;
// case TYPE_NET_E131_RGB: case TYPE_NET_E131_RGB:
// _rgbw = false; _rgbw = false;
// _UDPtype = 1; _UDPtype = 1;
// break; break;
// case TYPE_NET_DDP_RGB: case TYPE_NET_DDP_RGB:
// _rgbw = false; _rgbw = false;
// _UDPtype = 0; _UDPtype = 0;
// break; break;
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
_rgbw = bc.type == TYPE_NET_DDP_RGBW; _rgbw = bc.type == TYPE_NET_DDP_RGBW;
_UDPtype = 0; _UDPtype = 0;
// break; break;
// } }
_UDPchannels = _rgbw ? 4 : 3; _UDPchannels = _rgbw ? 4 : 3;
_data = (byte *)malloc(bc.count * _UDPchannels); _data = (byte *)malloc(bc.count * _UDPchannels);
if (_data == nullptr) return; if (_data == nullptr) return;

View File

@ -345,7 +345,7 @@ ${i+1}:
<!--option value="46">PWM RGB+DCCT</option-->'} <!--option value="46">PWM RGB+DCCT</option-->'}
<option value="80">DDP RGB (network)</option> <option value="80">DDP RGB (network)</option>
<!--option value="81">E1.31 RGB (network)</option--> <!--option value="81">E1.31 RGB (network)</option-->
<!--option value="82">ArtNet RGB (network)</option--> <option value="82">Art-Net RGB (network)</option>
<option value="88">DDP RGBW (network)</option> <option value="88">DDP RGBW (network)</option>
</select><br> </select><br>
<div id="co${i}" style="display:inline">Color Order: <div id="co${i}" style="display:inline">Color Order:

View File

@ -791,6 +791,57 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
case 2: //ArtNet case 2: //ArtNet
{ {
// calculate the number of UDP packets we need to send
size_t channelCount = length * (isRGBW?4:3); // 1 channel for every R,G,B,(W?) value
size_t ARTNET_CHANNELS_PER_PACKET = isRGBW?512:510; // 512/4=128 RGBW LEDs, 510/3=170 RGB LEDs
size_t packetCount = ((channelCount-1)/ARTNET_CHANNELS_PER_PACKET)+1;
uint32_t channel = 0;
size_t bufferOffset = 0;
sequenceNumber++;
for (size_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
if (sequenceNumber > 255) sequenceNumber = 0;
if (!ddpUdp.beginPacket(client, ARTNET_DEFAULT_PORT)) {
DEBUG_PRINTLN(F("Art-Net WiFiUDP.beginPacket returned an error"));
return 1; // borked
}
size_t packetSize = ARTNET_CHANNELS_PER_PACKET;
if (currentPacket == (packetCount - 1U)) {
// last packet
if (channelCount % ARTNET_CHANNELS_PER_PACKET) {
packetSize = channelCount % ARTNET_CHANNELS_PER_PACKET;
}
}
const byte ART_NET_HEADER[12] = {0x41,0x72,0x74,0x2d,0x4e,0x65,0x74,0x00,0x00,0x50,0x00,0x0e};
ddpUdp.write(ART_NET_HEADER,12); // This doesn't change. Hard coded ID, OpCode, and protocol version.
ddpUdp.write(sequenceNumber & 0xFF); // sequence number. 1..255
ddpUdp.write(0x00); // physical - more an FYI, not really used for anything. 0..3
ddpUdp.write((currentPacket) & 0xFF); // Universe LSB. 1 full packet == 1 full universe, so just use current packet number.
ddpUdp.write(0x00); // Universe MSB, unused.
ddpUdp.write(0xFF & (packetSize >> 8)); // 16-bit length of channel data, MSB
ddpUdp.write(0xFF & (packetSize )); // 16-bit length of channel data, LSB
for (size_t i = 0; i < packetSize; i += (isRGBW?4:3)) {
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // G
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // B
if (isRGBW) ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // W
}
if (!ddpUdp.endPacket()) {
DEBUG_PRINTLN(F("Art-Net WiFiUDP.endPacket returned an error"));
return 1; // borked
}
channel += packetSize;
}
} break; } break;
} }
return 0; return 0;