diff --git a/Marlin/Conditionals.h b/Marlin/Conditionals.h index bb17924a6..36ba39187 100644 --- a/Marlin/Conditionals.h +++ b/Marlin/Conditionals.h @@ -314,6 +314,13 @@ #define Z_SAFE_HOMING #endif + /** + * Avoid double-negatives for enabling features + */ + #if DISABLED(DISABLE_HOST_KEEPALIVE) + #define HOST_KEEPALIVE_FEATURE + #endif + /** * MAX_STEP_FREQUENCY differs for TOSHIBA */ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c7f9ae095..bb8b8ba26 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -646,6 +646,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 7fe9786e0..550cea0f0 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -426,6 +426,26 @@ static uint8_t target_extruder; int lpq_len = 20; #endif +#if ENABLED(HOST_KEEPALIVE_FEATURE) + + // States for managing Marlin and host communication + // Marlin sends messages if blocked or busy + enum MarlinBusyState { + NOT_BUSY, // Not in a handler + IN_HANDLER, // Processing a GCode + IN_PROCESS, // Known to be blocking command input (as in G29) + PAUSED_FOR_USER, // Blocking pending any input + PAUSED_FOR_INPUT // Blocking pending text input (concept) + }; + + static MarlinBusyState busy_state = NOT_BUSY; + static millis_t next_busy_signal_ms = -1; + #define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0) +#else + #define host_keepalive() ; + #define KEEPALIVE_STATE(n) ; +#endif // HOST_KEEPALIVE_FEATURE + //=========================================================================== //================================ Functions ================================ //=========================================================================== @@ -2130,6 +2150,35 @@ void unknown_command_error() { SERIAL_ECHOPGM("\"\n"); } +#if ENABLED(HOST_KEEPALIVE_FEATURE) + + void host_keepalive() { + millis_t ms = millis(); + if (busy_state != NOT_BUSY) { + if (ms < next_busy_signal_ms) return; + switch (busy_state) { + case NOT_BUSY: + break; + case IN_HANDLER: + case IN_PROCESS: + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(MSG_BUSY_PROCESSING); + break; + case PAUSED_FOR_USER: + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(MSG_BUSY_PAUSED_FOR_USER); + break; + case PAUSED_FOR_INPUT: + SERIAL_ECHO_START; + SERIAL_ECHOLNPGM(MSG_BUSY_PAUSED_FOR_INPUT); + break; + } + } + next_busy_signal_ms = ms + 2000UL; + } + +#endif //HOST_KEEPALIVE_FEATURE + /** * G0, G1: Coordinated movement of X Y Z E axes */ @@ -3219,6 +3268,8 @@ inline void gcode_G28() { st_synchronize(); #endif + KEEPALIVE_STATE(IN_HANDLER); + #if ENABLED(DEBUG_LEVELING_FEATURE) if (marlin_debug_flags & DEBUG_LEVELING) { SERIAL_ECHOLNPGM("<<< gcode_G29"); @@ -3325,12 +3376,16 @@ inline void gcode_G92() { refresh_cmd_timeout(); if (codenum > 0) { codenum += previous_cmd_ms; // wait until this time for a click + KEEPALIVE_STATE(PAUSED_FOR_USER); while (millis() < codenum && !lcd_clicked()) idle(); + KEEPALIVE_STATE(IN_HANDLER); lcd_ignore_click(false); } else { if (!lcd_detected()) return; + KEEPALIVE_STATE(PAUSED_FOR_USER); while (!lcd_clicked()) idle(); + KEEPALIVE_STATE(IN_HANDLER); } if (IS_SD_PRINTING) LCD_MESSAGEPGM(MSG_RESUMING); @@ -4963,6 +5018,8 @@ inline void gcode_M303() { if (e >=0 && e < EXTRUDERS) target_extruder = e; + + KEEPALIVE_STATE(NOT_BUSY); PID_autotune(temp, e, c); } @@ -5334,6 +5391,13 @@ inline void gcode_M503() { #if ENABLED(FILAMENTCHANGEENABLE) + inline void idle2() { + manage_heater(); + manage_inactivity(true); + host_keepalive(); + lcd_update(); + } + /** * M600: Pause for filament change * @@ -5412,6 +5476,7 @@ inline void gcode_M503() { delay(100); LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE); millis_t next_tick = 0; + KEEPALIVE_STATE(WAIT_FOR_USER); while (!lcd_clicked()) { #if DISABLED(AUTO_FILAMENT_CHANGE) millis_t ms = millis(); @@ -5419,9 +5484,7 @@ inline void gcode_M503() { lcd_quick_feedback(); next_tick = ms + 2500; // feedback every 2.5s while waiting } - manage_heater(); - manage_inactivity(true); - lcd_update(); + idle2(); #else current_position[E_AXIS] += AUTO_FILAMENT_CHANGE_LENGTH; destination[E_AXIS] = current_position[E_AXIS]; @@ -5429,6 +5492,7 @@ inline void gcode_M503() { st_synchronize(); #endif } // while(!lcd_clicked) + KEEPALIVE_STATE(IN_HANDLER); lcd_quick_feedback(); // click sound feedback #if ENABLED(AUTO_FILAMENT_CHANGE) @@ -5765,6 +5829,8 @@ void process_next_command() { seen_pointer = current_command; codenum = code_value_short(); + KEEPALIVE_STATE(IN_HANDLER); + // Handle a known G, M, or T switch (command_code) { case 'G': switch (codenum) { @@ -6286,6 +6352,8 @@ void process_next_command() { default: code_is_good = false; } + KEEPALIVE_STATE(NOT_BUSY); + ExitUnknownCommand: // Still unknown command? Throw an error @@ -6975,6 +7043,7 @@ void disable_all_steppers() { void idle() { manage_heater(); manage_inactivity(); + host_keepalive(); lcd_update(); } diff --git a/Marlin/example_configurations/Felix/Configuration.h b/Marlin/example_configurations/Felix/Configuration.h index 6c397725f..c9d7e970e 100644 --- a/Marlin/example_configurations/Felix/Configuration.h +++ b/Marlin/example_configurations/Felix/Configuration.h @@ -629,6 +629,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/Felix/Configuration_DUAL.h b/Marlin/example_configurations/Felix/Configuration_DUAL.h index 674025b9d..6f2cffa61 100644 --- a/Marlin/example_configurations/Felix/Configuration_DUAL.h +++ b/Marlin/example_configurations/Felix/Configuration_DUAL.h @@ -626,6 +626,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/Hephestos/Configuration.h b/Marlin/example_configurations/Hephestos/Configuration.h index 8f69858bd..7fdec04dd 100644 --- a/Marlin/example_configurations/Hephestos/Configuration.h +++ b/Marlin/example_configurations/Hephestos/Configuration.h @@ -638,6 +638,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/Hephestos_2/Configuration.h b/Marlin/example_configurations/Hephestos_2/Configuration.h index 201a2865e..b8a920bc7 100644 --- a/Marlin/example_configurations/Hephestos_2/Configuration.h +++ b/Marlin/example_configurations/Hephestos_2/Configuration.h @@ -641,6 +641,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/K8200/Configuration.h b/Marlin/example_configurations/K8200/Configuration.h index 94752253f..39aa59922 100644 --- a/Marlin/example_configurations/K8200/Configuration.h +++ b/Marlin/example_configurations/K8200/Configuration.h @@ -661,6 +661,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h index 9687deac0..8c5a6080f 100644 --- a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h +++ b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h @@ -646,6 +646,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/RigidBot/Configuration.h b/Marlin/example_configurations/RigidBot/Configuration.h index 61d1df7fd..ce55421b2 100644 --- a/Marlin/example_configurations/RigidBot/Configuration.h +++ b/Marlin/example_configurations/RigidBot/Configuration.h @@ -641,6 +641,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/SCARA/Configuration.h b/Marlin/example_configurations/SCARA/Configuration.h index ebaf29c86..2e56626b3 100644 --- a/Marlin/example_configurations/SCARA/Configuration.h +++ b/Marlin/example_configurations/SCARA/Configuration.h @@ -654,6 +654,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/TAZ4/Configuration.h b/Marlin/example_configurations/TAZ4/Configuration.h index 7067155e5..b6671fa6f 100644 --- a/Marlin/example_configurations/TAZ4/Configuration.h +++ b/Marlin/example_configurations/TAZ4/Configuration.h @@ -666,6 +666,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/WITBOX/Configuration.h b/Marlin/example_configurations/WITBOX/Configuration.h index f320e6ce2..7ca638c21 100644 --- a/Marlin/example_configurations/WITBOX/Configuration.h +++ b/Marlin/example_configurations/WITBOX/Configuration.h @@ -638,6 +638,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/adafruit/ST7565/Configuration.h b/Marlin/example_configurations/adafruit/ST7565/Configuration.h index 2fb0e1e20..705b9c39a 100644 --- a/Marlin/example_configurations/adafruit/ST7565/Configuration.h +++ b/Marlin/example_configurations/adafruit/ST7565/Configuration.h @@ -646,6 +646,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration.h b/Marlin/example_configurations/delta/biv2.5/Configuration.h index 65e428512..4b15caa8f 100644 --- a/Marlin/example_configurations/delta/biv2.5/Configuration.h +++ b/Marlin/example_configurations/delta/biv2.5/Configuration.h @@ -768,6 +768,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/delta/generic/Configuration.h b/Marlin/example_configurations/delta/generic/Configuration.h index 11e7e63ff..84dc90a36 100644 --- a/Marlin/example_configurations/delta/generic/Configuration.h +++ b/Marlin/example_configurations/delta/generic/Configuration.h @@ -768,6 +768,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration.h b/Marlin/example_configurations/delta/kossel_mini/Configuration.h index c65f5bebd..e43de5a18 100644 --- a/Marlin/example_configurations/delta/kossel_mini/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_mini/Configuration.h @@ -772,6 +772,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration.h b/Marlin/example_configurations/delta/kossel_pro/Configuration.h index b3dfc272f..b0755f581 100644 --- a/Marlin/example_configurations/delta/kossel_pro/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_pro/Configuration.h @@ -763,6 +763,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration.h b/Marlin/example_configurations/delta/kossel_xl/Configuration.h index 987e35346..ccda7a39e 100644 --- a/Marlin/example_configurations/delta/kossel_xl/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_xl/Configuration.h @@ -682,6 +682,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/makibox/Configuration.h b/Marlin/example_configurations/makibox/Configuration.h index 21229b297..43536fe6a 100644 --- a/Marlin/example_configurations/makibox/Configuration.h +++ b/Marlin/example_configurations/makibox/Configuration.h @@ -649,6 +649,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration.h b/Marlin/example_configurations/tvrrug/Round2/Configuration.h index 229ff1606..a8026d771 100644 --- a/Marlin/example_configurations/tvrrug/Round2/Configuration.h +++ b/Marlin/example_configurations/tvrrug/Round2/Configuration.h @@ -640,6 +640,14 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo #define EEPROM_CHITCHAT // Please keep turned on if you can. #endif +// +// Host Keepalive +// +// By default Marlin will send a busy status message to the host +// every 2 seconds when it can't accept commands. +// +//#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages. + // // M100 Free Memory Watcher // diff --git a/Marlin/language.h b/Marlin/language.h index e0fb3d9f2..3637babe3 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -124,6 +124,9 @@ #define MSG_COUNT_A " Count A: " #define MSG_ERR_KILLED "Printer halted. kill() called!" #define MSG_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)" +#define MSG_BUSY_PROCESSING "busy: processing" +#define MSG_BUSY_PAUSED_FOR_USER "busy: paused for user" +#define MSG_BUSY_PAUSED_FOR_INPUT "busy: paused for input" #define MSG_RESEND "Resend: " #define MSG_UNKNOWN_COMMAND "Unknown command: \"" #define MSG_ACTIVE_EXTRUDER "Active Extruder: "