|
|
@ -426,6 +426,26 @@ static uint8_t target_extruder;
|
|
|
|
int lpq_len = 20;
|
|
|
|
int lpq_len = 20;
|
|
|
|
#endif
|
|
|
|
#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 ================================
|
|
|
|
//================================ Functions ================================
|
|
|
|
//===========================================================================
|
|
|
|
//===========================================================================
|
|
|
@ -2130,6 +2150,35 @@ void unknown_command_error() {
|
|
|
|
SERIAL_ECHOPGM("\"\n");
|
|
|
|
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
|
|
|
|
* G0, G1: Coordinated movement of X Y Z E axes
|
|
|
|
*/
|
|
|
|
*/
|
|
|
@ -3219,6 +3268,8 @@ inline void gcode_G28() {
|
|
|
|
st_synchronize();
|
|
|
|
st_synchronize();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
|
|
if (marlin_debug_flags & DEBUG_LEVELING) {
|
|
|
|
if (marlin_debug_flags & DEBUG_LEVELING) {
|
|
|
|
SERIAL_ECHOLNPGM("<<< gcode_G29");
|
|
|
|
SERIAL_ECHOLNPGM("<<< gcode_G29");
|
|
|
@ -3325,12 +3376,16 @@ inline void gcode_G92() {
|
|
|
|
refresh_cmd_timeout();
|
|
|
|
refresh_cmd_timeout();
|
|
|
|
if (codenum > 0) {
|
|
|
|
if (codenum > 0) {
|
|
|
|
codenum += previous_cmd_ms; // wait until this time for a click
|
|
|
|
codenum += previous_cmd_ms; // wait until this time for a click
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
while (millis() < codenum && !lcd_clicked()) idle();
|
|
|
|
while (millis() < codenum && !lcd_clicked()) idle();
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
lcd_ignore_click(false);
|
|
|
|
lcd_ignore_click(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
if (!lcd_detected()) return;
|
|
|
|
if (!lcd_detected()) return;
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER);
|
|
|
|
while (!lcd_clicked()) idle();
|
|
|
|
while (!lcd_clicked()) idle();
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IS_SD_PRINTING)
|
|
|
|
if (IS_SD_PRINTING)
|
|
|
|
LCD_MESSAGEPGM(MSG_RESUMING);
|
|
|
|
LCD_MESSAGEPGM(MSG_RESUMING);
|
|
|
@ -4963,6 +5018,8 @@ inline void gcode_M303() {
|
|
|
|
|
|
|
|
|
|
|
|
if (e >=0 && e < EXTRUDERS)
|
|
|
|
if (e >=0 && e < EXTRUDERS)
|
|
|
|
target_extruder = e;
|
|
|
|
target_extruder = e;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(NOT_BUSY);
|
|
|
|
PID_autotune(temp, e, c);
|
|
|
|
PID_autotune(temp, e, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -5412,6 +5469,7 @@ inline void gcode_M503() {
|
|
|
|
delay(100);
|
|
|
|
delay(100);
|
|
|
|
LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE);
|
|
|
|
LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE);
|
|
|
|
millis_t next_tick = 0;
|
|
|
|
millis_t next_tick = 0;
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(WAIT_FOR_USER);
|
|
|
|
while (!lcd_clicked()) {
|
|
|
|
while (!lcd_clicked()) {
|
|
|
|
#if DISABLED(AUTO_FILAMENT_CHANGE)
|
|
|
|
#if DISABLED(AUTO_FILAMENT_CHANGE)
|
|
|
|
millis_t ms = millis();
|
|
|
|
millis_t ms = millis();
|
|
|
@ -5419,9 +5477,7 @@ inline void gcode_M503() {
|
|
|
|
lcd_quick_feedback();
|
|
|
|
lcd_quick_feedback();
|
|
|
|
next_tick = ms + 2500; // feedback every 2.5s while waiting
|
|
|
|
next_tick = ms + 2500; // feedback every 2.5s while waiting
|
|
|
|
}
|
|
|
|
}
|
|
|
|
manage_heater();
|
|
|
|
idle(true);
|
|
|
|
manage_inactivity(true);
|
|
|
|
|
|
|
|
lcd_update();
|
|
|
|
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
current_position[E_AXIS] += AUTO_FILAMENT_CHANGE_LENGTH;
|
|
|
|
current_position[E_AXIS] += AUTO_FILAMENT_CHANGE_LENGTH;
|
|
|
|
destination[E_AXIS] = current_position[E_AXIS];
|
|
|
|
destination[E_AXIS] = current_position[E_AXIS];
|
|
|
@ -5429,6 +5485,7 @@ inline void gcode_M503() {
|
|
|
|
st_synchronize();
|
|
|
|
st_synchronize();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
} // while(!lcd_clicked)
|
|
|
|
} // while(!lcd_clicked)
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
lcd_quick_feedback(); // click sound feedback
|
|
|
|
lcd_quick_feedback(); // click sound feedback
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_FILAMENT_CHANGE)
|
|
|
|
#if ENABLED(AUTO_FILAMENT_CHANGE)
|
|
|
@ -5765,6 +5822,8 @@ void process_next_command() {
|
|
|
|
seen_pointer = current_command;
|
|
|
|
seen_pointer = current_command;
|
|
|
|
codenum = code_value_short();
|
|
|
|
codenum = code_value_short();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER);
|
|
|
|
|
|
|
|
|
|
|
|
// Handle a known G, M, or T
|
|
|
|
// Handle a known G, M, or T
|
|
|
|
switch (command_code) {
|
|
|
|
switch (command_code) {
|
|
|
|
case 'G': switch (codenum) {
|
|
|
|
case 'G': switch (codenum) {
|
|
|
@ -6286,6 +6345,8 @@ void process_next_command() {
|
|
|
|
default: code_is_good = false;
|
|
|
|
default: code_is_good = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(NOT_BUSY);
|
|
|
|
|
|
|
|
|
|
|
|
ExitUnknownCommand:
|
|
|
|
ExitUnknownCommand:
|
|
|
|
|
|
|
|
|
|
|
|
// Still unknown command? Throw an error
|
|
|
|
// Still unknown command? Throw an error
|
|
|
@ -6972,9 +7033,18 @@ void disable_all_steppers() {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Standard idle routine keeps the machine alive
|
|
|
|
* Standard idle routine keeps the machine alive
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void idle() {
|
|
|
|
void idle(
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE)
|
|
|
|
|
|
|
|
bool no_stepper_sleep/*=false*/
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
) {
|
|
|
|
manage_heater();
|
|
|
|
manage_heater();
|
|
|
|
manage_inactivity();
|
|
|
|
manage_inactivity(
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE)
|
|
|
|
|
|
|
|
no_stepper_sleep
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
host_keepalive();
|
|
|
|
lcd_update();
|
|
|
|
lcd_update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|