diff --git a/include/UDPProto.h b/include/UDPProto.h index ff12b0e..855a800 100644 --- a/include/UDPProto.h +++ b/include/UDPProto.h @@ -16,10 +16,13 @@ public: UDPProto(Fader *fader); + bool start(uint16_t port); + + bool check(void); bool loop(void); private: WiFiUDP m_udpServer; Fader *m_fader; -}; \ No newline at end of file +}; diff --git a/src/UDPProto.cpp b/src/UDPProto.cpp index 0ef9c45..4b83156 100644 --- a/src/UDPProto.cpp +++ b/src/UDPProto.cpp @@ -23,6 +23,22 @@ bool UDPProto::start(uint16_t port) return true; } +bool UDPProto::check(void) +{ + int packetSize = m_udpServer.parsePacket(); + if(packetSize) { + byte buf[1024]; + int len; + while((len = m_udpServer.read(buf, 1024)) == 1024) { + // do nothing + } + m_udpServer.endPacket(); + return true; + } else { + return false; + } +} + bool UDPProto::loop(void) { byte cmd[WS2801_CMD_LEN]; diff --git a/src/main.cpp b/src/main.cpp index d8e9581..aa8be13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -87,6 +87,82 @@ bool initLEDs() return true; } +enum LEDState { + UDP, + ANIMATION, + TRANSITION +}; + +static void ledFSM(void) +{ + static bool stateEntered = true; + static LEDState ledState = ANIMATION; + static LEDState nextState; + + static unsigned long lastUDPUpdate = 0; + + LEDState lastState = ledState; + + switch(ledState) { + case ANIMATION: + Serial.print("A"); + + if(stateEntered) { + animController.restart(); + } + + animController.loop(); + + if(animController.isIdle()) { + animController.changeAnimation(std::unique_ptr(new FireAnimation(&ledFader, false))); + } + + if(((WiFi.status() == WL_CONNECTED) || (WiFi.getMode() == WIFI_MODE_AP)) && + udpProto.check()) { + // UDP packet received -> transition to UDP state + nextState = UDP; + ledState = TRANSITION; + } + break; + + case UDP: + Serial.print("U"); + if((WiFi.status() != WL_CONNECTED) && (WiFi.getMode() != WIFI_MODE_AP)) { + // WiFi disconnected -> switch to animation immediately to show reconnect animation + ledState = ANIMATION; + break; + } + + if(udpProto.loop()) { + lastUDPUpdate = millis(); + ledFader.update(); + } else if(millis() - lastUDPUpdate > 3000) { + // seems like no more UDP data arrives -> transition to ANIMATION state + nextState = ANIMATION; + ledState = TRANSITION; + } + break; + + case TRANSITION: + Serial.print("T"); + if(stateEntered) { + ledFader.set_fadestep(2); + ledFader.fade_color(Fader::Color{0, 0, 0, 0}); + } + + ledFader.update(); + if(!ledFader.something_changed()) { + // transition finished + ledState = nextState; + lastUDPUpdate = millis(); + } + + break; + } + + stateEntered = (lastState != ledState); +} + static void ledTask( void * parameter ) { uint64_t frame = 0; @@ -96,15 +172,7 @@ static void ledTask( void * parameter ) uint32_t start_time = micros(); - animController.loop(); - - if(animController.isIdle()) { - animController.changeAnimation(std::unique_ptr(new FireAnimation(&ledFader, false))); - } - - if((WiFi.status() == WL_CONNECTED) || (WiFi.getMode() == WIFI_MODE_AP)) { - udpProto.loop(); - } + ledFSM(); led_idx++; if(led_idx >= STRANDS[0].numPixels) { @@ -117,10 +185,6 @@ static void ledTask( void * parameter ) strands[i] = &STRANDS[i]; } - if(animController.isIdle()) { - ledFader.update(); - } - if(ledFader.something_changed()) { const std::vector &colors = ledFader.get_color_values();