Skip to content

Commit 46b66c7

Browse files
committed
Merge pbolduc/WLED/feature/upd-ddp-send into network-bus
1 parent 17c2027 commit 46b66c7

File tree

1 file changed

+110
-1
lines changed

1 file changed

+110
-1
lines changed

wled00/udp.cpp

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "wled.h"
2+
#include "src/dependencies/json/ArduinoJson-v6.h"
23

34
/*
45
* UDP sync notifier / Realtime / Hyperion / TPM2.NET
@@ -89,7 +90,6 @@ void notify(byte callMode, bool followUp)
8990
notificationTwoRequired = (followUp)? false:notifyTwice;
9091
}
9192

92-
9393
void realtimeLock(uint32_t timeoutMs, byte md)
9494
{
9595
if (!realtimeMode && !realtimeOverride){
@@ -101,6 +101,10 @@ void realtimeLock(uint32_t timeoutMs, byte md)
101101

102102
realtimeTimeout = millis() + timeoutMs;
103103
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
104+
// if strip is off (bri==0) and not already in RTM
105+
if (bri == 0 && !realtimeMode) {
106+
strip.setBrightness(scaledBri(briLast));
107+
}
104108
realtimeMode = md;
105109

106110
if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(scaledBri(255));
@@ -514,3 +518,108 @@ void sendSysInfoUDP()
514518
notifier2Udp.write(data, sizeof(data));
515519
notifier2Udp.endPacket();
516520
}
521+
522+
523+
/*********************************************************************************************\
524+
* Art-Net, DDP, E131 output - work in progress
525+
\*********************************************************************************************/
526+
527+
#define DDP_HEADER_LEN 10
528+
#define DDP_SYNCPACKET_LEN 10
529+
530+
#define DDP_FLAGS1_VER 0xc0 // version mask
531+
#define DDP_FLAGS1_VER1 0x40 // version=1
532+
#define DDP_FLAGS1_PUSH 0x01
533+
#define DDP_FLAGS1_QUERY 0x02
534+
#define DDP_FLAGS1_REPLY 0x04
535+
#define DDP_FLAGS1_STORAGE 0x08
536+
#define DDP_FLAGS1_TIME 0x10
537+
538+
#define DDP_ID_DISPLAY 1
539+
#define DDP_ID_CONFIG 250
540+
#define DDP_ID_STATUS 251
541+
542+
// 1440 channels per packet
543+
#define DDP_CHANNELS_PER_PACKET 1440 // 480 leds
544+
545+
//
546+
// Send real time DDP UDP updates to the specified client
547+
//
548+
// client - the IP address to send to
549+
// length - the number of pixels
550+
// buffer - a buffer of at least length*4 bytes long
551+
// isRGBW - true if the buffer contains 4 components per pixel
552+
553+
uint8_t sequenceNumber = 0; // this needs to be shared across all outputs
554+
555+
uint8_t realtimeBroadcast(IPAddress client, uint16_t length, uint8_t *buffer, bool isRGBW) {
556+
WiFiUDP ddpUdp;
557+
558+
// calclate the number of UDP packets we need to send
559+
uint16_t channelCount = length * 3; // 1 channel for every R,G,B value
560+
uint16_t packetCount = channelCount / DDP_CHANNELS_PER_PACKET;
561+
if (channelCount % DDP_CHANNELS_PER_PACKET) {
562+
packetCount++;
563+
}
564+
565+
// there are 3 channels per RGB pixel
566+
uint16_t channel = 0; // TODO: allow specifying the start channel
567+
// the current position in the buffer
568+
uint16_t bufferOffset = 0;
569+
570+
for (uint16_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
571+
if (sequenceNumber > 15) sequenceNumber = 0;
572+
573+
int rc = ddpUdp.beginPacket(client, DDP_PORT);
574+
if (rc == 0) {
575+
//DEBUG_PRINTLN("WiFiUDP.beginPacket returned an error");
576+
return 1; // problem
577+
}
578+
579+
// the amount of data is AFTER the header in the current packet
580+
uint16_t packetSize = DDP_CHANNELS_PER_PACKET;
581+
582+
uint8_t flags = DDP_FLAGS1_VER1;
583+
if (currentPacket == (packetCount - 1)) {
584+
// last packet, set the push flag
585+
// TODO: determine if we want to send an empty push packet to each destination after sending the pixel data
586+
flags = DDP_FLAGS1_VER1 | DDP_FLAGS1_PUSH;
587+
if (channelCount % DDP_CHANNELS_PER_PACKET) {
588+
packetSize = channelCount % DDP_CHANNELS_PER_PACKET;
589+
}
590+
}
591+
592+
// write the header
593+
/*0*/ddpUdp.write(flags);
594+
/*1*/ddpUdp.write(sequenceNumber++ & 0xF);
595+
/*2*/ddpUdp.write(0);
596+
/*3*/ddpUdp.write(DDP_ID_DISPLAY);
597+
// data offset in bytes, 32-bit number, MSB first
598+
/*4*/ddpUdp.write((channel & 0xFF000000) >> 24);
599+
/*5*/ddpUdp.write((channel & 0x00FF0000) >> 16);
600+
/*6*/ddpUdp.write((channel & 0x0000FF00) >> 8);
601+
/*7*/ddpUdp.write((channel & 0x000000FF));
602+
// data length in bytes, 16-bit number, MSB first
603+
/*8*/ddpUdp.write((packetSize & 0xFF00) >> 8);
604+
/*9*/ddpUdp.write(packetSize & 0xFF);
605+
606+
// write the colors, the write write(const uint8_t *buffer, size_t size)
607+
// function is just a loop internally too
608+
for (uint16_t i = 0; i < packetSize; i += 3) {
609+
ddpUdp.write(buffer[bufferOffset++]); // R
610+
ddpUdp.write(buffer[bufferOffset++]); // G
611+
ddpUdp.write(buffer[bufferOffset++]); // B
612+
if (isRGBW) bufferOffset++;
613+
}
614+
615+
rc = ddpUdp.endPacket();
616+
if (rc == 0) {
617+
//DEBUG_PRINTLN("WiFiUDP.endPacket returned an error");
618+
return 1; // problem
619+
}
620+
621+
channel += packetSize;
622+
}
623+
624+
return 0;
625+
}

0 commit comments

Comments
 (0)