Circumvent problems with UDP fragmentation

The ESP’s IP stack seems not to support UDP packet fragmentation and
drops such packets silently which is problematic for setups with many
LEDs and huge updates.

With this patch, the UDP server processes up to 3 full UDP packets per
frame, allowing much larger updates. Additionally, the new END_OF_UPDATE
flag allows to signal when a update sequence is finished. If this flag
is encountered, no further UDP packets are processed in the current
frame.
This commit is contained in:
Thomas Kolb 2020-04-14 21:03:39 +02:00
parent da37f32096
commit dc8bc98193
2 changed files with 71 additions and 58 deletions

View file

@ -12,6 +12,7 @@ public:
FADE_COLOUR = 1, FADE_COLOUR = 1,
ADD_COLOUR = 2, ADD_COLOUR = 2,
SET_FADESTEP = 3, SET_FADESTEP = 3,
END_OF_UPDATE = 254,
ACK_REQUEST = 255 ACK_REQUEST = 255
}; };
@ -24,6 +25,8 @@ public:
bool loop(void); bool loop(void);
private: private:
const static uint32_t MAX_PACKETS_PER_UPDATE = 3;
WiFiUDP m_udpServer; WiFiUDP m_udpServer;
Fader *m_fader; Fader *m_fader;
}; };

View file

@ -39,9 +39,12 @@ bool UDPProto::loop(void)
byte cmd[WS2801_CMD_LEN]; byte cmd[WS2801_CMD_LEN];
byte action, strip, module, r, g, b, w; byte action, strip, module, r, g, b, w;
int len; int len;
int packets_processed = 0;
bool done_something = false;
int32_t seq = -1; int32_t seq = -1;
while(packets_processed < MAX_PACKETS_PER_UPDATE) {
int packetSize = m_udpServer.parsePacket(); int packetSize = m_udpServer.parsePacket();
if(packetSize) if(packetSize)
{ {
@ -84,6 +87,10 @@ bool UDPProto::loop(void)
m_fader->set_fadestep(r); // red channel contains the fadestep in this case m_fader->set_fadestep(r); // red channel contains the fadestep in this case
break; break;
case END_OF_UPDATE:
packets_processed = MAX_PACKETS_PER_UPDATE;
break;
case ACK_REQUEST: case ACK_REQUEST:
seq = ((int32_t)r) << 8 | (int32_t)g; seq = ((int32_t)r) << 8 | (int32_t)g;
@ -103,8 +110,11 @@ bool UDPProto::loop(void)
m_udpServer.flush(); m_udpServer.flush();
return true; // processed a packet done_something = true;
} else { } else {
return false; break;
} }
}
return done_something;
} }