From 4c872a01f284cbf181f52c84e2ba6b4618e62556 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 19 Jun 2019 00:00:19 -0500 Subject: [PATCH] G-code queue singleton, front injection (#14236) --- Marlin/src/Marlin.cpp | 18 +- Marlin/src/core/macros.h | 4 +- Marlin/src/feature/host_actions.cpp | 2 +- Marlin/src/feature/power_loss_recovery.cpp | 18 +- Marlin/src/feature/power_loss_recovery.h | 4 +- Marlin/src/feature/prusa_MMU2/mmu2.cpp | 2 +- Marlin/src/gcode/bedlevel/abl/G29.cpp | 2 +- Marlin/src/gcode/bedlevel/mbl/G29.cpp | 2 +- Marlin/src/gcode/calibrate/M100.cpp | 2 +- Marlin/src/gcode/control/M999.cpp | 3 +- Marlin/src/gcode/gcode.cpp | 12 +- Marlin/src/gcode/gcode.h | 2 +- Marlin/src/gcode/host/M110.cpp | 4 +- Marlin/src/gcode/queue.cpp | 270 ++++++++----------- Marlin/src/gcode/queue.h | 204 +++++++------- Marlin/src/gcode/sdcard/M28_M29.cpp | 2 +- Marlin/src/lcd/extensible_ui/ui_api.cpp | 4 +- Marlin/src/lcd/malyanlcd.cpp | 12 +- Marlin/src/lcd/menu/menu.cpp | 10 +- Marlin/src/lcd/menu/menu.h | 4 +- Marlin/src/lcd/menu/menu_advanced.cpp | 4 +- Marlin/src/lcd/menu/menu_bed_corners.cpp | 2 +- Marlin/src/lcd/menu/menu_bed_leveling.cpp | 10 +- Marlin/src/lcd/menu/menu_configuration.cpp | 2 +- Marlin/src/lcd/menu/menu_custom.cpp | 2 +- Marlin/src/lcd/menu/menu_delta_calibrate.cpp | 2 +- Marlin/src/lcd/menu/menu_filament.cpp | 2 +- Marlin/src/lcd/menu/menu_job_recovery.cpp | 2 +- Marlin/src/lcd/menu/menu_ubl.cpp | 70 ++--- Marlin/src/lcd/ultralcd.cpp | 8 +- Marlin/src/module/planner.h | 2 +- Marlin/src/sd/cardreader.cpp | 6 +- 32 files changed, 337 insertions(+), 356 deletions(-) diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp index b21d5593fd..ef07116368 100644 --- a/Marlin/src/Marlin.cpp +++ b/Marlin/src/Marlin.cpp @@ -369,7 +369,7 @@ void disable_all_steppers() { #endif // HOST_ACTION_COMMANDS if (run_runout_script) - enqueue_and_echo_commands_front_P(PSTR(FILAMENT_RUNOUT_SCRIPT)); + queue.inject_P(PSTR(FILAMENT_RUNOUT_SCRIPT)); } #endif // HAS_FILAMENT_SENSOR @@ -425,7 +425,7 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) { runout.run(); #endif - if (commands_in_queue < BUFSIZE) get_available_commands(); + if (queue.length < BUFSIZE) queue.get_available_commands(); const millis_t ms = millis(); @@ -508,7 +508,7 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) { const int HOME_DEBOUNCE_DELAY = 2500; if (!IS_SD_PRINTING() && !READ(HOME_PIN)) { if (!homeDebounceCount) { - enqueue_and_echo_commands_P(PSTR("G28")); + queue.inject_P(PSTR("G28")); LCD_MESSAGEPGM(MSG_AUTO_HOME); } if (homeDebounceCount < HOME_DEBOUNCE_DELAY) @@ -797,7 +797,7 @@ void stop() { #endif if (IsRunning()) { - Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart + queue.stop(); SERIAL_ERROR_MSG(MSG_ERR_STOPPED); LCD_MESSAGEPGM(MSG_STOPPED); safe_delay(350); // allow enough time for messages to get out before stopping @@ -926,8 +926,6 @@ void setup() { SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(MSG_FREE_MEMORY, freeMemory(), MSG_PLANNER_BUFFER_BYTES, (int)sizeof(block_t) * (BLOCK_BUFFER_SIZE)); - queue_setup(); - // UI must be initialized before EEPROM // (because EEPROM code calls the UI). ui.init(); @@ -1135,7 +1133,7 @@ void loop() { true #endif ); - clear_command_queue(); + queue.clear(); quickstop_stepper(); print_job_timer.stop(); #if DISABLED(SD_ABORT_NO_COOLDOWN) @@ -1147,14 +1145,14 @@ void loop() { card.removeJobRecoveryFile(); #endif #ifdef EVENT_GCODE_SD_STOP - enqueue_and_echo_commands_P(PSTR(EVENT_GCODE_SD_STOP)); + queue.inject_P(PSTR(EVENT_GCODE_SD_STOP)); #endif } #endif // SDSUPPORT - if (commands_in_queue < BUFSIZE) get_available_commands(); - advance_command_queue(); + if (queue.length < BUFSIZE) queue.get_available_commands(); + queue.advance(); endstops.event_handler(); idle(); } diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 3805c216fe..2faf9900d1 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -56,7 +56,9 @@ #define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU) // Remove compiler warning on an unused variable -#define UNUSED(X) (void)X +#ifndef UNUSED + #define UNUSED(x) ((void)(x)) +#endif // Macros to make a string from a macro #define STRINGIFY_(M) #M diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index 1154553e27..6893f2c593 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -142,7 +142,7 @@ void host_action(const char * const pstr, const bool eol) { break; case PROMPT_PAUSE_RESUME: msg = PSTR("LCD_PAUSE_RESUME"); - enqueue_and_echo_commands_P(PSTR("M24")); + queue.inject_P(PSTR("M24")); break; case PROMPT_INFO: msg = PSTR("GCODE_INFO"); diff --git a/Marlin/src/feature/power_loss_recovery.cpp b/Marlin/src/feature/power_loss_recovery.cpp index 3605d0e486..6394a611c0 100644 --- a/Marlin/src/feature/power_loss_recovery.cpp +++ b/Marlin/src/feature/power_loss_recovery.cpp @@ -98,7 +98,7 @@ void PrintJobRecovery::check() { if (card.isDetected()) { load(); if (!valid()) return purge(); - enqueue_and_echo_commands_P(PSTR("M1000 S")); + queue.inject_P(PSTR("M1000 S")); } } } @@ -209,9 +209,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*= info.relative_modes_e = gcode.axis_relative_modes[E_AXIS]; // Commands in the queue - info.commands_in_queue = save_queue ? commands_in_queue : 0; - info.cmd_queue_index_r = cmd_queue_index_r; - COPY(info.command_queue, command_queue); + info.queue_length = save_queue ? queue.length : 0; + info.queue_index_r = queue.index_r; + COPY(info.queue_buffer, queue.buffer); // Elapsed print job time info.print_job_elapsed = print_job_timer.duration(); @@ -402,9 +402,9 @@ void PrintJobRecovery::resume() { #endif // Process commands from the old pending queue - uint8_t c = info.commands_in_queue, r = info.cmd_queue_index_r; + uint8_t c = info.queue_length, r = info.queue_index_r; for (; c--; r = (r + 1) % BUFSIZE) - gcode.process_subcommands_now(info.command_queue[r]); + gcode.process_subcommands_now(info.queue_buffer[r]); // Resume the SD file from the last position char *fn = info.sd_filename; @@ -484,9 +484,9 @@ void PrintJobRecovery::resume() { DEBUG_EOL(); DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop); #endif - DEBUG_ECHOLNPAIR("cmd_queue_index_r: ", int(info.cmd_queue_index_r)); - DEBUG_ECHOLNPAIR("commands_in_queue: ", int(info.commands_in_queue)); - for (uint8_t i = 0; i < info.commands_in_queue; i++) DEBUG_ECHOLNPAIR("> ", info.command_queue[i]); + DEBUG_ECHOLNPAIR("queue_index_r: ", int(info.queue_index_r)); + DEBUG_ECHOLNPAIR("queue_length: ", int(info.queue_length)); + for (uint8_t i = 0; i < info.queue_length; i++) DEBUG_ECHOLNPAIR("> ", info.queue_buffer[i]); DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename); DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos); DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed); diff --git a/Marlin/src/feature/power_loss_recovery.h b/Marlin/src/feature/power_loss_recovery.h index e7f8c09124..b7684fccb6 100644 --- a/Marlin/src/feature/power_loss_recovery.h +++ b/Marlin/src/feature/power_loss_recovery.h @@ -87,8 +87,8 @@ typedef struct { bool relative_mode, relative_modes_e; // Command queue - uint8_t commands_in_queue, cmd_queue_index_r; - char command_queue[BUFSIZE][MAX_CMD_SIZE]; + uint8_t queue_length, queue_index_r; + char queue_buffer[BUFSIZE][MAX_CMD_SIZE]; // SD Filename and position char sd_filename[MAXPATHNAMELENGTH]; diff --git a/Marlin/src/feature/prusa_MMU2/mmu2.cpp b/Marlin/src/feature/prusa_MMU2/mmu2.cpp index b3eb60bf5e..0870b168ba 100644 --- a/Marlin/src/feature/prusa_MMU2/mmu2.cpp +++ b/Marlin/src/feature/prusa_MMU2/mmu2.cpp @@ -650,7 +650,7 @@ void MMU2::set_filament_type(uint8_t index, uint8_t filamentType) { } void MMU2::filament_runout() { - enqueue_and_echo_commands_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT)); + queue.inject_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT)); planner.synchronize(); } diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index f43cfa6a35..bcef33ec4a 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -966,7 +966,7 @@ G29_TYPE GcodeSuite::G29() { #ifdef Z_PROBE_END_SCRIPT if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Z Probe End Script: ", Z_PROBE_END_SCRIPT); planner.synchronize(); - enqueue_and_echo_commands_P(PSTR(Z_PROBE_END_SCRIPT)); + queue.inject_P(PSTR(Z_PROBE_END_SCRIPT)); #endif // Auto Bed Leveling is complete! Enable if possible. diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index dd6faea955..6a073f577e 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -85,7 +85,7 @@ void GcodeSuite::G29() { mbl.reset(); mbl_probe_index = 0; if (!ui.wait_for_bl_move) { - enqueue_and_echo_commands_P(PSTR("G28\nG29 S2")); + queue.inject_P(PSTR("G28\nG29 S2")); return; } state = MeshNext; diff --git a/Marlin/src/gcode/calibrate/M100.cpp b/Marlin/src/gcode/calibrate/M100.cpp index bc3c0fc59b..53eb4c0ace 100644 --- a/Marlin/src/gcode/calibrate/M100.cpp +++ b/Marlin/src/gcode/calibrate/M100.cpp @@ -153,7 +153,7 @@ inline int32_t count_test_bytes(const char * const start_free_memory) { SERIAL_CHAR('|'); // Point out non test bytes for (uint8_t i = 0; i < 16; i++) { char ccc = (char)start_free_memory[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken - if (&start_free_memory[i] >= (char*)command_queue && &start_free_memory[i] < (char*)command_queue + sizeof(command_queue)) { // Print out ASCII in the command buffer area + if (&start_free_memory[i] >= (char*)queue.buffer && &start_free_memory[i] < (char*)queue.buffer + sizeof(queue.buffer)) { // Print out ASCII in the command buffer area if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' '; } else { // If not in the command buffer area, flag bytes that don't match the test byte diff --git a/Marlin/src/gcode/control/M999.cpp b/Marlin/src/gcode/control/M999.cpp index 1d2dfae733..6f8fe06f0f 100644 --- a/Marlin/src/gcode/control/M999.cpp +++ b/Marlin/src/gcode/control/M999.cpp @@ -42,6 +42,5 @@ void GcodeSuite::M999() { if (parser.boolval('S')) return; - // gcode_LastN = Stopped_gcode_LastN; - flush_and_request_resend(); + queue.flush_and_request_resend(); } diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 8607ae2eb8..98091f78fd 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -187,7 +187,7 @@ void GcodeSuite::dwell(millis_t time) { /** * Process the parsed command and dispatch it to its handler */ -void GcodeSuite::process_parsed_command(const bool no_ok) { +void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { KEEPALIVE_STATE(IN_HANDLER); // Handle a known G, M, or T @@ -798,7 +798,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok) { KEEPALIVE_STATE(NOT_BUSY); - if (!no_ok) ok_to_send(); + if (!no_ok) queue.ok_to_send(); } /** @@ -806,16 +806,16 @@ void GcodeSuite::process_parsed_command(const bool no_ok) { * This is called from the main loop() */ void GcodeSuite::process_next_command() { - char * const current_command = command_queue[cmd_queue_index_r]; + char * const current_command = queue.buffer[queue.index_r]; - PORT_REDIRECT(command_queue_port[cmd_queue_index_r]); + PORT_REDIRECT(queue.port[queue.index_r]); if (DEBUGGING(ECHO)) { SERIAL_ECHO_START(); SERIAL_ECHOLN(current_command); #if ENABLED(M100_FREE_MEMORY_DUMPER) - SERIAL_ECHOPAIR("slot:", cmd_queue_index_r); - M100_dump_routine(PSTR(" Command Queue:"), (const char*)command_queue, (const char*)(command_queue) + sizeof(command_queue)); + SERIAL_ECHOPAIR("slot:", queue.index_r); + M100_dump_routine(PSTR(" Command Queue:"), queue.buffer, queue.buffer + sizeof(queue.buffer)); #endif } diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 21f4a1cb80..0ec531e550 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -315,7 +315,7 @@ public: static void process_parsed_command(const bool no_ok=false); static void process_next_command(); - // Execute G-code as a macro, preserving parser state + // Execute G-code in-place, preserving current G-code parameters static void process_subcommands_now_P(PGM_P pgcode); static void process_subcommands_now(char * gcode); diff --git a/Marlin/src/gcode/host/M110.cpp b/Marlin/src/gcode/host/M110.cpp index 108f414d2b..33e6e67900 100644 --- a/Marlin/src/gcode/host/M110.cpp +++ b/Marlin/src/gcode/host/M110.cpp @@ -21,11 +21,11 @@ */ #include "../gcode.h" -#include "../queue.h" // for gcode_LastN +#include "../queue.h" // for last_N /** * M110: Set Current Line Number */ void GcodeSuite::M110() { - if (parser.seenval('N')) gcode_LastN = parser.value_long(); + if (parser.seenval('N')) queue.last_N = parser.value_long(); } diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp index afc76bbe1f..d09f678c3c 100644 --- a/Marlin/src/gcode/queue.cpp +++ b/Marlin/src/gcode/queue.cpp @@ -25,6 +25,8 @@ */ #include "queue.h" +GCodeQueue queue; + #include "gcode.h" #include "../lcd/ultralcd.h" @@ -42,7 +44,7 @@ * sending commands to Marlin, and lines will be checked for sequentiality. * M110 N sets the current line number. */ -long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; +long gcode_N, GCodeQueue::last_N, GCodeQueue::stopped_N = 0; /** * GCode Command Queue @@ -53,17 +55,17 @@ long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; * the main loop. The gcode.process_next_command method parses the next * command and hands off execution to individual handler functions. */ -uint8_t commands_in_queue = 0, // Count of commands in the queue - cmd_queue_index_r = 0, // Ring buffer read position - cmd_queue_index_w = 0; // Ring buffer write position +uint8_t GCodeQueue::length = 0, // Count of commands in the queue + GCodeQueue::index_r = 0, // Ring buffer read position + GCodeQueue::index_w = 0; // Ring buffer write position -char command_queue[BUFSIZE][MAX_CMD_SIZE]; +char GCodeQueue::buffer[BUFSIZE][MAX_CMD_SIZE]; /* * The port that the command was received on */ #if NUM_SERIAL > 1 - int16_t command_queue_port[BUFSIZE]; + int16_t GCodeQueue::port[BUFSIZE]; #endif /** @@ -82,7 +84,7 @@ bool send_ok[BUFSIZE]; */ static PGM_P injected_commands_P = nullptr; -void queue_setup() { +GCodeQueue::GCodeQueue() { // Send "ok" after commands by default for (uint8_t i = 0; i < COUNT(send_ok); i++) send_ok[i] = true; } @@ -90,24 +92,24 @@ void queue_setup() { /** * Clear the Marlin command queue */ -void clear_command_queue() { - cmd_queue_index_r = cmd_queue_index_w = commands_in_queue = 0; +void GCodeQueue::clear() { + index_r = index_w = length = 0; } /** * Once a new command is in the ring buffer, call this to commit it */ -inline void _commit_command(bool say_ok +void GCodeQueue::_commit_command(bool say_ok #if NUM_SERIAL > 1 - , int16_t port = -1 + , int16_t p/*=-1*/ #endif ) { - send_ok[cmd_queue_index_w] = say_ok; + send_ok[index_w] = say_ok; #if NUM_SERIAL > 1 - command_queue_port[cmd_queue_index_w] = port; + port[index_w] = p; #endif - if (++cmd_queue_index_w >= BUFSIZE) cmd_queue_index_w = 0; - commands_in_queue++; + if (++index_w >= BUFSIZE) index_w = 0; + length++; } /** @@ -115,16 +117,16 @@ inline void _commit_command(bool say_ok * Return true if the command was successfully added. * Return false for a full buffer, or if the 'command' is a comment. */ -inline bool _enqueuecommand(const char* cmd, bool say_ok=false +bool GCodeQueue::_enqueue(const char* cmd, bool say_ok/*=false*/ #if NUM_SERIAL > 1 - , int16_t port = -1 + , int16_t pn/*=-1*/ #endif ) { - if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false; - strcpy(command_queue[cmd_queue_index_w], cmd); + if (*cmd == ';' || length >= BUFSIZE) return false; + strcpy(buffer[index_w], cmd); _commit_command(say_ok #if NUM_SERIAL > 1 - , port + , pn #endif ); return true; @@ -134,15 +136,15 @@ inline bool _enqueuecommand(const char* cmd, bool say_ok=false * Enqueue with Serial Echo * Return true if the command was consumed */ -bool enqueue_and_echo_command(const char* cmd) { +bool GCodeQueue::enqueue_one(const char* cmd) { - //SERIAL_ECHOPGM("enqueue_and_echo_command(\""); + //SERIAL_ECHOPGM("enqueue_one(\""); //SERIAL_ECHO(cmd); //SERIAL_ECHOPGM("\") \n"); if (*cmd == 0 || *cmd == '\n' || *cmd == '\r') return true; - if (_enqueuecommand(cmd)) { + if (_enqueue(cmd)) { SERIAL_ECHO_START(); SERIAL_ECHOLNPAIR(MSG_ENQUEUEING, cmd, "\""); return true; @@ -150,104 +152,67 @@ bool enqueue_and_echo_command(const char* cmd) { return false; } -#if HAS_QUEUE_FRONT - - bool early_cmd; // = false - - /** - * Insert a high Priority command from RAM into the main command buffer. - * Return true if the command was consumed - * Return false for a full buffer, or if the 'command' is a comment. - */ - inline bool _enqueuecommand_front(const char* cmd) { - if (*cmd == 0 || *cmd == '\n' || *cmd == '\r') return true; - if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false; - if (cmd_queue_index_r == 0) cmd_queue_index_r = BUFSIZE; - --cmd_queue_index_r; - strcpy(command_queue[cmd_queue_index_r], cmd); - send_ok[cmd_queue_index_r] = false; - #if NUM_SERIAL > 1 - command_queue_port[cmd_queue_index_r] = -1; - #endif - commands_in_queue++; - return true; - } - - /** - * Insert in the front of queue, one or many commands to run from program memory. - * Aborts the current queue, if any. - * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards - */ - void enqueue_and_echo_commands_front_P(PGM_P const pgcode) { - early_cmd = true; - enqueue_and_echo_commands_P(pgcode); - } - -#endif - /** - * Inject the next "immediate" command, when possible, onto the front of the queue. - * Return true if any immediate commands remain to inject. - * Do not inject a comment or use leading space!. + * Process the next "immediate" command. */ -static bool drain_injected_commands_P() { - while (injected_commands_P != nullptr) { - size_t i = 0; - char c, cmd[60]; - strncpy_P(cmd, injected_commands_P, sizeof(cmd) - 1); - cmd[sizeof(cmd) - 1] = '\0'; - while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command - cmd[i] = '\0'; +bool GCodeQueue::process_injected_command() { + if (injected_commands_P == nullptr) return false; - if ( - #if HAS_QUEUE_FRONT - early_cmd ? _enqueuecommand_front(cmd) : - #endif - enqueue_and_echo_command(cmd) - ) { - injected_commands_P = c ? injected_commands_P + i + 1 : nullptr; // next command or done - #if HAS_QUEUE_FRONT - if (!c) early_cmd = false; - #endif - } - else - return true; // buffer is full (or command is comment); - } - return false; // return whether any more remain + char c; + size_t i = 0; + while ((c = pgm_read_byte(&injected_commands_P[i])) && c != '\n') i++; + if (!i) return false; + + char cmd[i + 1]; + memcpy_P(cmd, injected_commands_P, i); + cmd[i] = '\0'; + + injected_commands_P = c ? injected_commands_P + i + 1 : nullptr; + + parser.parse(cmd); + PORT_REDIRECT(SERIAL_PORT); + gcode.process_parsed_command(); + PORT_RESTORE(); + + return true; } /** * Enqueue one or many commands to run from program memory. + * Do not inject a comment or use leading spaces! * Aborts the current queue, if any. - * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards + * Note: process_injected_command() will be called to drain any commands afterwards */ -void enqueue_and_echo_commands_P(PGM_P const pgcode) { - #if HAS_QUEUE_FRONT - early_cmd = false; - #endif +void GCodeQueue::inject_P(PGM_P const pgcode) { injected_commands_P = pgcode; - (void)drain_injected_commands_P(); // first command executed asap (when possible) } -#if HAS_QUEUE_NOW - /** - * Enqueue and return only when commands are actually enqueued. - * Never call this from a G-code handler! - */ - void enqueue_and_echo_command_now(const char* cmd) { - while (!enqueue_and_echo_command(cmd)) idle(); +/** + * Enqueue and return only when commands are actually enqueued. + * Never call this from a G-code handler! + */ +void GCodeQueue::enqueue_one_now(const char* cmd) { + while (!enqueue_one(cmd)) idle(); +} + +/** + * Enqueue from program memory and return only when commands are actually enqueued + * Never call this from a G-code handler! + */ +void GCodeQueue::enqueue_now_P(PGM_P const pgcode) { + size_t i = 0; + PGM_P p = pgcode; + for (;;) { + char c; + while ((c = p[i]) && c != '\n') i++; + char cmd[i + 1]; + memcpy_P(cmd, p, i); + cmd[i] = '\0'; + enqueue_one_now(cmd); + if (!c) break; + p += i + 1; } - #if HAS_LCD_QUEUE_NOW - /** - * Enqueue from program memory and return only when commands are actually enqueued - * Never call this from a G-code handler! - */ - void enqueue_and_echo_commands_now_P(PGM_P const pgcode) { - enqueue_and_echo_commands_P(pgcode); - while (drain_injected_commands_P()) idle(); - } - #endif -#endif +} /** * Send an "ok" message to the host, indicating @@ -258,16 +223,16 @@ void enqueue_and_echo_commands_P(PGM_P const pgcode) { * P Planner space remaining * B Block queue space remaining */ -void ok_to_send() { +void GCodeQueue::ok_to_send() { #if NUM_SERIAL > 1 - const int16_t port = command_queue_port[cmd_queue_index_r]; - if (port < 0) return; - PORT_REDIRECT(port); + const int16_t p = port[index_r]; + if (p < 0) return; + PORT_REDIRECT(p); #endif - if (!send_ok[cmd_queue_index_r]) return; + if (!send_ok[index_r]) return; SERIAL_ECHOPGM(MSG_OK); #if ENABLED(ADVANCED_OK) - char* p = command_queue[cmd_queue_index_r]; + char* p = buffer[index_r]; if (*p == 'N') { SERIAL_ECHO(' '); SERIAL_ECHO(*p++); @@ -275,7 +240,7 @@ void ok_to_send() { SERIAL_ECHO(*p++); } SERIAL_ECHOPGM(" P"); SERIAL_ECHO(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1)); - SERIAL_ECHOPGM(" B"); SERIAL_ECHO(BUFSIZE - commands_in_queue); + SERIAL_ECHOPGM(" B"); SERIAL_ECHO(BUFSIZE - length); #endif SERIAL_EOL(); } @@ -284,15 +249,15 @@ void ok_to_send() { * Send a "Resend: nnn" message to the host to * indicate that a command needs to be re-sent. */ -void flush_and_request_resend() { +void GCodeQueue::flush_and_request_resend() { #if NUM_SERIAL > 1 - const int16_t port = command_queue_port[cmd_queue_index_r]; - if (port < 0) return; - PORT_REDIRECT(port); + const int16_t p = port[index_r]; + if (p < 0) return; + PORT_REDIRECT(p); #endif SERIAL_FLUSH(); SERIAL_ECHOPGM(MSG_RESEND); - SERIAL_ECHOLN(gcode_LastN + 1); + SERIAL_ECHOLN(last_N + 1); ok_to_send(); } @@ -315,16 +280,6 @@ inline int read_serial(const uint8_t index) { } } -void gcode_line_error(PGM_P const err, const int8_t port) { - PORT_REDIRECT(port); - SERIAL_ERROR_START(); - serialprintPGM(err); - SERIAL_ECHOLN(gcode_LastN); - while (read_serial(port) != -1); // clear out the RX buffer - flush_and_request_resend(); - serial_count[port] = 0; -} - #if ENABLED(BINARY_FILE_TRANSFER) inline bool serial_data_available(const uint8_t index) { @@ -575,6 +530,16 @@ void gcode_line_error(PGM_P const err, const int8_t port) { #endif // BINARY_FILE_TRANSFER +void GCodeQueue::gcode_line_error(PGM_P const err, const int8_t port) { + PORT_REDIRECT(port); + SERIAL_ERROR_START(); + serialprintPGM(err); + SERIAL_ECHOLN(last_N); + while (read_serial(port) != -1); // clear out the RX buffer + flush_and_request_resend(); + serial_count[port] = 0; +} + FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", but not "M290", etc const char * const m29 = strstr_P(cmd, PSTR("M29")); return m29 && !NUMERIC(m29[3]); @@ -585,7 +550,7 @@ FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", b * Exit when the buffer is full or when no more characters are * left on the serial port. */ -inline void get_serial_commands() { +void GCodeQueue::get_serial_commands() { static char serial_line_buffer[NUM_SERIAL][MAX_CMD_SIZE]; static bool serial_comment_mode[NUM_SERIAL] = { false } #if ENABLED(PAREN_COMMENTS) @@ -610,7 +575,7 @@ inline void get_serial_commands() { #if NO_TIMEOUTS > 0 static millis_t last_command_time = 0; const millis_t ms = millis(); - if (commands_in_queue == 0 && !serial_data_available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) { + if (length == 0 && !serial_data_available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) { SERIAL_ECHOLNPGM(MSG_WAIT); last_command_time = ms; } @@ -619,7 +584,7 @@ inline void get_serial_commands() { /** * Loop while serial characters are incoming and the queue is not full */ - while (commands_in_queue < BUFSIZE && serial_data_available()) { + while (length < BUFSIZE && serial_data_available()) { for (uint8_t i = 0; i < NUM_SERIAL; ++i) { int c; if ((c = read_serial(i)) < 0) continue; @@ -659,7 +624,7 @@ inline void get_serial_commands() { gcode_N = strtol(npos + 1, nullptr, 10); - if (gcode_N != gcode_LastN + 1 && !M110) + if (gcode_N != last_N + 1 && !M110) return gcode_line_error(PSTR(MSG_ERR_LINE_NO), i); char *apos = strrchr(command, '*'); @@ -672,7 +637,7 @@ inline void get_serial_commands() { else return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i); - gcode_LastN = gcode_N; + last_N = gcode_N; } #if ENABLED(SDSUPPORT) // Pronterface "M29" and "M29 " has no line number @@ -718,7 +683,7 @@ inline void get_serial_commands() { #endif // Add the command to the queue - _enqueuecommand(serial_line_buffer[i], true + _enqueue(serial_line_buffer[i], true #if NUM_SERIAL > 1 , i #endif @@ -760,7 +725,7 @@ inline void get_serial_commands() { * or until the end of the file is reached. The special character '#' * can also interrupt buffering. */ - inline void get_sdcard_commands() { + inline void GCodeQueue::get_sdcard_commands() { static bool stop_buffering = false, sd_comment_mode = false #if ENABLED(PAREN_COMMENTS) @@ -777,11 +742,11 @@ inline void get_serial_commands() { * due to checksums, however, no checksums are used in SD printing. */ - if (commands_in_queue == 0) stop_buffering = false; + if (length == 0) stop_buffering = false; uint16_t sd_count = 0; bool card_eof = card.eof(); - while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) { + while (length < BUFSIZE && !card_eof && !stop_buffering) { const int16_t n = card.get(); char sd_char = (char)n; card_eof = card.eof(); @@ -804,7 +769,7 @@ inline void get_serial_commands() { #if ENABLED(PRINTER_EVENT_LEDS) printerEventLEDs.onPrintCompleted(); #if HAS_RESUME_CONTINUE - enqueue_and_echo_commands_P(PSTR("M0 S" + inject_P(PSTR("M0 S" #if HAS_LCD_MENU "1800" #else @@ -828,7 +793,7 @@ inline void get_serial_commands() { // Skip empty lines and comments if (!sd_count) { thermalManager.manage_heater(); continue; } - command_queue[cmd_queue_index_w][sd_count] = '\0'; // terminate string + buffer[index_w][sd_count] = '\0'; // terminate string sd_count = 0; // clear sd line buffer _commit_command(false); @@ -849,7 +814,7 @@ inline void get_serial_commands() { #if ENABLED(PAREN_COMMENTS) && ! sd_comment_paren_mode #endif - ) command_queue[cmd_queue_index_w][sd_count++] = sd_char; + ) buffer[index_w][sd_count++] = sd_char; } } } @@ -862,10 +827,7 @@ inline void get_serial_commands() { * - The active serial input (usually USB) * - The SD card file being actively printed */ -void get_available_commands() { - - // if any immediate commands remain, don't get other commands yet - if (drain_injected_commands_P()) return; +void GCodeQueue::get_available_commands() { get_serial_commands(); @@ -877,14 +839,18 @@ void get_available_commands() { /** * Get the next command in the queue, optionally log it to SD, then dispatch it */ -void advance_command_queue() { +void GCodeQueue::advance() { - if (!commands_in_queue) return; + // Process immediate commands + if (process_injected_command()) return; + + // Return if the G-code buffer is empty + if (!length) return; #if ENABLED(SDSUPPORT) if (card.flag.saving) { - char* command = command_queue[cmd_queue_index_r]; + char* command = buffer[index_r]; if (is_M29(command)) { // M29 closes the file card.closefile(); @@ -921,9 +887,9 @@ void advance_command_queue() { #endif // SDSUPPORT // The queue may be reset by a command handler or by code invoked by idle() within a handler - if (commands_in_queue) { - --commands_in_queue; - if (++cmd_queue_index_r >= BUFSIZE) cmd_queue_index_r = 0; + if (length) { + --length; + if (++index_r >= BUFSIZE) index_r = 0; } } diff --git a/Marlin/src/gcode/queue.h b/Marlin/src/gcode/queue.h index 07e164c5f5..49c01f0431 100644 --- a/Marlin/src/gcode/queue.h +++ b/Marlin/src/gcode/queue.h @@ -28,109 +28,125 @@ #include "../inc/MarlinConfig.h" -/** - * GCode line number handling. Hosts may include line numbers when sending - * commands to Marlin, and lines will be checked for sequentiality. - * M110 N sets the current line number. - */ -extern long gcode_LastN, Stopped_gcode_LastN; - -/** - * GCode Command Queue - * A simple ring buffer of BUFSIZE command strings. - * - * Commands are copied into this buffer by the command injectors - * (immediate, serial, sd card) and they are processed sequentially by - * the main loop. The gcode.process_next_command method parses the next - * command and hands off execution to individual handler functions. - */ -extern uint8_t commands_in_queue, // Count of commands in the queue - cmd_queue_index_r; // Ring buffer read position - -extern char command_queue[BUFSIZE][MAX_CMD_SIZE]; - -/* - * The port that the command was received on - */ -#if NUM_SERIAL > 1 - extern int16_t command_queue_port[BUFSIZE]; -#endif - -/** - * Initialization of queue for setup() - */ -void queue_setup(); - -/** - * Clear the Marlin command queue - */ -void clear_command_queue(); - -/** - * Clear the serial line and request a resend of - * the next expected line number. - */ -void flush_and_request_resend(); - -/** - * Send an "ok" message to the host, indicating - * that a command was successfully processed. - * - * If ADVANCED_OK is enabled also include: - * N Line number of the command, if any - * P Planner space remaining - * B Block queue space remaining - */ -void ok_to_send(); - -#if ENABLED(ADVANCED_PAUSE_FEATURE) +class GCodeQueue { +public: /** - * Insert in the front of queue, one or many commands to run from program memory. - * Aborts the current queue, if any. - * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards + * GCode line number handling. Hosts may include line numbers when sending + * commands to Marlin, and lines will be checked for sequentiality. + * M110 N sets the current line number. */ - void enqueue_and_echo_commands_front_P(PGM_P const pgcode); -#endif + static long last_N, stopped_N; -/** - * Enqueue one or many commands to run from program memory. - * Aborts the current queue, if any. - * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards - */ -void enqueue_and_echo_commands_P(PGM_P const pgcode); + static inline void stop() { stopped_N = last_N; } -/** - * Enqueue with Serial Echo - * Return true on success - */ -bool enqueue_and_echo_command(const char* cmd); + /** + * GCode Command Queue + * A simple ring buffer of BUFSIZE command strings. + * + * Commands are copied into this buffer by the command injectors + * (immediate, serial, sd card) and they are processed sequentially by + * the main loop. The gcode.process_next_command method parses the next + * command and hands off execution to individual handler functions. + */ + static uint8_t length, // Count of commands in the queue + index_r; // Ring buffer read position -#define HAS_LCD_QUEUE_NOW (ENABLED(MALYAN_LCD) || (HAS_LCD_MENU && ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE))) -#define HAS_QUEUE_NOW (ENABLED(SDSUPPORT) || HAS_LCD_QUEUE_NOW) -#define HAS_QUEUE_FRONT ENABLED(ADVANCED_PAUSE_FEATURE) + static char buffer[BUFSIZE][MAX_CMD_SIZE]; + + /* + * The port that the command was received on + */ + #if NUM_SERIAL > 1 + static int16_t port[BUFSIZE]; + #endif + + GCodeQueue(); + + /** + * Clear the Marlin command queue + */ + static void clear(); + + /** + * Enqueue one or many commands to run from program memory. + * Aborts the current queue, if any. + * Note: process_injected_command() will process them. + */ + static void inject_P(PGM_P const pgcode); -#if HAS_QUEUE_NOW /** * Enqueue and return only when commands are actually enqueued */ - void enqueue_and_echo_command_now(const char* cmd); - #if HAS_LCD_QUEUE_NOW - /** - * Enqueue from program memory and return only when commands are actually enqueued - */ - void enqueue_and_echo_commands_now_P(PGM_P const cmd); + static void enqueue_one_now(const char* cmd); + + /** + * Enqueue from program memory and return only when commands are actually enqueued + */ + static void enqueue_now_P(PGM_P const cmd); + + /** + * Get the next command in the queue, optionally log it to SD, then dispatch it + */ + static void advance(); + + /** + * Add to the circular command queue the next command from: + * - The command-injection queue (injected_commands_P) + * - The active serial input (usually USB) + * - The SD card file being actively printed + */ + static void get_available_commands(); + + /** + * Send an "ok" message to the host, indicating + * that a command was successfully processed. + * + * If ADVANCED_OK is enabled also include: + * N Line number of the command, if any + * P Planner space remaining + * B Block queue space remaining + */ + static void ok_to_send(); + + /** + * Clear the serial line and request a resend of + * the next expected line number. + */ + static void flush_and_request_resend(); + +private: + + static uint8_t index_w; // Ring buffer write position + + static void get_serial_commands(); + + #if ENABLED(SDSUPPORT) + static void get_sdcard_commands(); #endif -#endif -/** - * Add to the circular command queue the next command from: - * - The command-injection queue (injected_commands_P) - * - The active serial input (usually USB) - * - The SD card file being actively printed - */ -void get_available_commands(); + static void _commit_command(bool say_ok + #if NUM_SERIAL > 1 + , int16_t p=-1 + #endif + ); -/** - * Get the next command in the queue, optionally log it to SD, then dispatch it - */ -void advance_command_queue(); + static bool _enqueue(const char* cmd, bool say_ok=false + #if NUM_SERIAL > 1 + , int16_t p=-1 + #endif + ); + + // Process the next "immediate" command + static bool process_injected_command(); + + /** + * Enqueue with Serial Echo + * Return true on success + */ + static bool enqueue_one(const char* cmd); + + static void gcode_line_error(PGM_P const err, const int8_t port); + +}; + +extern GCodeQueue queue; diff --git a/Marlin/src/gcode/sdcard/M28_M29.cpp b/Marlin/src/gcode/sdcard/M28_M29.cpp index 815a43ae0c..ae31eec165 100644 --- a/Marlin/src/gcode/sdcard/M28_M29.cpp +++ b/Marlin/src/gcode/sdcard/M28_M29.cpp @@ -53,7 +53,7 @@ void GcodeSuite::M28() { SERIAL_ECHOLN(p); card.openFile(p, false); #if NUM_SERIAL > 1 - card.transfer_port_index = command_queue_port[cmd_queue_index_r]; + card.transfer_port_index = queue.port[queue.index_r]; #endif } else diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp index cabed6f322..e89ed2ec64 100644 --- a/Marlin/src/lcd/extensible_ui/ui_api.cpp +++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp @@ -777,10 +777,10 @@ namespace ExtUI { float getFeedrate_percent() { return feedrate_percentage; } void enqueueCommands_P(PGM_P const gcode) { - enqueue_and_echo_commands_P(gcode); + queue.inject_P(gcode); } - bool commandsInQueue() { return (planner.movesplanned() || commands_in_queue); } + bool commandsInQueue() { return (planner.movesplanned() || queue.length); } bool isAxisPositionKnown(const axis_t axis) { return TEST(axis_known_position, axis); diff --git a/Marlin/src/lcd/malyanlcd.cpp b/Marlin/src/lcd/malyanlcd.cpp index a3462d295d..ea474d0b93 100644 --- a/Marlin/src/lcd/malyanlcd.cpp +++ b/Marlin/src/lcd/malyanlcd.cpp @@ -190,8 +190,8 @@ void process_lcd_j_command(const char* command) { case 'E': // enable or disable steppers // switch to relative - enqueue_and_echo_commands_now_P(PSTR("G91")); - enqueue_and_echo_commands_now_P(steppers_enabled ? PSTR("M18") : PSTR("M17")); + queue.enqueue_now_P(PSTR("G91")); + queue.enqueue_now_P(steppers_enabled ? PSTR("M18") : PSTR("M17")); steppers_enabled = !steppers_enabled; break; case 'A': @@ -204,7 +204,7 @@ void process_lcd_j_command(const char* command) { // The M200 class UI seems to send movement in .1mm values. char cmd[20]; sprintf_P(cmd, PSTR("G1 %c%03.1f"), axis, atof(command + 1) / 10.0); - enqueue_and_echo_command_now(cmd); + queue.enqueue_one_now(cmd); } break; default: SERIAL_ECHOLNPAIR("UNKNOWN J COMMAND", command); @@ -247,7 +247,7 @@ void process_lcd_p_command(const char* command) { true #endif ); - clear_command_queue(); + queue.clear(); quickstop_stepper(); print_job_timer.stop(); thermalManager.disable_all_heaters(); @@ -258,7 +258,7 @@ void process_lcd_p_command(const char* command) { break; case 'H': // Home all axis - enqueue_and_echo_commands_now_P(PSTR("G28")); + queue.enqueue_now_P(PSTR("G28")); break; default: { #if ENABLED(SDSUPPORT) @@ -321,7 +321,7 @@ void process_lcd_s_command(const char* command) { case 'H': // Home all axis - enqueue_and_echo_command("G28"); + queue.inject_P(PSTR("G28")); break; case 'L': { diff --git a/Marlin/src/lcd/menu/menu.cpp b/Marlin/src/lcd/menu/menu.cpp index ff2b5fd6e9..85f876d68e 100644 --- a/Marlin/src/lcd/menu/menu.cpp +++ b/Marlin/src/lcd/menu/menu.cpp @@ -99,7 +99,7 @@ void MarlinUI::goto_previous_screen() { /////////// Common Menu Actions //////////// //////////////////////////////////////////// -void MenuItem_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); } +void MenuItem_gcode::action(PGM_P pgcode) { queue.inject_P(pgcode); } //////////////////////////////////////////// /////////// Menu Editing Actions /////////// @@ -410,15 +410,15 @@ void MarlinUI::completion_feedback(const bool good/*=true*/) { #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE) - void lcd_enqueue_command(const char * const cmd) { + void lcd_enqueue_one_now(const char * const cmd) { no_reentry = true; - enqueue_and_echo_command_now(cmd); + queue.enqueue_one_now(cmd); no_reentry = false; } - void lcd_enqueue_commands_P(PGM_P const cmd) { + void lcd_enqueue_one_now_P(PGM_P const cmd) { no_reentry = true; - enqueue_and_echo_commands_now_P(cmd); + queue.enqueue_now_P(cmd); no_reentry = false; } diff --git a/Marlin/src/lcd/menu/menu.h b/Marlin/src/lcd/menu/menu.h index b70f2e3e3a..8135d2a973 100644 --- a/Marlin/src/lcd/menu/menu.h +++ b/Marlin/src/lcd/menu/menu.h @@ -375,8 +375,8 @@ void _lcd_draw_homing(); #endif #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE) - void lcd_enqueue_command(const char * const cmd); - void lcd_enqueue_commands_P(PGM_P const cmd); + void lcd_enqueue_one_now(const char * const cmd); + void lcd_enqueue_one_now_P(PGM_P const cmd); #endif #if ENABLED(LEVEL_BED_CORNERS) diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index e709eb339a..537fb769c8 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -101,7 +101,7 @@ void menu_backlash(); // Set the home offset based on the current_position // void _lcd_set_home_offsets() { - enqueue_and_echo_commands_P(PSTR("M428")); + queue.inject_P(PSTR("M428")); ui.return_to_status(); } #endif @@ -255,7 +255,7 @@ void menu_backlash(); autotune_temp[e] #endif ); - lcd_enqueue_command(cmd); + lcd_enqueue_one_now(cmd); } #endif // PID_AUTOTUNE_MENU diff --git a/Marlin/src/lcd/menu/menu_bed_corners.cpp b/Marlin/src/lcd/menu/menu_bed_corners.cpp index fd90043d0f..43841dd4dc 100644 --- a/Marlin/src/lcd/menu/menu_bed_corners.cpp +++ b/Marlin/src/lcd/menu/menu_bed_corners.cpp @@ -120,7 +120,7 @@ void _lcd_level_bed_corners() { ui.defer_status_screen(); if (!all_axes_known()) { set_all_unhomed(); - enqueue_and_echo_commands_P(PSTR("G28")); + queue.inject_P(PSTR("G28")); } // Disable leveling so the planner won't mess with us diff --git a/Marlin/src/lcd/menu/menu_bed_leveling.cpp b/Marlin/src/lcd/menu/menu_bed_leveling.cpp index e8107aa58a..0d534d86ee 100644 --- a/Marlin/src/lcd/menu/menu_bed_leveling.cpp +++ b/Marlin/src/lcd/menu/menu_bed_leveling.cpp @@ -105,9 +105,9 @@ ui.wait_for_bl_move = true; ui.goto_screen(_lcd_level_bed_done); #if ENABLED(MESH_BED_LEVELING) - enqueue_and_echo_commands_P(PSTR("G29 S2")); + queue.inject_P(PSTR("G29 S2")); #elif ENABLED(PROBE_MANUALLY) - enqueue_and_echo_commands_P(PSTR("G29 V1")); + queue.inject_P(PSTR("G29 V1")); #endif } else @@ -157,9 +157,9 @@ // G29 Records Z, moves, and signals when it pauses ui.wait_for_bl_move = true; #if ENABLED(MESH_BED_LEVELING) - enqueue_and_echo_commands_P(manual_probe_index ? PSTR("G29 S2") : PSTR("G29 S1")); + queue.inject_P(manual_probe_index ? PSTR("G29 S2") : PSTR("G29 S1")); #elif ENABLED(PROBE_MANUALLY) - enqueue_and_echo_commands_P(PSTR("G29 V1")); + queue.inject_P(PSTR("G29 V1")); #endif } @@ -194,7 +194,7 @@ ui.defer_status_screen(); set_all_unhomed(); ui.goto_screen(_lcd_level_bed_homing); - enqueue_and_echo_commands_P(PSTR("G28")); + queue.inject_P(PSTR("G28")); } #endif // PROBE_MANUALLY || MESH_BED_LEVELING diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index 3e666d9f14..0f17a3ca44 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -127,7 +127,7 @@ static void lcd_factory_settings() { auto _recalc_offsets = []{ if (active_extruder && all_axes_known()) { // For the 2nd extruder re-home so the next tool-change gets the new offsets. - enqueue_and_echo_commands_P(PSTR("G28")); // In future, we can babystep the 2nd extruder (if active), making homing unnecessary. + queue.inject_P(PSTR("G28")); // In future, we can babystep the 2nd extruder (if active), making homing unnecessary. active_extruder = 0; } }; diff --git a/Marlin/src/lcd/menu/menu_custom.cpp b/Marlin/src/lcd/menu/menu_custom.cpp index 9d6cd9e8a1..bc9a23adfb 100644 --- a/Marlin/src/lcd/menu/menu_custom.cpp +++ b/Marlin/src/lcd/menu/menu_custom.cpp @@ -38,7 +38,7 @@ #endif void _lcd_user_gcode(PGM_P const cmd) { - enqueue_and_echo_commands_P(cmd); + queue.inject_P(cmd); #if ENABLED(USER_SCRIPT_AUDIBLE_FEEDBACK) ui.completion_feedback(); #endif diff --git a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp index 6931f32726..54915e12f9 100644 --- a/Marlin/src/lcd/menu/menu_delta_calibrate.cpp +++ b/Marlin/src/lcd/menu/menu_delta_calibrate.cpp @@ -73,7 +73,7 @@ void _man_probe_pt(const float &rx, const float &ry) { } void _lcd_delta_calibrate_home() { - enqueue_and_echo_commands_P(PSTR("G28")); + queue.inject_P(PSTR("G28")); ui.goto_screen(_lcd_calibrate_homing); } diff --git a/Marlin/src/lcd/menu/menu_filament.cpp b/Marlin/src/lcd/menu/menu_filament.cpp index 2902d12a00..4d4beb9e1c 100644 --- a/Marlin/src/lcd/menu/menu_filament.cpp +++ b/Marlin/src/lcd/menu/menu_filament.cpp @@ -58,7 +58,7 @@ static void _change_filament_temp(const uint16_t temperature) { char cmd[11]; sprintf_P(cmd, _change_filament_temp_command(), _change_filament_temp_extruder); thermalManager.setTargetHotend(temperature, _change_filament_temp_extruder); - lcd_enqueue_command(cmd); + lcd_enqueue_one_now(cmd); } inline void _lcd_change_filament_temp_1_func() { _change_filament_temp(ui.preheat_hotend_temp[0]); } inline void _lcd_change_filament_temp_2_func() { _change_filament_temp(ui.preheat_hotend_temp[1]); } diff --git a/Marlin/src/lcd/menu/menu_job_recovery.cpp b/Marlin/src/lcd/menu/menu_job_recovery.cpp index f819052977..72fe4cd992 100644 --- a/Marlin/src/lcd/menu/menu_job_recovery.cpp +++ b/Marlin/src/lcd/menu/menu_job_recovery.cpp @@ -35,7 +35,7 @@ static void lcd_power_loss_recovery_resume() { ui.return_to_status(); - enqueue_and_echo_commands_P(PSTR("M1000")); + queue.inject_P(PSTR("M1000")); } static void lcd_power_loss_recovery_cancel() { diff --git a/Marlin/src/lcd/menu/menu_ubl.cpp b/Marlin/src/lcd/menu/menu_ubl.cpp index 2bb9409794..cd8262b611 100644 --- a/Marlin/src/lcd/menu/menu_ubl.cpp +++ b/Marlin/src/lcd/menu/menu_ubl.cpp @@ -107,15 +107,15 @@ void lcd_z_offset_edit_setup(const float &initial) { * UBL Build Custom Mesh Command */ void _lcd_ubl_build_custom_mesh() { - char UBL_LCD_GCODE[20]; - enqueue_and_echo_commands_P(PSTR("G28")); + char ubl_lcd_gcode[20]; + queue.inject_P(PSTR("G28")); #if HAS_HEATED_BED - sprintf_P(UBL_LCD_GCODE, PSTR("M190 S%i"), custom_bed_temp); - lcd_enqueue_command(UBL_LCD_GCODE); + sprintf_P(ubl_lcd_gcode, PSTR("M190 S%i"), custom_bed_temp); + lcd_enqueue_one_now(ubl_lcd_gcode); #endif - sprintf_P(UBL_LCD_GCODE, PSTR("M109 S%i"), custom_hotend_temp); - lcd_enqueue_command(UBL_LCD_GCODE); - enqueue_and_echo_commands_P(PSTR("G29 P1")); + sprintf_P(ubl_lcd_gcode, PSTR("M109 S%i"), custom_hotend_temp); + lcd_enqueue_one_now(ubl_lcd_gcode); + queue.inject_P(PSTR("G29 P1")); } /** @@ -141,11 +141,11 @@ void _lcd_ubl_custom_mesh() { * UBL Adjust Mesh Height Command */ void _lcd_ubl_adjust_height_cmd() { - char UBL_LCD_GCODE[16]; + char ubl_lcd_gcode[16]; const int ind = ubl_height_amount > 0 ? 9 : 10; - strcpy_P(UBL_LCD_GCODE, PSTR("G29 P6 C -")); - sprintf_P(&UBL_LCD_GCODE[ind], PSTR(".%i"), ABS(ubl_height_amount)); - lcd_enqueue_command(UBL_LCD_GCODE); + strcpy_P(ubl_lcd_gcode, PSTR("G29 P6 C -")); + sprintf_P(&ubl_lcd_gcode[ind], PSTR(".%i"), ABS(ubl_height_amount)); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -187,7 +187,7 @@ void _lcd_ubl_edit_mesh() { * UBL Validate Custom Mesh Command */ void _lcd_ubl_validate_custom_mesh() { - char UBL_LCD_GCODE[24]; + char ubl_lcd_gcode[24]; const int temp = #if HAS_HEATED_BED custom_bed_temp @@ -195,9 +195,9 @@ void _lcd_ubl_validate_custom_mesh() { 0 #endif ; - sprintf_P(UBL_LCD_GCODE, PSTR("G26 C B%i H%i P"), temp, custom_hotend_temp); - lcd_enqueue_commands_P(PSTR("G28")); - lcd_enqueue_command(UBL_LCD_GCODE); + sprintf_P(ubl_lcd_gcode, PSTR("G26 C B%i H%i P"), temp, custom_hotend_temp); + lcd_enqueue_one_now_P(PSTR("G28")); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -228,9 +228,9 @@ void _lcd_ubl_validate_mesh() { * UBL Grid Leveling Command */ void _lcd_ubl_grid_level_cmd() { - char UBL_LCD_GCODE[12]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 J%i"), side_points); - lcd_enqueue_command(UBL_LCD_GCODE); + char ubl_lcd_gcode[12]; + sprintf_P(ubl_lcd_gcode, PSTR("G29 J%i"), side_points); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -269,9 +269,9 @@ void _lcd_ubl_mesh_leveling() { * UBL Fill-in Amount Mesh Command */ void _lcd_ubl_fillin_amount_cmd() { - char UBL_LCD_GCODE[18]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 P3 R C.%i"), ubl_fillin_amount); - lcd_enqueue_command(UBL_LCD_GCODE); + char ubl_lcd_gcode[18]; + sprintf_P(ubl_lcd_gcode, PSTR("G29 P3 R C.%i"), ubl_fillin_amount); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -361,22 +361,22 @@ void _lcd_ubl_build_mesh() { * UBL Load Mesh Command */ void _lcd_ubl_load_mesh_cmd() { - char UBL_LCD_GCODE[25]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 L%i"), ubl_storage_slot); - lcd_enqueue_command(UBL_LCD_GCODE); - sprintf_P(UBL_LCD_GCODE, PSTR("M117 " MSG_MESH_LOADED), ubl_storage_slot); - lcd_enqueue_command(UBL_LCD_GCODE); + char ubl_lcd_gcode[25]; + sprintf_P(ubl_lcd_gcode, PSTR("G29 L%i"), ubl_storage_slot); + lcd_enqueue_one_now(ubl_lcd_gcode); + sprintf_P(ubl_lcd_gcode, PSTR("M117 " MSG_MESH_LOADED), ubl_storage_slot); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** * UBL Save Mesh Command */ void _lcd_ubl_save_mesh_cmd() { - char UBL_LCD_GCODE[25]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 S%i"), ubl_storage_slot); - lcd_enqueue_command(UBL_LCD_GCODE); - sprintf_P(UBL_LCD_GCODE, PSTR("M117 " MSG_MESH_SAVED), ubl_storage_slot); - lcd_enqueue_command(UBL_LCD_GCODE); + char ubl_lcd_gcode[25]; + sprintf_P(ubl_lcd_gcode, PSTR("G29 S%i"), ubl_storage_slot); + lcd_enqueue_one_now(ubl_lcd_gcode); + sprintf_P(ubl_lcd_gcode, PSTR("M117 " MSG_MESH_SAVED), ubl_storage_slot); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -420,11 +420,11 @@ void _lcd_ubl_map_homing() { * UBL LCD "radar" map point editing */ void _lcd_ubl_map_lcd_edit_cmd() { - char UBL_LCD_GCODE[50], str[10], str2[10]; + char ubl_lcd_gcode[50], str[10], str2[10]; dtostrf(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]), 0, 2, str); dtostrf(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]), 0, 2, str2); - snprintf_P(UBL_LCD_GCODE, sizeof(UBL_LCD_GCODE), PSTR("G29 P4 X%s Y%s R%i"), str, str2, n_edit_pts); - lcd_enqueue_command(UBL_LCD_GCODE); + snprintf_P(ubl_lcd_gcode, sizeof(ubl_lcd_gcode), PSTR("G29 P4 X%s Y%s R%i"), str, str2, n_edit_pts); + lcd_enqueue_one_now(ubl_lcd_gcode); } /** @@ -529,7 +529,7 @@ void _lcd_ubl_output_map_lcd() { void _lcd_ubl_output_map_lcd_cmd() { if (!all_axes_known()) { set_all_unhomed(); - enqueue_and_echo_commands_P(PSTR("G28")); + queue.inject_P(PSTR("G28")); } ui.goto_screen(_lcd_ubl_map_homing); } diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 7a3ea4538f..6dba900cb7 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -441,7 +441,7 @@ bool MarlinUI::get_blink() { #endif // HAS_LCD_MENU - if (!homed && RRK(EN_KEYPAD_F1)) enqueue_and_echo_commands_P(PSTR("G28")); + if (!homed && RRK(EN_KEYPAD_F1)) queue.inject_P(PSTR("G28")); return true; } @@ -1461,9 +1461,9 @@ void MarlinUI::update() { #if HAS_SPI_LCD lcd_pause_show_message(PAUSE_MESSAGE_PAUSING, PAUSE_MODE_PAUSE_PRINT); // Show message immediately to let user know about pause in progress #endif - enqueue_and_echo_commands_front_P(PSTR("M25 P\nM24")); + queue.inject_P(PSTR("M25 P\nM24")); #elif ENABLED(SDSUPPORT) - enqueue_and_echo_commands_P(PSTR("M25")); + queue.inject_P(PSTR("M25")); #elif defined(ACTION_ON_PAUSE) host_action_pause(); #endif @@ -1475,7 +1475,7 @@ void MarlinUI::update() { wait_for_heatup = wait_for_user = false; #endif #if ENABLED(SDSUPPORT) - if (card.isPaused()) enqueue_and_echo_commands_P(PSTR("M24")); + if (card.isPaused()) queue.inject_P(PSTR("M24")); #endif #ifdef ACTION_ON_RESUME host_action_resume(); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index bebcf113a3..5bcb37f39a 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -735,7 +735,7 @@ class Planner { if (cleaning_buffer_counter) { --cleaning_buffer_counter; #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND) - if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND)); + if (!cleaning_buffer_counter) queue.inject_P(PSTR(SD_FINISHED_RELEASECOMMAND)); #endif } } diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 5a17c0633a..c7a97a2705 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -367,8 +367,8 @@ void CardReader::openAndPrintFile(const char *name) { char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null sprintf_P(cmd, PSTR("M23 %s"), name); for (char *c = &cmd[4]; *c; c++) *c = tolower(*c); - enqueue_and_echo_command_now(cmd); - enqueue_and_echo_commands_P(PSTR("M24")); + queue.enqueue_one_now(cmd); + queue.inject_P(PSTR("M24")); } void CardReader::startFileprint() { @@ -1001,7 +1001,7 @@ void CardReader::printingHasFinished() { #endif print_job_timer.stop(); - if (print_job_timer.duration() > 60) enqueue_and_echo_commands_P(PSTR("M31")); + if (print_job_timer.duration() > 60) queue.inject_P(PSTR("M31")); #if ENABLED(SDCARD_SORT_ALPHA) presort();