From a29aefc9c0c02c23862fded29e3f950ead339238 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Sat, 24 Apr 2021 01:29:30 -0500
Subject: [PATCH] Move last bootscreen delay to end of setup (#21665)

---
 Marlin/src/MarlinCore.cpp                   | 11 ++++++++++-
 Marlin/src/core/utility.cpp                 | 12 ++++++++++++
 Marlin/src/core/utility.h                   |  8 ++++++--
 Marlin/src/lcd/HD44780/marlinui_HD44780.cpp |  2 ++
 Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp |  5 ++++-
 Marlin/src/lcd/dogm/marlinui_DOGM.cpp       | 16 ++++++++++------
 Marlin/src/lcd/marlinui.h                   |  1 +
 Marlin/src/lcd/tft/ui_320x240.cpp           |  7 ++++++-
 Marlin/src/lcd/tft/ui_480x320.cpp           |  7 ++++++-
 9 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index 668f977b03..6cb51bc577 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -1214,8 +1214,9 @@ void setup() {
     DWIN_UpdateLCD();     // Show bootscreen (first image)
   #else
     SETUP_RUN(ui.init());
-    #if HAS_WIRED_LCD && ENABLED(SHOW_BOOTSCREEN)
+    #if BOTH(HAS_WIRED_LCD, SHOW_BOOTSCREEN)
       SETUP_RUN(ui.show_bootscreen());
+      const millis_t bootscreen_ms = millis();
     #endif
     SETUP_RUN(ui.reset_status());     // Load welcome message early. (Retained if no errors exist.)
   #endif
@@ -1501,6 +1502,14 @@ void setup() {
     SETUP_RUN(tft_lvgl_init());
   #endif
 
+  #if BOTH(HAS_WIRED_LCD, SHOW_BOOTSCREEN)
+    const millis_t elapsed = millis() - bootscreen_ms;
+    #if ENABLED(MARLIN_DEV_MODE)
+      SERIAL_ECHOLNPAIR("elapsed=", elapsed);
+    #endif
+    SETUP_RUN(ui.bootscreen_completion(elapsed));
+  #endif
+
   #if ENABLED(PASSWORD_ON_STARTUP)
     SETUP_RUN(password.lock_machine());      // Will not proceed until correct password provided
   #endif
diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp
index 3d7897f95a..385a572029 100644
--- a/Marlin/src/core/utility.cpp
+++ b/Marlin/src/core/utility.cpp
@@ -35,6 +35,18 @@ void safe_delay(millis_t ms) {
   thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
 }
 
+#if ENABLED(MARLIN_DEV_MODE)
+  void early_safe_delay(millis_t ms) {
+    while (ms > 50) {
+      ms -= 50;
+      delay(50);
+      watchdog_refresh();
+    }
+    delay(ms);
+    watchdog_refresh();
+  }
+#endif
+
 // A delay to provide brittle hosts time to receive bytes
 #if ENABLED(SERIAL_OVERRUN_PROTECTION)
 
diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h
index aaa241d460..0e1c109be1 100644
--- a/Marlin/src/core/utility.h
+++ b/Marlin/src/core/utility.h
@@ -25,8 +25,12 @@
 #include "../core/types.h"
 #include "../core/millis_t.h"
 
-// Delay that ensures heaters and watchdog are kept alive
-void safe_delay(millis_t ms);
+void safe_delay(millis_t ms);           // Delay ensuring that temperatures are updated and the watchdog is kept alive.
+#if ENABLED(MARLIN_DEV_MODE)
+  void early_safe_delay(millis_t ms);   // Delay ensuring that the watchdog is kept alive. Can be used before the Temperature ISR starts.
+#else
+  inline void early_safe_delay(millis_t ms) { safe_delay(ms); }
+#endif
 
 #if ENABLED(SERIAL_OVERRUN_PROTECTION)
   void serial_delay(const millis_t ms);
diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
index e91213b5b7..75ff1f52c2 100644
--- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
+++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp
@@ -486,7 +486,9 @@ void MarlinUI::clear_lcd() { lcd.clear(); }
         CENTER_OR_SCROLL(STRING_SPLASH_LINE3, 1500);
       #endif
     }
+  }
 
+  void MarlinUI::bootscreen_completion(const millis_t) {
     lcd.clear();
     safe_delay(100);
     set_custom_characters(CHARSET_INFO);
diff --git a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp
index 31cdc4ac30..edb17b69c0 100644
--- a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp
+++ b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp
@@ -397,7 +397,10 @@ static void center_text_P(PGM_P pstart, uint8_t y) {
     center_text_P(PSTR(MARLIN_WEBSITE_URL), 4);
     picBits = ICON_LOGO;
     lcd.print_screen();
-    safe_delay(1500);
+  }
+
+  void MarlinUI::bootscreen_completion(const millis_t sofar) {
+    if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar);
   }
 
 #endif // SHOW_BOOTSCREEN
diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
index f298e7be8b..1fdc291642 100644
--- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
+++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
@@ -160,20 +160,21 @@ bool MarlinUI::detected() { return true; }
           #endif
           u8g.firstPage();
           do { draw_custom_bootscreen(f); } while (u8g.nextPage());
-          if (frame_time) safe_delay(frame_time);
+          if (frame_time) early_safe_delay(frame_time);
         }
 
       #ifndef CUSTOM_BOOTSCREEN_TIMEOUT
         #define CUSTOM_BOOTSCREEN_TIMEOUT 2500
       #endif
       #if CUSTOM_BOOTSCREEN_TIMEOUT
-        safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT);
+        early_safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT);
       #endif
     }
   #endif // SHOW_CUSTOM_BOOTSCREEN
 
   // Two-part needed to display all info
   constexpr bool two_part = ((LCD_PIXEL_HEIGHT) - (START_BMPHEIGHT)) < ((MENU_FONT_ASCENT) * 2);
+  constexpr uint8_t bootscreen_pages = 1 + two_part;
 
   // Draw the static Marlin bootscreen from a u8g loop
   // or the animated boot screen within its own u8g loop
@@ -225,17 +226,16 @@ bool MarlinUI::detected() { return true; }
       constexpr millis_t frame_time = MARLIN_BOOTSCREEN_FRAME_TIME;
       LOOP_L_N(f, COUNT(marlin_bootscreen_animation)) {
         draw_bootscreen_bmp((uint8_t*)pgm_read_ptr(&marlin_bootscreen_animation[f]));
-        if (frame_time) safe_delay(frame_time);
+        if (frame_time) early_safe_delay(frame_time);
       }
     #endif
   }
 
   // Show the Marlin bootscreen, with the u8g loop and delays
   void MarlinUI::show_marlin_bootscreen() {
-    constexpr uint8_t pages = two_part ? 2 : 1;
-    for (uint8_t q = pages; q--;) {
+    for (uint8_t q = bootscreen_pages; q--;) {
       draw_marlin_bootscreen(q == 0);
-      safe_delay((BOOTSCREEN_TIMEOUT) / pages);
+      if (q) early_safe_delay((BOOTSCREEN_TIMEOUT) / bootscreen_pages);
     }
   }
 
@@ -244,6 +244,10 @@ bool MarlinUI::detected() { return true; }
     show_marlin_bootscreen();
   }
 
+  void MarlinUI::bootscreen_completion(const millis_t sofar) {
+    if ((BOOTSCREEN_TIMEOUT) / bootscreen_pages > sofar) safe_delay((BOOTSCREEN_TIMEOUT) / bootscreen_pages - sofar);
+  }
+
 #endif // SHOW_BOOTSCREEN
 
 #if ENABLED(LIGHTWEIGHT_UI)
diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h
index 24fedb039e..8cbb9ebd19 100644
--- a/Marlin/src/lcd/marlinui.h
+++ b/Marlin/src/lcd/marlinui.h
@@ -337,6 +337,7 @@ public:
         static void draw_marlin_bootscreen(const bool line2=false);
         static void show_marlin_bootscreen();
         static void show_bootscreen();
+        static void bootscreen_completion(const millis_t sofar);
       #endif
 
       #if HAS_MARLINUI_U8GLIB
diff --git a/Marlin/src/lcd/tft/ui_320x240.cpp b/Marlin/src/lcd/tft/ui_320x240.cpp
index 68457baa1c..8e7365932b 100644
--- a/Marlin/src/lcd/tft/ui_320x240.cpp
+++ b/Marlin/src/lcd/tft/ui_320x240.cpp
@@ -60,6 +60,7 @@ void MarlinUI::tft_idle() {
 }
 
 #if ENABLED(SHOW_BOOTSCREEN)
+
   void MarlinUI::show_bootscreen() {
     tft.queue.reset();
 
@@ -81,9 +82,13 @@ void MarlinUI::tft_idle() {
     #endif
 
     tft.queue.sync();
-    safe_delay(BOOTSCREEN_TIMEOUT);
+  }
+
+  void MarlinUI::bootscreen_completion(const millis_t sofar) {
+    if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar);
     clear_lcd();
   }
+
 #endif
 
 void MarlinUI::draw_kill_screen() {
diff --git a/Marlin/src/lcd/tft/ui_480x320.cpp b/Marlin/src/lcd/tft/ui_480x320.cpp
index 3150aff058..0d7e01683f 100644
--- a/Marlin/src/lcd/tft/ui_480x320.cpp
+++ b/Marlin/src/lcd/tft/ui_480x320.cpp
@@ -60,6 +60,7 @@ void MarlinUI::tft_idle() {
 }
 
 #if ENABLED(SHOW_BOOTSCREEN)
+
   void MarlinUI::show_bootscreen() {
     tft.queue.reset();
 
@@ -81,9 +82,13 @@ void MarlinUI::tft_idle() {
     #endif
 
     tft.queue.sync();
-    safe_delay(BOOTSCREEN_TIMEOUT);
+  }
+
+  void MarlinUI::bootscreen_completion(const millis_t sofar) {
+    if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar);
     clear_lcd();
   }
+
 #endif
 
 void MarlinUI::draw_kill_screen() {