diff --git a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino index e7c221f..5644700 100644 --- a/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino +++ b/ESPTimeCast_ESP32/ESPTimeCast_ESP32.ino @@ -3494,160 +3494,160 @@ void loop() { } -// --- Custom Message Display Mode (displayMode == 6) --- -if (displayMode == 6) { - - // 1. Initial Check: If message is empty, skip mode 6. - if (strlen(customMessage) == 0) { - advanceDisplayMode(); - yield(); - return; - } + // --- Custom Message Display Mode (displayMode == 6) --- + if (displayMode == 6) { - // --- CHARACTER REPLACEMENT AND PADDING (Common to both short and long) --- - const size_t MAX_NON_SCROLLING_CHARS = 8; - String msg = String(customMessage); - - // Replace standard digits 0–9 with your custom font character codes - for (int i = 0; i < msg.length(); i++) { - if (isDigit(msg[i])) { - int num = msg[i] - '0'; - msg[i] = 145 + ((num + 9) % 10); + // 1. Initial Check: If message is empty, skip mode 6. + if (strlen(customMessage) == 0) { + advanceDisplayMode(); + yield(); + return; } - } - // --- CHECK FOR TIMEOUT (Applies to temporary short & long messages) --- - bool timedOut = false; - // Check if a time limit (messageDisplaySeconds > 0) has been exceeded - if (messageDisplaySeconds > 0 && (millis() - messageStartTime) >= (messageDisplaySeconds * 1000UL)) { - Serial.printf("[MESSAGE] HA message timed out after %d seconds.\n", messageDisplaySeconds); - timedOut = true; - } + // --- CHARACTER REPLACEMENT AND PADDING (Common to both short and long) --- + const size_t MAX_NON_SCROLLING_CHARS = 8; + String msg = String(customMessage); - // --- CHECK FOR SCROLL/CYCLE LIMIT BEFORE DISPLAYING --- - // Scrolls complete applies to long messages. - bool scrollsComplete = (messageScrollTimes > 0) && (currentScrollCount >= messageScrollTimes); + // Replace standard digits 0–9 with your custom font character codes + for (int i = 0; i < msg.length(); i++) { + if (isDigit(msg[i])) { + int num = msg[i] - '0'; + msg[i] = 145 + ((num + 9) % 10); + } + } - // Cycles complete applies to short messages. - extern int currentDisplayCycleCount; // Use the dedicated short message counter - bool cyclesComplete = (messageScrollTimes > 0) && (currentDisplayCycleCount >= messageScrollTimes); + // --- CHECK FOR TIMEOUT (Applies to temporary short & long messages) --- + bool timedOut = false; + // Check if a time limit (messageDisplaySeconds > 0) has been exceeded + if (messageDisplaySeconds > 0 && (millis() - messageStartTime) >= (messageDisplaySeconds * 1000UL)) { + Serial.printf("[MESSAGE] HA message timed out after %d seconds.\n", messageDisplaySeconds); + timedOut = true; + } + + // --- CHECK FOR SCROLL/CYCLE LIMIT BEFORE DISPLAYING --- + // Scrolls complete applies to long messages. + bool scrollsComplete = (messageScrollTimes > 0) && (currentScrollCount >= messageScrollTimes); + + // Cycles complete applies to short messages. + extern int currentDisplayCycleCount; // Use the dedicated short message counter + bool cyclesComplete = (messageScrollTimes > 0) && (currentDisplayCycleCount >= messageScrollTimes); - // --- ADVANCE MODE CHECK (Check if HA parameters are complete) --- - // If either timer or cycle/scroll count is finished, we clean up the temporary message. - if (scrollsComplete || cyclesComplete) { - Serial.println(F("[MESSAGE] HA-controlled message finished.")); + // --- ADVANCE MODE CHECK (Check if HA parameters are complete) --- + // If either timer or cycle/scroll count is finished, we clean up the temporary message. + if (scrollsComplete || cyclesComplete) { + Serial.println(F("[MESSAGE] HA-controlled message finished.")); - // Reset common counters - currentScrollCount = 0; - messageStartTime = 0; - currentDisplayCycleCount = 0; // Reset the cycle counter + // Reset common counters + currentScrollCount = 0; + messageStartTime = 0; + currentDisplayCycleCount = 0; // Reset the cycle counter - // CRITICAL LOGIC: RESTORE PERSISTENT MESSAGE (Exit Mode 6 Logic) - if (strlen(lastPersistentMessage) > 0) { - // A persistent message exists, restore it - strncpy(customMessage, lastPersistentMessage, sizeof(customMessage)); - messageScrollSpeed = GENERAL_SCROLL_SPEED; - messageDisplaySeconds = 0; - messageScrollTimes = 0; - Serial.printf("[MESSAGE] Restored persistent message: '%s'. Staying in mode 6.\n", customMessage); - } else { - // No persistent message to restore. Clear the temporary HA message and Exit mode 6. - customMessage[0] = '\0'; - Serial.println(F("[MESSAGE] No persistent message to restore. Advancing display mode.")); + // CRITICAL LOGIC: RESTORE PERSISTENT MESSAGE (Exit Mode 6 Logic) + if (strlen(lastPersistentMessage) > 0) { + // A persistent message exists, restore it + strncpy(customMessage, lastPersistentMessage, sizeof(customMessage)); + messageScrollSpeed = GENERAL_SCROLL_SPEED; + messageDisplaySeconds = 0; + messageScrollTimes = 0; + Serial.printf("[MESSAGE] Restored persistent message: '%s'. Staying in mode 6.\n", customMessage); + } else { + // No persistent message to restore. Clear the temporary HA message and Exit mode 6. + customMessage[0] = '\0'; + Serial.println(F("[MESSAGE] No persistent message to restore. Advancing display mode.")); + advanceDisplayMode(); + } + yield(); + return; + } + + // ---------------------------------------------------------------------- + // BRANCH A: NON-SCROLLING (Short Message: strlen <= 8) + // ---------------------------------------------------------------------- + if (msg.length() <= MAX_NON_SCROLLING_CHARS) { + + // Determine the duration: use HA seconds if set, otherwise use weatherDuration. + unsigned long durationMs = (messageDisplaySeconds > 0) + ? (messageDisplaySeconds * 1000UL) + : weatherDuration; + + // If HA seconds is set, we use the timedOut check at the top. + // If only scrollTimes is set, we still display for weatherDuration before incrementing the cycle count. + + Serial.printf("[MESSAGE] Displaying timed short message: '%s' for %lu ms. Advancing mode.\n", customMessage, durationMs); + + P.setTextAlignment(PA_CENTER); + P.setCharSpacing(1); + P.print(msg.c_str()); + + // Block execution for the specified duration (non-HA uses weatherDuration) + unsigned long displayUntil = millis() + durationMs; + while (millis() < displayUntil) { + yield(); + } + + // --- CYCLE TRACKING FOR SCROLLTIMES --- + // Increment the counter if the HA message is configured to clear by scroll count. + if (messageScrollTimes > 0) { + currentDisplayCycleCount++; + Serial.printf("[MESSAGE] Short message cycle complete. Count: %d/%d\n", currentDisplayCycleCount, messageScrollTimes); + } + + // After display, the message content must persist, but the display must cycle. + Serial.println(F("[MESSAGE] Short message duration complete. Advancing display mode.")); + advanceDisplayMode(); + yield(); + return; + } + + // ---------------------------------------------------------------------- + // BRANCH B: SCROLLING (Long Message: strlen > 8) - (Existing Logic) + // ---------------------------------------------------------------------- + + // --- Determine if we need left padding based on previous mode --- + bool addPadding = false; + bool humidityVisible = showHumidity && weatherAvailable && strlen(openWeatherApiKey) == 32 && strlen(openWeatherCity) > 0 && strlen(openWeatherCountry) > 0; + + // If coming from CLOCK mode + if (prevDisplayMode == 0 && (showDayOfWeek || colonBlinkEnabled)) { + addPadding = true; + } else if (prevDisplayMode == 1 && humidityVisible) { + addPadding = true; + } + // Apply padding (4 spaces) if needed + if (addPadding) { + msg = " " + msg; + } + + // --- Display scrolling message --- + P.setTextAlignment(PA_LEFT); + P.setCharSpacing(1); + textEffect_t actualScrollDirection = getEffectiveScrollDirection(PA_SCROLL_LEFT, flipDisplay); + extern int messageScrollSpeed; + + // START SCROLL CYCLE + P.displayScroll(msg.c_str(), PA_LEFT, actualScrollDirection, messageScrollSpeed); + + // BLOCKING WAIT: Completes 1 full scroll + while (!P.displayAnimate()) yield(); + + // SCROLL COUNT INCREMENT + if (messageScrollTimes > 0) { + currentScrollCount++; + Serial.printf("[MESSAGE] Scroll complete. Count: %d/%d\n", currentScrollCount, messageScrollTimes); + } + + // If no HA parameters are set, this is a persistent/infinite scroll, so advance mode after 1 scroll cycle. + // If HA parameters ARE set, the mode relies on the check at the top to break out. + if (messageDisplaySeconds == 0 && messageScrollTimes == 0) { + P.setTextAlignment(PA_CENTER); advanceDisplayMode(); } + yield(); return; } - // ---------------------------------------------------------------------- - // BRANCH A: NON-SCROLLING (Short Message: strlen <= 8) - // ---------------------------------------------------------------------- - if (msg.length() <= MAX_NON_SCROLLING_CHARS) { - - // Determine the duration: use HA seconds if set, otherwise use weatherDuration. - unsigned long durationMs = (messageDisplaySeconds > 0) - ? (messageDisplaySeconds * 1000UL) - : weatherDuration; - - // If HA seconds is set, we use the timedOut check at the top. - // If only scrollTimes is set, we still display for weatherDuration before incrementing the cycle count. - - Serial.printf("[MESSAGE] Displaying timed short message: '%s' for %lu ms. Advancing mode.\n", customMessage, durationMs); - - P.setTextAlignment(PA_CENTER); - P.setCharSpacing(1); - P.print(msg.c_str()); - - // Block execution for the specified duration (non-HA uses weatherDuration) - unsigned long displayUntil = millis() + durationMs; - while (millis() < displayUntil) { - yield(); - } - - // --- CYCLE TRACKING FOR SCROLLTIMES --- - // Increment the counter if the HA message is configured to clear by scroll count. - if (messageScrollTimes > 0) { - currentDisplayCycleCount++; - Serial.printf("[MESSAGE] Short message cycle complete. Count: %d/%d\n", currentDisplayCycleCount, messageScrollTimes); - } - - // After display, the message content must persist, but the display must cycle. - Serial.println(F("[MESSAGE] Short message duration complete. Advancing display mode.")); - advanceDisplayMode(); - yield(); - return; - } - - // ---------------------------------------------------------------------- - // BRANCH B: SCROLLING (Long Message: strlen > 8) - (Existing Logic) - // ---------------------------------------------------------------------- - - // --- Determine if we need left padding based on previous mode --- - bool addPadding = false; - bool humidityVisible = showHumidity && weatherAvailable && strlen(openWeatherApiKey) == 32 && strlen(openWeatherCity) > 0 && strlen(openWeatherCountry) > 0; - - // If coming from CLOCK mode - if (prevDisplayMode == 0 && (showDayOfWeek || colonBlinkEnabled)) { - addPadding = true; - } else if (prevDisplayMode == 1 && humidityVisible) { - addPadding = true; - } - // Apply padding (4 spaces) if needed - if (addPadding) { - msg = " " + msg; - } - - // --- Display scrolling message --- - P.setTextAlignment(PA_LEFT); - P.setCharSpacing(1); - textEffect_t actualScrollDirection = getEffectiveScrollDirection(PA_SCROLL_LEFT, flipDisplay); - extern int messageScrollSpeed; - - // START SCROLL CYCLE - P.displayScroll(msg.c_str(), PA_LEFT, actualScrollDirection, messageScrollSpeed); - - // BLOCKING WAIT: Completes 1 full scroll - while (!P.displayAnimate()) yield(); - - // SCROLL COUNT INCREMENT - if (messageScrollTimes > 0) { - currentScrollCount++; - Serial.printf("[MESSAGE] Scroll complete. Count: %d/%d\n", currentScrollCount, messageScrollTimes); - } - - // If no HA parameters are set, this is a persistent/infinite scroll, so advance mode after 1 scroll cycle. - // If HA parameters ARE set, the mode relies on the check at the top to break out. - if (messageDisplaySeconds == 0 && messageScrollTimes == 0) { - P.setTextAlignment(PA_CENTER); - advanceDisplayMode(); - } - - yield(); - return; -} - unsigned long currentMillis = millis(); unsigned long runtimeSeconds = (currentMillis - bootMillis) / 1000; diff --git a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino index 3efe5ea..cc4e60a 100644 --- a/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino +++ b/ESPTimeCast_ESP8266/ESPTimeCast_ESP8266.ino @@ -3486,161 +3486,160 @@ void loop() { } -// --- Custom Message Display Mode (displayMode == 6) --- -if (displayMode == 6) { - - // 1. Initial Check: If message is empty, skip mode 6. - if (strlen(customMessage) == 0) { - advanceDisplayMode(); - yield(); - return; - } + // --- Custom Message Display Mode (displayMode == 6) --- + if (displayMode == 6) { - // --- CHARACTER REPLACEMENT AND PADDING (Common to both short and long) --- - const size_t MAX_NON_SCROLLING_CHARS = 8; - String msg = String(customMessage); - - // Replace standard digits 0–9 with your custom font character codes - for (int i = 0; i < msg.length(); i++) { - if (isDigit(msg[i])) { - int num = msg[i] - '0'; - msg[i] = 145 + ((num + 9) % 10); + // 1. Initial Check: If message is empty, skip mode 6. + if (strlen(customMessage) == 0) { + advanceDisplayMode(); + yield(); + return; } - } - // --- CHECK FOR TIMEOUT (Applies to temporary short & long messages) --- - bool timedOut = false; - // Check if a time limit (messageDisplaySeconds > 0) has been exceeded - if (messageDisplaySeconds > 0 && (millis() - messageStartTime) >= (messageDisplaySeconds * 1000UL)) { - Serial.printf("[MESSAGE] HA message timed out after %d seconds.\n", messageDisplaySeconds); - timedOut = true; - } + // --- CHARACTER REPLACEMENT AND PADDING (Common to both short and long) --- + const size_t MAX_NON_SCROLLING_CHARS = 8; + String msg = String(customMessage); - // --- CHECK FOR SCROLL/CYCLE LIMIT BEFORE DISPLAYING --- - // Scrolls complete applies to long messages. - bool scrollsComplete = (messageScrollTimes > 0) && (currentScrollCount >= messageScrollTimes); + // Replace standard digits 0–9 with your custom font character codes + for (int i = 0; i < msg.length(); i++) { + if (isDigit(msg[i])) { + int num = msg[i] - '0'; + msg[i] = 145 + ((num + 9) % 10); + } + } - // Cycles complete applies to short messages. - extern int currentDisplayCycleCount; // Use the dedicated short message counter - bool cyclesComplete = (messageScrollTimes > 0) && (currentDisplayCycleCount >= messageScrollTimes); + // --- CHECK FOR TIMEOUT (Applies to temporary short & long messages) --- + bool timedOut = false; + // Check if a time limit (messageDisplaySeconds > 0) has been exceeded + if (messageDisplaySeconds > 0 && (millis() - messageStartTime) >= (messageDisplaySeconds * 1000UL)) { + Serial.printf("[MESSAGE] HA message timed out after %d seconds.\n", messageDisplaySeconds); + timedOut = true; + } + + // --- CHECK FOR SCROLL/CYCLE LIMIT BEFORE DISPLAYING --- + // Scrolls complete applies to long messages. + bool scrollsComplete = (messageScrollTimes > 0) && (currentScrollCount >= messageScrollTimes); + + // Cycles complete applies to short messages. + extern int currentDisplayCycleCount; // Use the dedicated short message counter + bool cyclesComplete = (messageScrollTimes > 0) && (currentDisplayCycleCount >= messageScrollTimes); - // --- ADVANCE MODE CHECK (Check if HA parameters are complete) --- - // If either timer or cycle/scroll count is finished, we clean up the temporary message. - if (scrollsComplete || cyclesComplete) { - Serial.println(F("[MESSAGE] HA-controlled message finished.")); + // --- ADVANCE MODE CHECK (Check if HA parameters are complete) --- + // If either timer or cycle/scroll count is finished, we clean up the temporary message. + if (scrollsComplete || cyclesComplete) { + Serial.println(F("[MESSAGE] HA-controlled message finished.")); - // Reset common counters - currentScrollCount = 0; - messageStartTime = 0; - currentDisplayCycleCount = 0; // Reset the cycle counter + // Reset common counters + currentScrollCount = 0; + messageStartTime = 0; + currentDisplayCycleCount = 0; // Reset the cycle counter - // CRITICAL LOGIC: RESTORE PERSISTENT MESSAGE (Exit Mode 6 Logic) - if (strlen(lastPersistentMessage) > 0) { - // A persistent message exists, restore it - strncpy(customMessage, lastPersistentMessage, sizeof(customMessage)); - messageScrollSpeed = GENERAL_SCROLL_SPEED; - messageDisplaySeconds = 0; - messageScrollTimes = 0; - Serial.printf("[MESSAGE] Restored persistent message: '%s'. Staying in mode 6.\n", customMessage); - } else { - // No persistent message to restore. Clear the temporary HA message and Exit mode 6. - customMessage[0] = '\0'; - Serial.println(F("[MESSAGE] No persistent message to restore. Advancing display mode.")); + // CRITICAL LOGIC: RESTORE PERSISTENT MESSAGE (Exit Mode 6 Logic) + if (strlen(lastPersistentMessage) > 0) { + // A persistent message exists, restore it + strncpy(customMessage, lastPersistentMessage, sizeof(customMessage)); + messageScrollSpeed = GENERAL_SCROLL_SPEED; + messageDisplaySeconds = 0; + messageScrollTimes = 0; + Serial.printf("[MESSAGE] Restored persistent message: '%s'. Staying in mode 6.\n", customMessage); + } else { + // No persistent message to restore. Clear the temporary HA message and Exit mode 6. + customMessage[0] = '\0'; + Serial.println(F("[MESSAGE] No persistent message to restore. Advancing display mode.")); + advanceDisplayMode(); + } + yield(); + return; + } + + // ---------------------------------------------------------------------- + // BRANCH A: NON-SCROLLING (Short Message: strlen <= 8) + // ---------------------------------------------------------------------- + if (msg.length() <= MAX_NON_SCROLLING_CHARS) { + + // Determine the duration: use HA seconds if set, otherwise use weatherDuration. + unsigned long durationMs = (messageDisplaySeconds > 0) + ? (messageDisplaySeconds * 1000UL) + : weatherDuration; + + // If HA seconds is set, we use the timedOut check at the top. + // If only scrollTimes is set, we still display for weatherDuration before incrementing the cycle count. + + Serial.printf("[MESSAGE] Displaying timed short message: '%s' for %lu ms. Advancing mode.\n", customMessage, durationMs); + + P.setTextAlignment(PA_CENTER); + P.setCharSpacing(1); + P.print(msg.c_str()); + + // Block execution for the specified duration (non-HA uses weatherDuration) + unsigned long displayUntil = millis() + durationMs; + while (millis() < displayUntil) { + yield(); + } + + // --- CYCLE TRACKING FOR SCROLLTIMES --- + // Increment the counter if the HA message is configured to clear by scroll count. + if (messageScrollTimes > 0) { + currentDisplayCycleCount++; + Serial.printf("[MESSAGE] Short message cycle complete. Count: %d/%d\n", currentDisplayCycleCount, messageScrollTimes); + } + + // After display, the message content must persist, but the display must cycle. + Serial.println(F("[MESSAGE] Short message duration complete. Advancing display mode.")); + advanceDisplayMode(); + yield(); + return; + } + + // ---------------------------------------------------------------------- + // BRANCH B: SCROLLING (Long Message: strlen > 8) - (Existing Logic) + // ---------------------------------------------------------------------- + + // --- Determine if we need left padding based on previous mode --- + bool addPadding = false; + bool humidityVisible = showHumidity && weatherAvailable && strlen(openWeatherApiKey) == 32 && strlen(openWeatherCity) > 0 && strlen(openWeatherCountry) > 0; + + // If coming from CLOCK mode + if (prevDisplayMode == 0 && (showDayOfWeek || colonBlinkEnabled)) { + addPadding = true; + } else if (prevDisplayMode == 1 && humidityVisible) { + addPadding = true; + } + // Apply padding (4 spaces) if needed + if (addPadding) { + msg = " " + msg; + } + + // --- Display scrolling message --- + P.setTextAlignment(PA_LEFT); + P.setCharSpacing(1); + textEffect_t actualScrollDirection = getEffectiveScrollDirection(PA_SCROLL_LEFT, flipDisplay); + extern int messageScrollSpeed; + + // START SCROLL CYCLE + P.displayScroll(msg.c_str(), PA_LEFT, actualScrollDirection, messageScrollSpeed); + + // BLOCKING WAIT: Completes 1 full scroll + while (!P.displayAnimate()) yield(); + + // SCROLL COUNT INCREMENT + if (messageScrollTimes > 0) { + currentScrollCount++; + Serial.printf("[MESSAGE] Scroll complete. Count: %d/%d\n", currentScrollCount, messageScrollTimes); + } + + // If no HA parameters are set, this is a persistent/infinite scroll, so advance mode after 1 scroll cycle. + // If HA parameters ARE set, the mode relies on the check at the top to break out. + if (messageDisplaySeconds == 0 && messageScrollTimes == 0) { + P.setTextAlignment(PA_CENTER); advanceDisplayMode(); } + yield(); return; } - // ---------------------------------------------------------------------- - // BRANCH A: NON-SCROLLING (Short Message: strlen <= 8) - // ---------------------------------------------------------------------- - if (msg.length() <= MAX_NON_SCROLLING_CHARS) { - - // Determine the duration: use HA seconds if set, otherwise use weatherDuration. - unsigned long durationMs = (messageDisplaySeconds > 0) - ? (messageDisplaySeconds * 1000UL) - : weatherDuration; - - // If HA seconds is set, we use the timedOut check at the top. - // If only scrollTimes is set, we still display for weatherDuration before incrementing the cycle count. - - Serial.printf("[MESSAGE] Displaying timed short message: '%s' for %lu ms. Advancing mode.\n", customMessage, durationMs); - - P.setTextAlignment(PA_CENTER); - P.setCharSpacing(1); - P.print(msg.c_str()); - - // Block execution for the specified duration (non-HA uses weatherDuration) - unsigned long displayUntil = millis() + durationMs; - while (millis() < displayUntil) { - yield(); - } - - // --- CYCLE TRACKING FOR SCROLLTIMES --- - // Increment the counter if the HA message is configured to clear by scroll count. - if (messageScrollTimes > 0) { - currentDisplayCycleCount++; - Serial.printf("[MESSAGE] Short message cycle complete. Count: %d/%d\n", currentDisplayCycleCount, messageScrollTimes); - } - - // After display, the message content must persist, but the display must cycle. - Serial.println(F("[MESSAGE] Short message duration complete. Advancing display mode.")); - advanceDisplayMode(); - yield(); - return; - } - - // ---------------------------------------------------------------------- - // BRANCH B: SCROLLING (Long Message: strlen > 8) - (Existing Logic) - // ---------------------------------------------------------------------- - - // --- Determine if we need left padding based on previous mode --- - bool addPadding = false; - bool humidityVisible = showHumidity && weatherAvailable && strlen(openWeatherApiKey) == 32 && strlen(openWeatherCity) > 0 && strlen(openWeatherCountry) > 0; - - // If coming from CLOCK mode - if (prevDisplayMode == 0 && (showDayOfWeek || colonBlinkEnabled)) { - addPadding = true; - } else if (prevDisplayMode == 1 && humidityVisible) { - addPadding = true; - } - // Apply padding (4 spaces) if needed - if (addPadding) { - msg = " " + msg; - } - - // --- Display scrolling message --- - P.setTextAlignment(PA_LEFT); - P.setCharSpacing(1); - textEffect_t actualScrollDirection = getEffectiveScrollDirection(PA_SCROLL_LEFT, flipDisplay); - extern int messageScrollSpeed; - - // START SCROLL CYCLE - P.displayScroll(msg.c_str(), PA_LEFT, actualScrollDirection, messageScrollSpeed); - - // BLOCKING WAIT: Completes 1 full scroll - while (!P.displayAnimate()) yield(); - - // SCROLL COUNT INCREMENT - if (messageScrollTimes > 0) { - currentScrollCount++; - Serial.printf("[MESSAGE] Scroll complete. Count: %d/%d\n", currentScrollCount, messageScrollTimes); - } - - // If no HA parameters are set, this is a persistent/infinite scroll, so advance mode after 1 scroll cycle. - // If HA parameters ARE set, the mode relies on the check at the top to break out. - if (messageDisplaySeconds == 0 && messageScrollTimes == 0) { - P.setTextAlignment(PA_CENTER); - advanceDisplayMode(); - } - - yield(); - return; -} - - unsigned long currentMillis = millis(); unsigned long runtimeSeconds = (currentMillis - bootMillis) / 1000; unsigned long currentTotal = totalUptimeSeconds + runtimeSeconds;