diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 3a6582bbb1e6..0fd511e004d3 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -439,7 +439,6 @@ void startOrResumeJob() { /** * Minimal management of Marlin's core activities: - * - Check for Filament Runout * - Keep the command buffer full * - Check for maximum inactive time between commands * - Check for maximum inactive time between stepper commands @@ -450,13 +449,8 @@ void startOrResumeJob() { * - Check if an idle but hot extruder needs filament extruded (EXTRUDER_RUNOUT_PREVENT) * - Pulse FET_SAFETY_PIN if it exists */ - inline void manage_inactivity(const bool ignore_stepper_queue=false) { - #if HAS_FILAMENT_SENSOR - runout.run(); - #endif - if (queue.length < BUFSIZE) queue.get_available_commands(); const millis_t ms = millis(); @@ -640,9 +634,53 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) { } /** - * Standard idle routine keeps the machine alive + * Standard idle routine keeps the machine alive: + * - Core Marlin activities + * - Manage heaters (and Watchdog) + * - Max7219 heartbeat, animation, etc. + * + * Only after setup() is complete: + * - Handle filament runout sensors + * - Run HAL idle tasks + * - Handle Power-Loss Recovery + * - Run StallGuard endstop checks + * - Handle SD Card insert / remove + * - Handle USB Flash Drive insert / remove + * - Announce Host Keepalive state (if any) + * - Update the Print Job Timer state + * - Update the Beeper queue + * - Read Buttons and Update the LCD + * - Run i2c Position Encoders + * - Auto-report Temperatures / SD Status + * - Update the Prusa MMU2 + * - Handle Joystick jogging */ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { + + // Core Marlin activities + manage_inactivity(TERN_(ADVANCED_PAUSE_FEATURE, no_stepper_sleep)); + + // Manage Heaters (and Watchdog) + thermalManager.manage_heater(); + + // Max7219 heartbeat, animation, etc + #if ENABLED(MAX7219_DEBUG) + max7219.idle_tasks(); + #endif + + // Return if setup() isn't completed + if (marlin_state == MF_INITIALIZING) return; + + // Handle filament runout sensors + #if HAS_FILAMENT_SENSOR + runout.run(); + #endif + + // Run HAL idle tasks + #ifdef HAL_IDLETASK + HAL_idletask(); + #endif + // Handle Power-Loss Recovery #if ENABLED(POWER_LOSS_RECOVERY) && PIN_EXISTS(POWER_LOSS) recovery.outage(); @@ -656,29 +694,21 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { if (endstops.tmc_spi_homing_check()) break; #endif - // Max7219 heartbeat, animation, etc. - #if ENABLED(MAX7219_DEBUG) - max7219.idle_tasks(); + // Handle SD Card insert / remove + #if ENABLED(SDSUPPORT) + card.manage_media(); #endif - // Read Buttons and Update the LCD - ui.update(); + // Handle USB Flash Drive insert / remove + #if ENABLED(USB_FLASH_DRIVE_SUPPORT) + Sd2Card::idle(); + #endif // Announce Host Keepalive state (if any) #if ENABLED(HOST_KEEPALIVE_FEATURE) gcode.host_keepalive(); #endif - // Core Marlin activities - manage_inactivity( - #if ENABLED(ADVANCED_PAUSE_FEATURE) - no_stepper_sleep - #endif - ); - - // Manage heaters (and Watchdog) - thermalManager.manage_heater(); - // Update the Print Job Timer state #if ENABLED(PRINTCOUNTER) print_job_timer.tick(); @@ -689,6 +719,9 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { buzzer.tick(); #endif + // Read Buttons and Update the LCD + ui.update(); + // Run i2c Position Encoders #if ENABLED(I2C_POSITION_ENCODERS) static millis_t i2cpem_next_update_ms; @@ -701,11 +734,6 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { } #endif - // Run HAL idle tasks - #ifdef HAL_IDLETASK - HAL_idletask(); - #endif - // Auto-report Temperatures / SD Status #if HAS_AUTO_REPORTING if (!gcode.autoreport_paused) { @@ -718,11 +746,6 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { } #endif - // Handle USB Flash Drive insert / remove - #if ENABLED(USB_FLASH_DRIVE_SUPPORT) - Sd2Card::idle(); - #endif - // Update the Prusa MMU2 #if ENABLED(PRUSA_MMU2) mmu2.mmu_loop(); @@ -971,8 +994,8 @@ void setup() { SETUP_RUN(ui.show_bootscreen()); #endif - #if ENABLED(SDSUPPORT) && defined(SDCARD_CONNECTION) && !SD_CONNECTION_IS(LCD) - SETUP_RUN(card.mount()); // Mount onboard / custom SD card before settings.first_load + #if BOTH(SDSUPPORT, SDCARD_EEPROM_EMULATION) + SETUP_RUN(card.mount()); // Mount media with settings before first_load #endif SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults) @@ -1139,10 +1162,6 @@ void setup() { queue.inject_P(PSTR(STARTUP_COMMANDS)); #endif - #if ENABLED(INIT_SDCARD_ON_BOOT) && !HAS_SPI_LCD - SETUP_RUN(card.beginautostart()); - #endif - #if ENABLED(HOST_PROMPT_SUPPORT) SETUP_RUN(host_action_prompt_end()); #endif diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 79e12f36d19c..f838ba0410b2 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -1139,28 +1139,7 @@ void MarlinUI::init() { ExtUI::onStartup(); } -void MarlinUI::update() { - #if ENABLED(SDSUPPORT) - static bool last_sd_status; - const bool sd_status = IS_SD_INSERTED(); - if (sd_status != last_sd_status) { - last_sd_status = sd_status; - if (sd_status) { - card.mount(); - if (card.isMounted()) - ExtUI::onMediaInserted(); - else - ExtUI::onMediaError(); - } - else { - const bool ok = card.isMounted(); - card.release(); - if (ok) ExtUI::onMediaRemoved(); - } - } - #endif // SDSUPPORT - ExtUI::onIdle(); -} +void MarlinUI::update() { ExtUI::onIdle(); } void MarlinUI::kill_screen(PGM_P const error, PGM_P const component) { using namespace ExtUI; diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index ff0331eb2072..10a717b6fe2e 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -121,10 +121,6 @@ MarlinUI ui; #endif #endif -#if ENABLED(INIT_SDCARD_ON_BOOT) - uint8_t lcd_sd_status; -#endif - #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS bool MarlinUI::defer_return_to_status; #endif @@ -342,13 +338,8 @@ void MarlinUI::init() { #endif // HAS_SHIFT_ENCODER - #if ENABLED(SDSUPPORT) - #if PIN_EXISTS(SD_DETECT) - SET_INPUT_PULLUP(SD_DETECT_PIN); - #endif - #if ENABLED(INIT_SDCARD_ON_BOOT) - lcd_sd_status = 2; // UNKNOWN - #endif + #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) + SET_INPUT_PULLUP(SD_DETECT_PIN); #endif #if HAS_ENCODER_ACTION && HAS_SLOW_BUTTONS @@ -744,11 +735,11 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) { */ LCDViewAction MarlinUI::lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW; +millis_t next_lcd_update_ms; void MarlinUI::update() { static uint16_t max_display_update_time = 0; - static millis_t next_lcd_update_ms; millis_t ms = millis(); #if HAS_LCD_MENU && LCD_TIMEOUT_TO_STATUS @@ -824,53 +815,6 @@ void MarlinUI::update() { #endif // HAS_LCD_MENU - #if ENABLED(INIT_SDCARD_ON_BOOT) - // - // SPI SD Card detection (and first card init when the LCD is present) - // - const uint8_t sd_status = (uint8_t)IS_SD_INSERTED(); - if (sd_status != lcd_sd_status && detected()) { - - uint8_t old_sd_status = lcd_sd_status; // prevent re-entry to this block! - lcd_sd_status = sd_status; - - if (sd_status) { - safe_delay(500); // Some boards need a delay to get settled - card.mount(); - if (old_sd_status == 2) - card.beginautostart(); // Initial boot - else - set_status_P(GET_TEXT(MSG_MEDIA_INSERTED)); - } - #if PIN_EXISTS(SD_DETECT) - else { - card.release(); - if (old_sd_status != 2) { - set_status_P(GET_TEXT(MSG_MEDIA_REMOVED)); - #if HAS_LCD_MENU - return_to_status(); - #endif - } - } - - #if DISABLED(NO_LCD_REINIT) - init_lcd(); // May revive the LCD if static electricity killed it - #endif - - #endif - - refresh(); - - ms = millis(); - next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL; // delay LCD update until after SD activity completes - - #ifdef LED_BACKLIGHT_TIMEOUT - leds.reset_timeout(ms); - #endif - } - - #endif // INIT_SDCARD_ON_BOOT - if (ELAPSED(ms, next_lcd_update_ms) #if HAS_GRAPHICAL_LCD || drawing_screen @@ -1595,3 +1539,55 @@ void MarlinUI::update() { } #endif // !HAS_DISPLAY + +#if ENABLED(SDSUPPORT) + + void MarlinUI::media_changed(const uint8_t old_status, const uint8_t status) { + if (old_status == status) { + #if ENABLED(EXTENSIBLE_UI) + ExtUI::onMediaError(); // Failed to mount/unmount + #endif + return; + } + + if (status) { + #if ENABLED(EXTENSIBLE_UI) + ExtUI::onMediaInserted(); // ExtUI response + #endif + if (old_status < 2) + set_status_P(GET_TEXT(MSG_MEDIA_INSERTED)); + } + else { + #if ENABLED(EXTENSIBLE_UI) + ExtUI::onMediaRemoved(); // ExtUI response + #endif + if (old_status < 2) { + #if PIN_EXISTS(SD_DETECT) + set_status_P(GET_TEXT(MSG_MEDIA_REMOVED)); + #if HAS_LCD_MENU + return_to_status(); + #endif + #endif + } + } + + #if PIN_EXISTS(SD_DETECT) && DISABLED(NO_LCD_REINIT) + init_lcd(); // Revive a noisy shared SPI LCD + #endif + + refresh(); + + #if HAS_SPI_LCD || defined(LED_BACKLIGHT_TIMEOUT) + const millis_t ms = millis(); + #endif + + #if HAS_SPI_LCD + next_lcd_update_ms = ms + LCD_UPDATE_INTERVAL; // Delay LCD update for SD activity + #endif + + #ifdef LED_BACKLIGHT_TIMEOUT + leds.reset_timeout(ms); + #endif + } + +#endif // SDSUPPORT diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h index 2737a1a64883..0be82ff1f687 100644 --- a/Marlin/src/lcd/ultralcd.h +++ b/Marlin/src/lcd/ultralcd.h @@ -274,6 +274,10 @@ class MarlinUI { // LCD implementations static void clear_lcd(); + #if ENABLED(SDSUPPORT) + static void media_changed(const uint8_t old_stat, const uint8_t stat); + #endif + #if HAS_SPI_LCD static bool detected(); static void init_lcd(); diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 80e94b88b580..0199aa65af6b 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -378,6 +378,35 @@ void CardReader::mount() { ui.refresh(); } +/** + * Handle SD card events + */ +void CardReader::manage_media() { + static uint8_t prev_stat = TERN(INIT_SDCARD_ON_BOOT, 2, 0); + uint8_t stat = uint8_t(IS_SD_INSERTED()); + if (stat != prev_stat && ui.detected()) { + + uint8_t old_stat = prev_stat; + prev_stat = stat; // Change now to prevent re-entry + + if (stat) { // Media Inserted + safe_delay(500); // Some boards need a delay to get settled + mount(); // Try to mount the media + if (!isMounted()) stat = 0; // Not mounted? + } + else { + #if PIN_EXISTS(SD_DETECT) + release(); // Card is released + #endif + } + + ui.media_changed(old_stat, stat); // Update the UI + + if (stat && old_stat == 2) // First mount? + beginautostart(); // Look for autostart files soon + } +} + void CardReader::release() { endFilePrint(); flag.mounted = false; diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index 955a8b69b39e..1fee807495f5 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -73,6 +73,9 @@ class CardReader { static inline bool isMounted() { return flag.mounted; } static void ls(); + // Handle media insert/remove + static void manage_media(); + // SD Card Logging static void openLogFile(char * const path); static void write_command(char * const buf);