|
|
@ -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); |
|
|
|
} |
|
|
|
|
|
|
@ -5412,6 +5469,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 +5477,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(); |
|
|
|
idle(true); |
|
|
|
#else |
|
|
|
current_position[E_AXIS] += AUTO_FILAMENT_CHANGE_LENGTH; |
|
|
|
destination[E_AXIS] = current_position[E_AXIS]; |
|
|
@ -5429,6 +5485,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 +5822,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 +6345,8 @@ void process_next_command() { |
|
|
|
default: code_is_good = false; |
|
|
|
} |
|
|
|
|
|
|
|
KEEPALIVE_STATE(NOT_BUSY); |
|
|
|
|
|
|
|
ExitUnknownCommand: |
|
|
|
|
|
|
|
// Still unknown command? Throw an error
|
|
|
@ -6972,9 +7033,18 @@ void disable_all_steppers() { |
|
|
|
/**
|
|
|
|
* Standard idle routine keeps the machine alive |
|
|
|
*/ |
|
|
|
void idle() { |
|
|
|
void idle( |
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
bool no_stepper_sleep/*=false*/ |
|
|
|
#endif |
|
|
|
) { |
|
|
|
manage_heater(); |
|
|
|
manage_inactivity(); |
|
|
|
manage_inactivity( |
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
no_stepper_sleep |
|
|
|
#endif |
|
|
|
); |
|
|
|
host_keepalive(); |
|
|
|
lcd_update(); |
|
|
|
} |
|
|
|
|
|
|
|