From dc8bc98193c7ed8ee06af34591af08c910f9a55f Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Tue, 14 Apr 2020 21:03:39 +0200 Subject: [PATCH] Circumvent problems with UDP fragmentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- include/UDPProto.h | 3 ++ src/UDPProto.cpp | 126 ++++++++++++++++++++++++--------------------- 2 files changed, 71 insertions(+), 58 deletions(-) diff --git a/include/UDPProto.h b/include/UDPProto.h index 14fbf18..59ac6fa 100644 --- a/include/UDPProto.h +++ b/include/UDPProto.h @@ -12,6 +12,7 @@ public: FADE_COLOUR = 1, ADD_COLOUR = 2, SET_FADESTEP = 3, + END_OF_UPDATE = 254, ACK_REQUEST = 255 }; @@ -24,6 +25,8 @@ public: bool loop(void); private: + const static uint32_t MAX_PACKETS_PER_UPDATE = 3; + WiFiUDP m_udpServer; Fader *m_fader; }; diff --git a/src/UDPProto.cpp b/src/UDPProto.cpp index a7ce39d..e06de6b 100644 --- a/src/UDPProto.cpp +++ b/src/UDPProto.cpp @@ -39,72 +39,82 @@ bool UDPProto::loop(void) byte cmd[WS2801_CMD_LEN]; byte action, strip, module, r, g, b, w; int len; + int packets_processed = 0; + bool done_something = false; int32_t seq = -1; - int packetSize = m_udpServer.parsePacket(); - if(packetSize) - { - // read the packet into packetBufffer - while((len = m_udpServer.read(cmd, WS2801_CMD_LEN)) == WS2801_CMD_LEN) { - action = cmd[0]; - strip = cmd[1]; - module = cmd[2]; - r = cmd[3]; - g = cmd[4]; - b = cmd[5]; - w = cmd[6]; + while(packets_processed < MAX_PACKETS_PER_UPDATE) { + int packetSize = m_udpServer.parsePacket(); + if(packetSize) + { + // read the packet into packetBufffer + while((len = m_udpServer.read(cmd, WS2801_CMD_LEN)) == WS2801_CMD_LEN) { + action = cmd[0]; + strip = cmd[1]; + module = cmd[2]; + r = cmd[3]; + g = cmd[4]; + b = cmd[5]; + w = cmd[6]; - Fader::Color color{r,g,b,w}; + Fader::Color color{r,g,b,w}; - if(strip >= m_fader->strips()) { - // strip index out of range - continue; + if(strip >= m_fader->strips()) { + // strip index out of range + continue; + } + + if(module >= m_fader->modules_per_strip()) { + // module index out of range + continue; + } + + switch(action) { + case SET_COLOUR: + m_fader->set_color(strip, module, color); + break; + + case FADE_COLOUR: + m_fader->fade_color(strip, module, color); + break; + + case ADD_COLOUR: + m_fader->add_color(strip, module, color); + break; + + case SET_FADESTEP: + m_fader->set_fadestep(r); // red channel contains the fadestep in this case + break; + + case END_OF_UPDATE: + packets_processed = MAX_PACKETS_PER_UPDATE; + break; + + case ACK_REQUEST: + seq = ((int32_t)r) << 8 | (int32_t)g; + + default: + break; + } + } + // send a reply, to the IP address and port that sent us the packet we received + if(seq >= 0) { + uint8_t data[2]; + data[0] = (seq >> 8) & 0xFF; + data[1] = seq & 0xFF; + m_udpServer.beginPacket(m_udpServer.remoteIP(), m_udpServer.remotePort()); + m_udpServer.write(data, 2); + m_udpServer.endPacket(); } - if(module >= m_fader->modules_per_strip()) { - // module index out of range - continue; - } + m_udpServer.flush(); - switch(action) { - case SET_COLOUR: - m_fader->set_color(strip, module, color); - break; - - case FADE_COLOUR: - m_fader->fade_color(strip, module, color); - break; - - case ADD_COLOUR: - m_fader->add_color(strip, module, color); - break; - - case SET_FADESTEP: - m_fader->set_fadestep(r); // red channel contains the fadestep in this case - break; - - case ACK_REQUEST: - seq = ((int32_t)r) << 8 | (int32_t)g; - - default: - break; - } + done_something = true; + } else { + break; } - // send a reply, to the IP address and port that sent us the packet we received - if(seq >= 0) { - uint8_t data[2]; - data[0] = (seq >> 8) & 0xFF; - data[1] = seq & 0xFF; - m_udpServer.beginPacket(m_udpServer.remoteIP(), m_udpServer.remotePort()); - m_udpServer.write(data, 2); - m_udpServer.endPacket(); - } - - m_udpServer.flush(); - - return true; // processed a packet - } else { - return false; } + + return done_something; }