Browse Source

G-code queue singleton, front injection (#14236)

Scott Lahteine 6 years ago
parent
commit
4c872a01f2
No account linked to committer's email address

+ 8
- 10
Marlin/src/Marlin.cpp View File

369
     #endif // HOST_ACTION_COMMANDS
369
     #endif // HOST_ACTION_COMMANDS
370
 
370
 
371
     if (run_runout_script)
371
     if (run_runout_script)
372
-      enqueue_and_echo_commands_front_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
372
+      queue.inject_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
373
   }
373
   }
374
 
374
 
375
 #endif // HAS_FILAMENT_SENSOR
375
 #endif // HAS_FILAMENT_SENSOR
425
     runout.run();
425
     runout.run();
426
   #endif
426
   #endif
427
 
427
 
428
-  if (commands_in_queue < BUFSIZE) get_available_commands();
428
+  if (queue.length < BUFSIZE) queue.get_available_commands();
429
 
429
 
430
   const millis_t ms = millis();
430
   const millis_t ms = millis();
431
 
431
 
508
     const int HOME_DEBOUNCE_DELAY = 2500;
508
     const int HOME_DEBOUNCE_DELAY = 2500;
509
     if (!IS_SD_PRINTING() && !READ(HOME_PIN)) {
509
     if (!IS_SD_PRINTING() && !READ(HOME_PIN)) {
510
       if (!homeDebounceCount) {
510
       if (!homeDebounceCount) {
511
-        enqueue_and_echo_commands_P(PSTR("G28"));
511
+        queue.inject_P(PSTR("G28"));
512
         LCD_MESSAGEPGM(MSG_AUTO_HOME);
512
         LCD_MESSAGEPGM(MSG_AUTO_HOME);
513
       }
513
       }
514
       if (homeDebounceCount < HOME_DEBOUNCE_DELAY)
514
       if (homeDebounceCount < HOME_DEBOUNCE_DELAY)
797
   #endif
797
   #endif
798
 
798
 
799
   if (IsRunning()) {
799
   if (IsRunning()) {
800
-    Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart
800
+    queue.stop();
801
     SERIAL_ERROR_MSG(MSG_ERR_STOPPED);
801
     SERIAL_ERROR_MSG(MSG_ERR_STOPPED);
802
     LCD_MESSAGEPGM(MSG_STOPPED);
802
     LCD_MESSAGEPGM(MSG_STOPPED);
803
     safe_delay(350);       // allow enough time for messages to get out before stopping
803
     safe_delay(350);       // allow enough time for messages to get out before stopping
926
   SERIAL_ECHO_START();
926
   SERIAL_ECHO_START();
927
   SERIAL_ECHOLNPAIR(MSG_FREE_MEMORY, freeMemory(), MSG_PLANNER_BUFFER_BYTES, (int)sizeof(block_t) * (BLOCK_BUFFER_SIZE));
927
   SERIAL_ECHOLNPAIR(MSG_FREE_MEMORY, freeMemory(), MSG_PLANNER_BUFFER_BYTES, (int)sizeof(block_t) * (BLOCK_BUFFER_SIZE));
928
 
928
 
929
-  queue_setup();
930
-
931
   // UI must be initialized before EEPROM
929
   // UI must be initialized before EEPROM
932
   // (because EEPROM code calls the UI).
930
   // (because EEPROM code calls the UI).
933
   ui.init();
931
   ui.init();
1135
             true
1133
             true
1136
           #endif
1134
           #endif
1137
         );
1135
         );
1138
-        clear_command_queue();
1136
+        queue.clear();
1139
         quickstop_stepper();
1137
         quickstop_stepper();
1140
         print_job_timer.stop();
1138
         print_job_timer.stop();
1141
         #if DISABLED(SD_ABORT_NO_COOLDOWN)
1139
         #if DISABLED(SD_ABORT_NO_COOLDOWN)
1147
           card.removeJobRecoveryFile();
1145
           card.removeJobRecoveryFile();
1148
         #endif
1146
         #endif
1149
         #ifdef EVENT_GCODE_SD_STOP
1147
         #ifdef EVENT_GCODE_SD_STOP
1150
-          enqueue_and_echo_commands_P(PSTR(EVENT_GCODE_SD_STOP));
1148
+          queue.inject_P(PSTR(EVENT_GCODE_SD_STOP));
1151
         #endif
1149
         #endif
1152
       }
1150
       }
1153
 
1151
 
1154
     #endif // SDSUPPORT
1152
     #endif // SDSUPPORT
1155
 
1153
 
1156
-    if (commands_in_queue < BUFSIZE) get_available_commands();
1157
-    advance_command_queue();
1154
+    if (queue.length < BUFSIZE) queue.get_available_commands();
1155
+    queue.advance();
1158
     endstops.event_handler();
1156
     endstops.event_handler();
1159
     idle();
1157
     idle();
1160
   }
1158
   }

+ 3
- 1
Marlin/src/core/macros.h View File

56
 #define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
56
 #define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
57
 
57
 
58
 // Remove compiler warning on an unused variable
58
 // Remove compiler warning on an unused variable
59
-#define UNUSED(X) (void)X
59
+#ifndef UNUSED
60
+  #define UNUSED(x) ((void)(x))
61
+#endif
60
 
62
 
61
 // Macros to make a string from a macro
63
 // Macros to make a string from a macro
62
 #define STRINGIFY_(M) #M
64
 #define STRINGIFY_(M) #M

+ 1
- 1
Marlin/src/feature/host_actions.cpp View File

142
         break;
142
         break;
143
       case PROMPT_PAUSE_RESUME:
143
       case PROMPT_PAUSE_RESUME:
144
         msg = PSTR("LCD_PAUSE_RESUME");
144
         msg = PSTR("LCD_PAUSE_RESUME");
145
-        enqueue_and_echo_commands_P(PSTR("M24"));
145
+        queue.inject_P(PSTR("M24"));
146
         break;
146
         break;
147
       case PROMPT_INFO:
147
       case PROMPT_INFO:
148
         msg = PSTR("GCODE_INFO");
148
         msg = PSTR("GCODE_INFO");

+ 9
- 9
Marlin/src/feature/power_loss_recovery.cpp View File

98
     if (card.isDetected()) {
98
     if (card.isDetected()) {
99
       load();
99
       load();
100
       if (!valid()) return purge();
100
       if (!valid()) return purge();
101
-      enqueue_and_echo_commands_P(PSTR("M1000 S"));
101
+      queue.inject_P(PSTR("M1000 S"));
102
     }
102
     }
103
   }
103
   }
104
 }
104
 }
209
     info.relative_modes_e = gcode.axis_relative_modes[E_AXIS];
209
     info.relative_modes_e = gcode.axis_relative_modes[E_AXIS];
210
 
210
 
211
     // Commands in the queue
211
     // Commands in the queue
212
-    info.commands_in_queue = save_queue ? commands_in_queue : 0;
213
-    info.cmd_queue_index_r = cmd_queue_index_r;
214
-    COPY(info.command_queue, command_queue);
212
+    info.queue_length = save_queue ? queue.length : 0;
213
+    info.queue_index_r = queue.index_r;
214
+    COPY(info.queue_buffer, queue.buffer);
215
 
215
 
216
     // Elapsed print job time
216
     // Elapsed print job time
217
     info.print_job_elapsed = print_job_timer.duration();
217
     info.print_job_elapsed = print_job_timer.duration();
402
   #endif
402
   #endif
403
 
403
 
404
   // Process commands from the old pending queue
404
   // Process commands from the old pending queue
405
-  uint8_t c = info.commands_in_queue, r = info.cmd_queue_index_r;
405
+  uint8_t c = info.queue_length, r = info.queue_index_r;
406
   for (; c--; r = (r + 1) % BUFSIZE)
406
   for (; c--; r = (r + 1) % BUFSIZE)
407
-    gcode.process_subcommands_now(info.command_queue[r]);
407
+    gcode.process_subcommands_now(info.queue_buffer[r]);
408
 
408
 
409
   // Resume the SD file from the last position
409
   // Resume the SD file from the last position
410
   char *fn = info.sd_filename;
410
   char *fn = info.sd_filename;
484
           DEBUG_EOL();
484
           DEBUG_EOL();
485
           DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
485
           DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
486
         #endif
486
         #endif
487
-        DEBUG_ECHOLNPAIR("cmd_queue_index_r: ", int(info.cmd_queue_index_r));
488
-        DEBUG_ECHOLNPAIR("commands_in_queue: ", int(info.commands_in_queue));
489
-        for (uint8_t i = 0; i < info.commands_in_queue; i++) DEBUG_ECHOLNPAIR("> ", info.command_queue[i]);
487
+        DEBUG_ECHOLNPAIR("queue_index_r: ", int(info.queue_index_r));
488
+        DEBUG_ECHOLNPAIR("queue_length: ", int(info.queue_length));
489
+        for (uint8_t i = 0; i < info.queue_length; i++) DEBUG_ECHOLNPAIR("> ", info.queue_buffer[i]);
490
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
490
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
491
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
491
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
492
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);
492
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);

+ 2
- 2
Marlin/src/feature/power_loss_recovery.h View File

87
   bool relative_mode, relative_modes_e;
87
   bool relative_mode, relative_modes_e;
88
 
88
 
89
   // Command queue
89
   // Command queue
90
-  uint8_t commands_in_queue, cmd_queue_index_r;
91
-  char command_queue[BUFSIZE][MAX_CMD_SIZE];
90
+  uint8_t queue_length, queue_index_r;
91
+  char queue_buffer[BUFSIZE][MAX_CMD_SIZE];
92
 
92
 
93
   // SD Filename and position
93
   // SD Filename and position
94
   char sd_filename[MAXPATHNAMELENGTH];
94
   char sd_filename[MAXPATHNAMELENGTH];

+ 1
- 1
Marlin/src/feature/prusa_MMU2/mmu2.cpp View File

650
 }
650
 }
651
 
651
 
652
 void MMU2::filament_runout() {
652
 void MMU2::filament_runout() {
653
-  enqueue_and_echo_commands_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT));
653
+  queue.inject_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT));
654
   planner.synchronize();
654
   planner.synchronize();
655
 }
655
 }
656
 
656
 

+ 1
- 1
Marlin/src/gcode/bedlevel/abl/G29.cpp View File

966
     #ifdef Z_PROBE_END_SCRIPT
966
     #ifdef Z_PROBE_END_SCRIPT
967
       if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Z Probe End Script: ", Z_PROBE_END_SCRIPT);
967
       if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Z Probe End Script: ", Z_PROBE_END_SCRIPT);
968
       planner.synchronize();
968
       planner.synchronize();
969
-      enqueue_and_echo_commands_P(PSTR(Z_PROBE_END_SCRIPT));
969
+      queue.inject_P(PSTR(Z_PROBE_END_SCRIPT));
970
     #endif
970
     #endif
971
 
971
 
972
     // Auto Bed Leveling is complete! Enable if possible.
972
     // Auto Bed Leveling is complete! Enable if possible.

+ 1
- 1
Marlin/src/gcode/bedlevel/mbl/G29.cpp View File

85
       mbl.reset();
85
       mbl.reset();
86
       mbl_probe_index = 0;
86
       mbl_probe_index = 0;
87
       if (!ui.wait_for_bl_move) {
87
       if (!ui.wait_for_bl_move) {
88
-        enqueue_and_echo_commands_P(PSTR("G28\nG29 S2"));
88
+        queue.inject_P(PSTR("G28\nG29 S2"));
89
         return;
89
         return;
90
       }
90
       }
91
       state = MeshNext;
91
       state = MeshNext;

+ 1
- 1
Marlin/src/gcode/calibrate/M100.cpp View File

153
       SERIAL_CHAR('|');                   // Point out non test bytes
153
       SERIAL_CHAR('|');                   // Point out non test bytes
154
       for (uint8_t i = 0; i < 16; i++) {
154
       for (uint8_t i = 0; i < 16; i++) {
155
         char ccc = (char)start_free_memory[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
155
         char ccc = (char)start_free_memory[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
156
-        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
156
+        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
157
           if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
157
           if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
158
         }
158
         }
159
         else { // If not in the command buffer area, flag bytes that don't match the test byte
159
         else { // If not in the command buffer area, flag bytes that don't match the test byte

+ 1
- 2
Marlin/src/gcode/control/M999.cpp View File

42
 
42
 
43
   if (parser.boolval('S')) return;
43
   if (parser.boolval('S')) return;
44
 
44
 
45
-  // gcode_LastN = Stopped_gcode_LastN;
46
-  flush_and_request_resend();
45
+  queue.flush_and_request_resend();
47
 }
46
 }

+ 6
- 6
Marlin/src/gcode/gcode.cpp View File

187
 /**
187
 /**
188
  * Process the parsed command and dispatch it to its handler
188
  * Process the parsed command and dispatch it to its handler
189
  */
189
  */
190
-void GcodeSuite::process_parsed_command(const bool no_ok) {
190
+void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
191
   KEEPALIVE_STATE(IN_HANDLER);
191
   KEEPALIVE_STATE(IN_HANDLER);
192
 
192
 
193
   // Handle a known G, M, or T
193
   // Handle a known G, M, or T
798
 
798
 
799
   KEEPALIVE_STATE(NOT_BUSY);
799
   KEEPALIVE_STATE(NOT_BUSY);
800
 
800
 
801
-  if (!no_ok) ok_to_send();
801
+  if (!no_ok) queue.ok_to_send();
802
 }
802
 }
803
 
803
 
804
 /**
804
 /**
806
  * This is called from the main loop()
806
  * This is called from the main loop()
807
  */
807
  */
808
 void GcodeSuite::process_next_command() {
808
 void GcodeSuite::process_next_command() {
809
-  char * const current_command = command_queue[cmd_queue_index_r];
809
+  char * const current_command = queue.buffer[queue.index_r];
810
 
810
 
811
-  PORT_REDIRECT(command_queue_port[cmd_queue_index_r]);
811
+  PORT_REDIRECT(queue.port[queue.index_r]);
812
 
812
 
813
   if (DEBUGGING(ECHO)) {
813
   if (DEBUGGING(ECHO)) {
814
     SERIAL_ECHO_START();
814
     SERIAL_ECHO_START();
815
     SERIAL_ECHOLN(current_command);
815
     SERIAL_ECHOLN(current_command);
816
     #if ENABLED(M100_FREE_MEMORY_DUMPER)
816
     #if ENABLED(M100_FREE_MEMORY_DUMPER)
817
-      SERIAL_ECHOPAIR("slot:", cmd_queue_index_r);
818
-      M100_dump_routine(PSTR("   Command Queue:"), (const char*)command_queue, (const char*)(command_queue) + sizeof(command_queue));
817
+      SERIAL_ECHOPAIR("slot:", queue.index_r);
818
+      M100_dump_routine(PSTR("   Command Queue:"), queue.buffer, queue.buffer + sizeof(queue.buffer));
819
     #endif
819
     #endif
820
   }
820
   }
821
 
821
 

+ 1
- 1
Marlin/src/gcode/gcode.h View File

315
   static void process_parsed_command(const bool no_ok=false);
315
   static void process_parsed_command(const bool no_ok=false);
316
   static void process_next_command();
316
   static void process_next_command();
317
 
317
 
318
-  // Execute G-code as a macro, preserving parser state
318
+  // Execute G-code in-place, preserving current G-code parameters
319
   static void process_subcommands_now_P(PGM_P pgcode);
319
   static void process_subcommands_now_P(PGM_P pgcode);
320
   static void process_subcommands_now(char * gcode);
320
   static void process_subcommands_now(char * gcode);
321
 
321
 

+ 2
- 2
Marlin/src/gcode/host/M110.cpp View File

21
  */
21
  */
22
 
22
 
23
 #include "../gcode.h"
23
 #include "../gcode.h"
24
-#include "../queue.h" // for gcode_LastN
24
+#include "../queue.h" // for last_N
25
 
25
 
26
 /**
26
 /**
27
  * M110: Set Current Line Number
27
  * M110: Set Current Line Number
28
  */
28
  */
29
 void GcodeSuite::M110() {
29
 void GcodeSuite::M110() {
30
-  if (parser.seenval('N')) gcode_LastN = parser.value_long();
30
+  if (parser.seenval('N')) queue.last_N = parser.value_long();
31
 }
31
 }

+ 116
- 150
Marlin/src/gcode/queue.cpp View File

25
  */
25
  */
26
 
26
 
27
 #include "queue.h"
27
 #include "queue.h"
28
+GCodeQueue queue;
29
+
28
 #include "gcode.h"
30
 #include "gcode.h"
29
 
31
 
30
 #include "../lcd/ultralcd.h"
32
 #include "../lcd/ultralcd.h"
42
  * sending commands to Marlin, and lines will be checked for sequentiality.
44
  * sending commands to Marlin, and lines will be checked for sequentiality.
43
  * M110 N<int> sets the current line number.
45
  * M110 N<int> sets the current line number.
44
  */
46
  */
45
-long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
47
+long gcode_N, GCodeQueue::last_N, GCodeQueue::stopped_N = 0;
46
 
48
 
47
 /**
49
 /**
48
  * GCode Command Queue
50
  * GCode Command Queue
53
  * the main loop. The gcode.process_next_command method parses the next
55
  * the main loop. The gcode.process_next_command method parses the next
54
  * command and hands off execution to individual handler functions.
56
  * command and hands off execution to individual handler functions.
55
  */
57
  */
56
-uint8_t commands_in_queue = 0, // Count of commands in the queue
57
-        cmd_queue_index_r = 0, // Ring buffer read position
58
-        cmd_queue_index_w = 0; // Ring buffer write position
58
+uint8_t GCodeQueue::length = 0,  // Count of commands in the queue
59
+        GCodeQueue::index_r = 0, // Ring buffer read position
60
+        GCodeQueue::index_w = 0; // Ring buffer write position
59
 
61
 
60
-char command_queue[BUFSIZE][MAX_CMD_SIZE];
62
+char GCodeQueue::buffer[BUFSIZE][MAX_CMD_SIZE];
61
 
63
 
62
 /*
64
 /*
63
  * The port that the command was received on
65
  * The port that the command was received on
64
  */
66
  */
65
 #if NUM_SERIAL > 1
67
 #if NUM_SERIAL > 1
66
-  int16_t command_queue_port[BUFSIZE];
68
+  int16_t GCodeQueue::port[BUFSIZE];
67
 #endif
69
 #endif
68
 
70
 
69
 /**
71
 /**
82
  */
84
  */
83
 static PGM_P injected_commands_P = nullptr;
85
 static PGM_P injected_commands_P = nullptr;
84
 
86
 
85
-void queue_setup() {
87
+GCodeQueue::GCodeQueue() {
86
   // Send "ok" after commands by default
88
   // Send "ok" after commands by default
87
   for (uint8_t i = 0; i < COUNT(send_ok); i++) send_ok[i] = true;
89
   for (uint8_t i = 0; i < COUNT(send_ok); i++) send_ok[i] = true;
88
 }
90
 }
90
 /**
92
 /**
91
  * Clear the Marlin command queue
93
  * Clear the Marlin command queue
92
  */
94
  */
93
-void clear_command_queue() {
94
-  cmd_queue_index_r = cmd_queue_index_w = commands_in_queue = 0;
95
+void GCodeQueue::clear() {
96
+  index_r = index_w = length = 0;
95
 }
97
 }
96
 
98
 
97
 /**
99
 /**
98
  * Once a new command is in the ring buffer, call this to commit it
100
  * Once a new command is in the ring buffer, call this to commit it
99
  */
101
  */
100
-inline void _commit_command(bool say_ok
102
+void GCodeQueue::_commit_command(bool say_ok
101
   #if NUM_SERIAL > 1
103
   #if NUM_SERIAL > 1
102
-    , int16_t port = -1
104
+    , int16_t p/*=-1*/
103
   #endif
105
   #endif
104
 ) {
106
 ) {
105
-  send_ok[cmd_queue_index_w] = say_ok;
107
+  send_ok[index_w] = say_ok;
106
   #if NUM_SERIAL > 1
108
   #if NUM_SERIAL > 1
107
-    command_queue_port[cmd_queue_index_w] = port;
109
+    port[index_w] = p;
108
   #endif
110
   #endif
109
-  if (++cmd_queue_index_w >= BUFSIZE) cmd_queue_index_w = 0;
110
-  commands_in_queue++;
111
+  if (++index_w >= BUFSIZE) index_w = 0;
112
+  length++;
111
 }
113
 }
112
 
114
 
113
 /**
115
 /**
115
  * Return true if the command was successfully added.
117
  * Return true if the command was successfully added.
116
  * Return false for a full buffer, or if the 'command' is a comment.
118
  * Return false for a full buffer, or if the 'command' is a comment.
117
  */
119
  */
118
-inline bool _enqueuecommand(const char* cmd, bool say_ok=false
120
+bool GCodeQueue::_enqueue(const char* cmd, bool say_ok/*=false*/
119
   #if NUM_SERIAL > 1
121
   #if NUM_SERIAL > 1
120
-    , int16_t port = -1
122
+    , int16_t pn/*=-1*/
121
   #endif
123
   #endif
122
 ) {
124
 ) {
123
-  if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
124
-  strcpy(command_queue[cmd_queue_index_w], cmd);
125
+  if (*cmd == ';' || length >= BUFSIZE) return false;
126
+  strcpy(buffer[index_w], cmd);
125
   _commit_command(say_ok
127
   _commit_command(say_ok
126
     #if NUM_SERIAL > 1
128
     #if NUM_SERIAL > 1
127
-      , port
129
+      , pn
128
     #endif
130
     #endif
129
   );
131
   );
130
   return true;
132
   return true;
134
  * Enqueue with Serial Echo
136
  * Enqueue with Serial Echo
135
  * Return true if the command was consumed
137
  * Return true if the command was consumed
136
  */
138
  */
137
-bool enqueue_and_echo_command(const char* cmd) {
139
+bool GCodeQueue::enqueue_one(const char* cmd) {
138
 
140
 
139
-  //SERIAL_ECHOPGM("enqueue_and_echo_command(\"");
141
+  //SERIAL_ECHOPGM("enqueue_one(\"");
140
   //SERIAL_ECHO(cmd);
142
   //SERIAL_ECHO(cmd);
141
   //SERIAL_ECHOPGM("\") \n");
143
   //SERIAL_ECHOPGM("\") \n");
142
 
144
 
143
   if (*cmd == 0 || *cmd == '\n' || *cmd == '\r') return true;
145
   if (*cmd == 0 || *cmd == '\n' || *cmd == '\r') return true;
144
 
146
 
145
-  if (_enqueuecommand(cmd)) {
147
+  if (_enqueue(cmd)) {
146
     SERIAL_ECHO_START();
148
     SERIAL_ECHO_START();
147
     SERIAL_ECHOLNPAIR(MSG_ENQUEUEING, cmd, "\"");
149
     SERIAL_ECHOLNPAIR(MSG_ENQUEUEING, cmd, "\"");
148
     return true;
150
     return true;
150
   return false;
152
   return false;
151
 }
153
 }
152
 
154
 
153
-#if HAS_QUEUE_FRONT
155
+/**
156
+ * Process the next "immediate" command.
157
+ */
158
+bool GCodeQueue::process_injected_command() {
159
+  if (injected_commands_P == nullptr) return false;
154
 
160
 
155
-  bool early_cmd; // = false
161
+  char c;
162
+  size_t i = 0;
163
+  while ((c = pgm_read_byte(&injected_commands_P[i])) && c != '\n') i++;
164
+  if (!i) return false;
156
 
165
 
157
-  /**
158
-   * Insert a high Priority command from RAM into the main command buffer.
159
-   * Return true if the command was consumed
160
-   * Return false for a full buffer, or if the 'command' is a comment.
161
-   */
162
-  inline bool _enqueuecommand_front(const char* cmd) {
163
-    if (*cmd == 0 || *cmd == '\n' || *cmd == '\r') return true;
164
-    if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
165
-    if (cmd_queue_index_r == 0) cmd_queue_index_r = BUFSIZE;
166
-    --cmd_queue_index_r;
167
-    strcpy(command_queue[cmd_queue_index_r], cmd);
168
-    send_ok[cmd_queue_index_r] = false;
169
-    #if NUM_SERIAL > 1
170
-      command_queue_port[cmd_queue_index_r] = -1;
171
-    #endif
172
-    commands_in_queue++;
173
-    return true;
174
-  }
166
+  char cmd[i + 1];
167
+  memcpy_P(cmd, injected_commands_P, i);
168
+  cmd[i] = '\0';
175
 
169
 
176
-  /**
177
-   * Insert in the front of queue, one or many commands to run from program memory.
178
-   * Aborts the current queue, if any.
179
-   * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
180
-   */
181
-  void enqueue_and_echo_commands_front_P(PGM_P const pgcode) {
182
-    early_cmd = true;
183
-    enqueue_and_echo_commands_P(pgcode);
184
-  }
170
+  injected_commands_P = c ? injected_commands_P + i + 1 : nullptr;
185
 
171
 
186
-#endif
172
+  parser.parse(cmd);
173
+  PORT_REDIRECT(SERIAL_PORT);
174
+  gcode.process_parsed_command();
175
+  PORT_RESTORE();
187
 
176
 
188
-/**
189
- * Inject the next "immediate" command, when possible, onto the front of the queue.
190
- * Return true if any immediate commands remain to inject.
191
- * Do not inject a comment or use leading space!.
192
- */
193
-static bool drain_injected_commands_P() {
194
-  while (injected_commands_P != nullptr) {
195
-    size_t i = 0;
196
-    char c, cmd[60];
197
-    strncpy_P(cmd, injected_commands_P, sizeof(cmd) - 1);
198
-    cmd[sizeof(cmd) - 1] = '\0';
199
-    while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
200
-    cmd[i] = '\0';
201
-
202
-    if (
203
-      #if HAS_QUEUE_FRONT
204
-        early_cmd ? _enqueuecommand_front(cmd) :
205
-      #endif
206
-      enqueue_and_echo_command(cmd)
207
-    ) {
208
-      injected_commands_P = c ? injected_commands_P + i + 1 : nullptr; // next command or done
209
-      #if HAS_QUEUE_FRONT
210
-        if (!c) early_cmd = false;
211
-      #endif
212
-    }
213
-    else
214
-      return true; // buffer is full (or command is comment);
215
-  }
216
-  return false;   // return whether any more remain
177
+  return true;
217
 }
178
 }
218
 
179
 
219
 /**
180
 /**
220
  * Enqueue one or many commands to run from program memory.
181
  * Enqueue one or many commands to run from program memory.
182
+ * Do not inject a comment or use leading spaces!
221
  * Aborts the current queue, if any.
183
  * Aborts the current queue, if any.
222
- * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
184
+ * Note: process_injected_command() will be called to drain any commands afterwards
223
  */
185
  */
224
-void enqueue_and_echo_commands_P(PGM_P const pgcode) {
225
-  #if HAS_QUEUE_FRONT
226
-    early_cmd = false;
227
-  #endif
186
+void GCodeQueue::inject_P(PGM_P const pgcode) {
228
   injected_commands_P = pgcode;
187
   injected_commands_P = pgcode;
229
-  (void)drain_injected_commands_P(); // first command executed asap (when possible)
230
 }
188
 }
231
 
189
 
232
-#if HAS_QUEUE_NOW
233
-  /**
234
-   * Enqueue and return only when commands are actually enqueued.
235
-   * Never call this from a G-code handler!
236
-   */
237
-  void enqueue_and_echo_command_now(const char* cmd) {
238
-    while (!enqueue_and_echo_command(cmd)) idle();
190
+/**
191
+ * Enqueue and return only when commands are actually enqueued.
192
+ * Never call this from a G-code handler!
193
+ */
194
+void GCodeQueue::enqueue_one_now(const char* cmd) {
195
+  while (!enqueue_one(cmd)) idle();
196
+}
197
+
198
+/**
199
+ * Enqueue from program memory and return only when commands are actually enqueued
200
+ * Never call this from a G-code handler!
201
+ */
202
+void GCodeQueue::enqueue_now_P(PGM_P const pgcode) {
203
+  size_t i = 0;
204
+  PGM_P p = pgcode;
205
+  for (;;) {
206
+    char c;
207
+    while ((c = p[i]) && c != '\n') i++;
208
+    char cmd[i + 1];
209
+    memcpy_P(cmd, p, i);
210
+    cmd[i] = '\0';
211
+    enqueue_one_now(cmd);
212
+    if (!c) break;
213
+    p += i + 1;
239
   }
214
   }
240
-  #if HAS_LCD_QUEUE_NOW
241
-    /**
242
-     * Enqueue from program memory and return only when commands are actually enqueued
243
-     * Never call this from a G-code handler!
244
-     */
245
-    void enqueue_and_echo_commands_now_P(PGM_P const pgcode) {
246
-      enqueue_and_echo_commands_P(pgcode);
247
-      while (drain_injected_commands_P()) idle();
248
-    }
249
-  #endif
250
-#endif
215
+}
251
 
216
 
252
 /**
217
 /**
253
  * Send an "ok" message to the host, indicating
218
  * Send an "ok" message to the host, indicating
258
  *   P<int>  Planner space remaining
223
  *   P<int>  Planner space remaining
259
  *   B<int>  Block queue space remaining
224
  *   B<int>  Block queue space remaining
260
  */
225
  */
261
-void ok_to_send() {
226
+void GCodeQueue::ok_to_send() {
262
   #if NUM_SERIAL > 1
227
   #if NUM_SERIAL > 1
263
-    const int16_t port = command_queue_port[cmd_queue_index_r];
264
-    if (port < 0) return;
265
-    PORT_REDIRECT(port);
228
+    const int16_t p = port[index_r];
229
+    if (p < 0) return;
230
+    PORT_REDIRECT(p);
266
   #endif
231
   #endif
267
-  if (!send_ok[cmd_queue_index_r]) return;
232
+  if (!send_ok[index_r]) return;
268
   SERIAL_ECHOPGM(MSG_OK);
233
   SERIAL_ECHOPGM(MSG_OK);
269
   #if ENABLED(ADVANCED_OK)
234
   #if ENABLED(ADVANCED_OK)
270
-    char* p = command_queue[cmd_queue_index_r];
235
+    char* p = buffer[index_r];
271
     if (*p == 'N') {
236
     if (*p == 'N') {
272
       SERIAL_ECHO(' ');
237
       SERIAL_ECHO(' ');
273
       SERIAL_ECHO(*p++);
238
       SERIAL_ECHO(*p++);
275
         SERIAL_ECHO(*p++);
240
         SERIAL_ECHO(*p++);
276
     }
241
     }
277
     SERIAL_ECHOPGM(" P"); SERIAL_ECHO(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
242
     SERIAL_ECHOPGM(" P"); SERIAL_ECHO(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
278
-    SERIAL_ECHOPGM(" B"); SERIAL_ECHO(BUFSIZE - commands_in_queue);
243
+    SERIAL_ECHOPGM(" B"); SERIAL_ECHO(BUFSIZE - length);
279
   #endif
244
   #endif
280
   SERIAL_EOL();
245
   SERIAL_EOL();
281
 }
246
 }
284
  * Send a "Resend: nnn" message to the host to
249
  * Send a "Resend: nnn" message to the host to
285
  * indicate that a command needs to be re-sent.
250
  * indicate that a command needs to be re-sent.
286
  */
251
  */
287
-void flush_and_request_resend() {
252
+void GCodeQueue::flush_and_request_resend() {
288
   #if NUM_SERIAL > 1
253
   #if NUM_SERIAL > 1
289
-    const int16_t port = command_queue_port[cmd_queue_index_r];
290
-    if (port < 0) return;
291
-    PORT_REDIRECT(port);
254
+    const int16_t p = port[index_r];
255
+    if (p < 0) return;
256
+    PORT_REDIRECT(p);
292
   #endif
257
   #endif
293
   SERIAL_FLUSH();
258
   SERIAL_FLUSH();
294
   SERIAL_ECHOPGM(MSG_RESEND);
259
   SERIAL_ECHOPGM(MSG_RESEND);
295
-  SERIAL_ECHOLN(gcode_LastN + 1);
260
+  SERIAL_ECHOLN(last_N + 1);
296
   ok_to_send();
261
   ok_to_send();
297
 }
262
 }
298
 
263
 
315
   }
280
   }
316
 }
281
 }
317
 
282
 
318
-void gcode_line_error(PGM_P const err, const int8_t port) {
319
-  PORT_REDIRECT(port);
320
-  SERIAL_ERROR_START();
321
-  serialprintPGM(err);
322
-  SERIAL_ECHOLN(gcode_LastN);
323
-  while (read_serial(port) != -1);           // clear out the RX buffer
324
-  flush_and_request_resend();
325
-  serial_count[port] = 0;
326
-}
327
-
328
 #if ENABLED(BINARY_FILE_TRANSFER)
283
 #if ENABLED(BINARY_FILE_TRANSFER)
329
 
284
 
330
   inline bool serial_data_available(const uint8_t index) {
285
   inline bool serial_data_available(const uint8_t index) {
575
 
530
 
576
 #endif // BINARY_FILE_TRANSFER
531
 #endif // BINARY_FILE_TRANSFER
577
 
532
 
533
+void GCodeQueue::gcode_line_error(PGM_P const err, const int8_t port) {
534
+  PORT_REDIRECT(port);
535
+  SERIAL_ERROR_START();
536
+  serialprintPGM(err);
537
+  SERIAL_ECHOLN(last_N);
538
+  while (read_serial(port) != -1);           // clear out the RX buffer
539
+  flush_and_request_resend();
540
+  serial_count[port] = 0;
541
+}
542
+
578
 FORCE_INLINE bool is_M29(const char * const cmd) {  // matches "M29" & "M29 ", but not "M290", etc
543
 FORCE_INLINE bool is_M29(const char * const cmd) {  // matches "M29" & "M29 ", but not "M290", etc
579
   const char * const m29 = strstr_P(cmd, PSTR("M29"));
544
   const char * const m29 = strstr_P(cmd, PSTR("M29"));
580
   return m29 && !NUMERIC(m29[3]);
545
   return m29 && !NUMERIC(m29[3]);
585
  * Exit when the buffer is full or when no more characters are
550
  * Exit when the buffer is full or when no more characters are
586
  * left on the serial port.
551
  * left on the serial port.
587
  */
552
  */
588
-inline void get_serial_commands() {
553
+void GCodeQueue::get_serial_commands() {
589
   static char serial_line_buffer[NUM_SERIAL][MAX_CMD_SIZE];
554
   static char serial_line_buffer[NUM_SERIAL][MAX_CMD_SIZE];
590
   static bool serial_comment_mode[NUM_SERIAL] = { false }
555
   static bool serial_comment_mode[NUM_SERIAL] = { false }
591
               #if ENABLED(PAREN_COMMENTS)
556
               #if ENABLED(PAREN_COMMENTS)
610
   #if NO_TIMEOUTS > 0
575
   #if NO_TIMEOUTS > 0
611
     static millis_t last_command_time = 0;
576
     static millis_t last_command_time = 0;
612
     const millis_t ms = millis();
577
     const millis_t ms = millis();
613
-    if (commands_in_queue == 0 && !serial_data_available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
578
+    if (length == 0 && !serial_data_available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
614
       SERIAL_ECHOLNPGM(MSG_WAIT);
579
       SERIAL_ECHOLNPGM(MSG_WAIT);
615
       last_command_time = ms;
580
       last_command_time = ms;
616
     }
581
     }
619
   /**
584
   /**
620
    * Loop while serial characters are incoming and the queue is not full
585
    * Loop while serial characters are incoming and the queue is not full
621
    */
586
    */
622
-  while (commands_in_queue < BUFSIZE && serial_data_available()) {
587
+  while (length < BUFSIZE && serial_data_available()) {
623
     for (uint8_t i = 0; i < NUM_SERIAL; ++i) {
588
     for (uint8_t i = 0; i < NUM_SERIAL; ++i) {
624
       int c;
589
       int c;
625
       if ((c = read_serial(i)) < 0) continue;
590
       if ((c = read_serial(i)) < 0) continue;
659
 
624
 
660
           gcode_N = strtol(npos + 1, nullptr, 10);
625
           gcode_N = strtol(npos + 1, nullptr, 10);
661
 
626
 
662
-          if (gcode_N != gcode_LastN + 1 && !M110)
627
+          if (gcode_N != last_N + 1 && !M110)
663
             return gcode_line_error(PSTR(MSG_ERR_LINE_NO), i);
628
             return gcode_line_error(PSTR(MSG_ERR_LINE_NO), i);
664
 
629
 
665
           char *apos = strrchr(command, '*');
630
           char *apos = strrchr(command, '*');
672
           else
637
           else
673
             return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i);
638
             return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i);
674
 
639
 
675
-          gcode_LastN = gcode_N;
640
+          last_N = gcode_N;
676
         }
641
         }
677
         #if ENABLED(SDSUPPORT)
642
         #if ENABLED(SDSUPPORT)
678
           // Pronterface "M29" and "M29 " has no line number
643
           // Pronterface "M29" and "M29 " has no line number
718
         #endif
683
         #endif
719
 
684
 
720
         // Add the command to the queue
685
         // Add the command to the queue
721
-        _enqueuecommand(serial_line_buffer[i], true
686
+        _enqueue(serial_line_buffer[i], true
722
           #if NUM_SERIAL > 1
687
           #if NUM_SERIAL > 1
723
             , i
688
             , i
724
           #endif
689
           #endif
760
    * or until the end of the file is reached. The special character '#'
725
    * or until the end of the file is reached. The special character '#'
761
    * can also interrupt buffering.
726
    * can also interrupt buffering.
762
    */
727
    */
763
-  inline void get_sdcard_commands() {
728
+  inline void GCodeQueue::get_sdcard_commands() {
764
     static bool stop_buffering = false,
729
     static bool stop_buffering = false,
765
                 sd_comment_mode = false
730
                 sd_comment_mode = false
766
                 #if ENABLED(PAREN_COMMENTS)
731
                 #if ENABLED(PAREN_COMMENTS)
777
      * due to checksums, however, no checksums are used in SD printing.
742
      * due to checksums, however, no checksums are used in SD printing.
778
      */
743
      */
779
 
744
 
780
-    if (commands_in_queue == 0) stop_buffering = false;
745
+    if (length == 0) stop_buffering = false;
781
 
746
 
782
     uint16_t sd_count = 0;
747
     uint16_t sd_count = 0;
783
     bool card_eof = card.eof();
748
     bool card_eof = card.eof();
784
-    while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) {
749
+    while (length < BUFSIZE && !card_eof && !stop_buffering) {
785
       const int16_t n = card.get();
750
       const int16_t n = card.get();
786
       char sd_char = (char)n;
751
       char sd_char = (char)n;
787
       card_eof = card.eof();
752
       card_eof = card.eof();
804
             #if ENABLED(PRINTER_EVENT_LEDS)
769
             #if ENABLED(PRINTER_EVENT_LEDS)
805
               printerEventLEDs.onPrintCompleted();
770
               printerEventLEDs.onPrintCompleted();
806
               #if HAS_RESUME_CONTINUE
771
               #if HAS_RESUME_CONTINUE
807
-                enqueue_and_echo_commands_P(PSTR("M0 S"
772
+                inject_P(PSTR("M0 S"
808
                   #if HAS_LCD_MENU
773
                   #if HAS_LCD_MENU
809
                     "1800"
774
                     "1800"
810
                   #else
775
                   #else
828
         // Skip empty lines and comments
793
         // Skip empty lines and comments
829
         if (!sd_count) { thermalManager.manage_heater(); continue; }
794
         if (!sd_count) { thermalManager.manage_heater(); continue; }
830
 
795
 
831
-        command_queue[cmd_queue_index_w][sd_count] = '\0'; // terminate string
796
+        buffer[index_w][sd_count] = '\0'; // terminate string
832
         sd_count = 0; // clear sd line buffer
797
         sd_count = 0; // clear sd line buffer
833
 
798
 
834
         _commit_command(false);
799
         _commit_command(false);
849
           #if ENABLED(PAREN_COMMENTS)
814
           #if ENABLED(PAREN_COMMENTS)
850
             && ! sd_comment_paren_mode
815
             && ! sd_comment_paren_mode
851
           #endif
816
           #endif
852
-        ) command_queue[cmd_queue_index_w][sd_count++] = sd_char;
817
+        ) buffer[index_w][sd_count++] = sd_char;
853
       }
818
       }
854
     }
819
     }
855
   }
820
   }
862
  *  - The active serial input (usually USB)
827
  *  - The active serial input (usually USB)
863
  *  - The SD card file being actively printed
828
  *  - The SD card file being actively printed
864
  */
829
  */
865
-void get_available_commands() {
866
-
867
-  // if any immediate commands remain, don't get other commands yet
868
-  if (drain_injected_commands_P()) return;
830
+void GCodeQueue::get_available_commands() {
869
 
831
 
870
   get_serial_commands();
832
   get_serial_commands();
871
 
833
 
877
 /**
839
 /**
878
  * Get the next command in the queue, optionally log it to SD, then dispatch it
840
  * Get the next command in the queue, optionally log it to SD, then dispatch it
879
  */
841
  */
880
-void advance_command_queue() {
842
+void GCodeQueue::advance() {
843
+
844
+  // Process immediate commands
845
+  if (process_injected_command()) return;
881
 
846
 
882
-  if (!commands_in_queue) return;
847
+  // Return if the G-code buffer is empty
848
+  if (!length) return;
883
 
849
 
884
   #if ENABLED(SDSUPPORT)
850
   #if ENABLED(SDSUPPORT)
885
 
851
 
886
     if (card.flag.saving) {
852
     if (card.flag.saving) {
887
-      char* command = command_queue[cmd_queue_index_r];
853
+      char* command = buffer[index_r];
888
       if (is_M29(command)) {
854
       if (is_M29(command)) {
889
         // M29 closes the file
855
         // M29 closes the file
890
         card.closefile();
856
         card.closefile();
921
   #endif // SDSUPPORT
887
   #endif // SDSUPPORT
922
 
888
 
923
   // The queue may be reset by a command handler or by code invoked by idle() within a handler
889
   // The queue may be reset by a command handler or by code invoked by idle() within a handler
924
-  if (commands_in_queue) {
925
-    --commands_in_queue;
926
-    if (++cmd_queue_index_r >= BUFSIZE) cmd_queue_index_r = 0;
890
+  if (length) {
891
+    --length;
892
+    if (++index_r >= BUFSIZE) index_r = 0;
927
   }
893
   }
928
 
894
 
929
 }
895
 }

+ 103
- 87
Marlin/src/gcode/queue.h View File

28
 
28
 
29
 #include "../inc/MarlinConfig.h"
29
 #include "../inc/MarlinConfig.h"
30
 
30
 
31
-/**
32
- * GCode line number handling. Hosts may include line numbers when sending
33
- * commands to Marlin, and lines will be checked for sequentiality.
34
- * M110 N<int> sets the current line number.
35
- */
36
-extern long gcode_LastN, Stopped_gcode_LastN;
37
-
38
-/**
39
- * GCode Command Queue
40
- * A simple ring buffer of BUFSIZE command strings.
41
- *
42
- * Commands are copied into this buffer by the command injectors
43
- * (immediate, serial, sd card) and they are processed sequentially by
44
- * the main loop. The gcode.process_next_command method parses the next
45
- * command and hands off execution to individual handler functions.
46
- */
47
-extern uint8_t commands_in_queue, // Count of commands in the queue
48
-               cmd_queue_index_r; // Ring buffer read position
31
+class GCodeQueue {
32
+public:
33
+  /**
34
+   * GCode line number handling. Hosts may include line numbers when sending
35
+   * commands to Marlin, and lines will be checked for sequentiality.
36
+   * M110 N<int> sets the current line number.
37
+   */
38
+  static long last_N, stopped_N;
49
 
39
 
50
-extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
40
+  static inline void stop() { stopped_N = last_N; }
51
 
41
 
52
-/*
53
- * The port that the command was received on
54
- */
55
-#if NUM_SERIAL > 1
56
-  extern int16_t command_queue_port[BUFSIZE];
57
-#endif
42
+  /**
43
+   * GCode Command Queue
44
+   * A simple ring buffer of BUFSIZE command strings.
45
+   *
46
+   * Commands are copied into this buffer by the command injectors
47
+   * (immediate, serial, sd card) and they are processed sequentially by
48
+   * the main loop. The gcode.process_next_command method parses the next
49
+   * command and hands off execution to individual handler functions.
50
+   */
51
+  static uint8_t length,  // Count of commands in the queue
52
+                 index_r; // Ring buffer read position
58
 
53
 
59
-/**
60
- * Initialization of queue for setup()
61
- */
62
-void queue_setup();
54
+  static char buffer[BUFSIZE][MAX_CMD_SIZE];
63
 
55
 
64
-/**
65
- * Clear the Marlin command queue
66
- */
67
-void clear_command_queue();
56
+  /*
57
+   * The port that the command was received on
58
+   */
59
+  #if NUM_SERIAL > 1
60
+    static int16_t port[BUFSIZE];
61
+  #endif
68
 
62
 
69
-/**
70
- * Clear the serial line and request a resend of
71
- * the next expected line number.
72
- */
73
-void flush_and_request_resend();
63
+  GCodeQueue();
74
 
64
 
75
-/**
76
- * Send an "ok" message to the host, indicating
77
- * that a command was successfully processed.
78
- *
79
- * If ADVANCED_OK is enabled also include:
80
- *   N<int>  Line number of the command, if any
81
- *   P<int>  Planner space remaining
82
- *   B<int>  Block queue space remaining
83
- */
84
-void ok_to_send();
65
+  /**
66
+   * Clear the Marlin command queue
67
+   */
68
+  static void clear();
85
 
69
 
86
-#if ENABLED(ADVANCED_PAUSE_FEATURE)
87
   /**
70
   /**
88
-   * Insert in the front of queue, one or many commands to run from program memory.
71
+   * Enqueue one or many commands to run from program memory.
89
    * Aborts the current queue, if any.
72
    * Aborts the current queue, if any.
90
-   * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
73
+   * Note: process_injected_command() will process them.
91
    */
74
    */
92
-  void enqueue_and_echo_commands_front_P(PGM_P const pgcode);
93
-#endif
75
+  static void inject_P(PGM_P const pgcode);
94
 
76
 
95
-/**
96
- * Enqueue one or many commands to run from program memory.
97
- * Aborts the current queue, if any.
98
- * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
99
- */
100
-void enqueue_and_echo_commands_P(PGM_P const pgcode);
77
+  /**
78
+   * Enqueue and return only when commands are actually enqueued
79
+   */
80
+  static void enqueue_one_now(const char* cmd);
101
 
81
 
102
-/**
103
- * Enqueue with Serial Echo
104
- * Return true on success
105
- */
106
-bool enqueue_and_echo_command(const char* cmd);
82
+  /**
83
+   * Enqueue from program memory and return only when commands are actually enqueued
84
+   */
85
+  static void enqueue_now_P(PGM_P const cmd);
107
 
86
 
108
-#define HAS_LCD_QUEUE_NOW (ENABLED(MALYAN_LCD) || (HAS_LCD_MENU && ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE)))
109
-#define HAS_QUEUE_NOW (ENABLED(SDSUPPORT) || HAS_LCD_QUEUE_NOW)
110
-#define HAS_QUEUE_FRONT ENABLED(ADVANCED_PAUSE_FEATURE)
87
+  /**
88
+   * Get the next command in the queue, optionally log it to SD, then dispatch it
89
+   */
90
+  static void advance();
111
 
91
 
112
-#if HAS_QUEUE_NOW
113
   /**
92
   /**
114
-   * Enqueue and return only when commands are actually enqueued
93
+   * Add to the circular command queue the next command from:
94
+   *  - The command-injection queue (injected_commands_P)
95
+   *  - The active serial input (usually USB)
96
+   *  - The SD card file being actively printed
115
    */
97
    */
116
-  void enqueue_and_echo_command_now(const char* cmd);
117
-  #if HAS_LCD_QUEUE_NOW
118
-    /**
119
-     * Enqueue from program memory and return only when commands are actually enqueued
120
-     */
121
-    void enqueue_and_echo_commands_now_P(PGM_P const cmd);
98
+  static void get_available_commands();
99
+
100
+  /**
101
+   * Send an "ok" message to the host, indicating
102
+   * that a command was successfully processed.
103
+   *
104
+   * If ADVANCED_OK is enabled also include:
105
+   *   N<int>  Line number of the command, if any
106
+   *   P<int>  Planner space remaining
107
+   *   B<int>  Block queue space remaining
108
+   */
109
+  static void ok_to_send();
110
+
111
+  /**
112
+   * Clear the serial line and request a resend of
113
+   * the next expected line number.
114
+   */
115
+  static void flush_and_request_resend();
116
+
117
+private:
118
+
119
+  static uint8_t index_w;  // Ring buffer write position
120
+
121
+  static void get_serial_commands();
122
+
123
+  #if ENABLED(SDSUPPORT)
124
+    static void get_sdcard_commands();
122
   #endif
125
   #endif
123
-#endif
124
 
126
 
125
-/**
126
- * Add to the circular command queue the next command from:
127
- *  - The command-injection queue (injected_commands_P)
128
- *  - The active serial input (usually USB)
129
- *  - The SD card file being actively printed
130
- */
131
-void get_available_commands();
127
+  static void _commit_command(bool say_ok
128
+    #if NUM_SERIAL > 1
129
+      , int16_t p=-1
130
+    #endif
131
+  );
132
 
132
 
133
-/**
134
- * Get the next command in the queue, optionally log it to SD, then dispatch it
135
- */
136
-void advance_command_queue();
133
+  static bool _enqueue(const char* cmd, bool say_ok=false
134
+    #if NUM_SERIAL > 1
135
+      , int16_t p=-1
136
+    #endif
137
+  );
138
+
139
+  // Process the next "immediate" command
140
+  static bool process_injected_command();
141
+
142
+  /**
143
+   * Enqueue with Serial Echo
144
+   * Return true on success
145
+   */
146
+  static bool enqueue_one(const char* cmd);
147
+
148
+  static void gcode_line_error(PGM_P const err, const int8_t port);
149
+
150
+};
151
+
152
+extern GCodeQueue queue;

+ 1
- 1
Marlin/src/gcode/sdcard/M28_M29.cpp View File

53
       SERIAL_ECHOLN(p);
53
       SERIAL_ECHOLN(p);
54
       card.openFile(p, false);
54
       card.openFile(p, false);
55
       #if NUM_SERIAL > 1
55
       #if NUM_SERIAL > 1
56
-        card.transfer_port_index = command_queue_port[cmd_queue_index_r];
56
+        card.transfer_port_index = queue.port[queue.index_r];
57
       #endif
57
       #endif
58
     }
58
     }
59
     else
59
     else

+ 2
- 2
Marlin/src/lcd/extensible_ui/ui_api.cpp View File

777
   float getFeedrate_percent() { return feedrate_percentage; }
777
   float getFeedrate_percent() { return feedrate_percentage; }
778
 
778
 
779
   void enqueueCommands_P(PGM_P const gcode) {
779
   void enqueueCommands_P(PGM_P const gcode) {
780
-    enqueue_and_echo_commands_P(gcode);
780
+    queue.inject_P(gcode);
781
   }
781
   }
782
 
782
 
783
-  bool commandsInQueue() { return (planner.movesplanned() || commands_in_queue); }
783
+  bool commandsInQueue() { return (planner.movesplanned() || queue.length); }
784
 
784
 
785
   bool isAxisPositionKnown(const axis_t axis) {
785
   bool isAxisPositionKnown(const axis_t axis) {
786
     return TEST(axis_known_position, axis);
786
     return TEST(axis_known_position, axis);

+ 6
- 6
Marlin/src/lcd/malyanlcd.cpp View File

190
     case 'E':
190
     case 'E':
191
       // enable or disable steppers
191
       // enable or disable steppers
192
       // switch to relative
192
       // switch to relative
193
-      enqueue_and_echo_commands_now_P(PSTR("G91"));
194
-      enqueue_and_echo_commands_now_P(steppers_enabled ? PSTR("M18") : PSTR("M17"));
193
+      queue.enqueue_now_P(PSTR("G91"));
194
+      queue.enqueue_now_P(steppers_enabled ? PSTR("M18") : PSTR("M17"));
195
       steppers_enabled = !steppers_enabled;
195
       steppers_enabled = !steppers_enabled;
196
       break;
196
       break;
197
     case 'A':
197
     case 'A':
204
       // The M200 class UI seems to send movement in .1mm values.
204
       // The M200 class UI seems to send movement in .1mm values.
205
       char cmd[20];
205
       char cmd[20];
206
       sprintf_P(cmd, PSTR("G1 %c%03.1f"), axis, atof(command + 1) / 10.0);
206
       sprintf_P(cmd, PSTR("G1 %c%03.1f"), axis, atof(command + 1) / 10.0);
207
-      enqueue_and_echo_command_now(cmd);
207
+      queue.enqueue_one_now(cmd);
208
     } break;
208
     } break;
209
     default:
209
     default:
210
       SERIAL_ECHOLNPAIR("UNKNOWN J COMMAND", command);
210
       SERIAL_ECHOLNPAIR("UNKNOWN J COMMAND", command);
247
             true
247
             true
248
           #endif
248
           #endif
249
         );
249
         );
250
-        clear_command_queue();
250
+        queue.clear();
251
         quickstop_stepper();
251
         quickstop_stepper();
252
         print_job_timer.stop();
252
         print_job_timer.stop();
253
         thermalManager.disable_all_heaters();
253
         thermalManager.disable_all_heaters();
258
       break;
258
       break;
259
     case 'H':
259
     case 'H':
260
       // Home all axis
260
       // Home all axis
261
-      enqueue_and_echo_commands_now_P(PSTR("G28"));
261
+      queue.enqueue_now_P(PSTR("G28"));
262
       break;
262
       break;
263
     default: {
263
     default: {
264
       #if ENABLED(SDSUPPORT)
264
       #if ENABLED(SDSUPPORT)
321
 
321
 
322
     case 'H':
322
     case 'H':
323
       // Home all axis
323
       // Home all axis
324
-      enqueue_and_echo_command("G28");
324
+      queue.inject_P(PSTR("G28"));
325
       break;
325
       break;
326
 
326
 
327
     case 'L': {
327
     case 'L': {

+ 5
- 5
Marlin/src/lcd/menu/menu.cpp View File

99
 /////////// Common Menu Actions ////////////
99
 /////////// Common Menu Actions ////////////
100
 ////////////////////////////////////////////
100
 ////////////////////////////////////////////
101
 
101
 
102
-void MenuItem_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); }
102
+void MenuItem_gcode::action(PGM_P pgcode) { queue.inject_P(pgcode); }
103
 
103
 
104
 ////////////////////////////////////////////
104
 ////////////////////////////////////////////
105
 /////////// Menu Editing Actions ///////////
105
 /////////// Menu Editing Actions ///////////
410
 
410
 
411
 #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE)
411
 #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE)
412
 
412
 
413
-  void lcd_enqueue_command(const char * const cmd) {
413
+  void lcd_enqueue_one_now(const char * const cmd) {
414
     no_reentry = true;
414
     no_reentry = true;
415
-    enqueue_and_echo_command_now(cmd);
415
+    queue.enqueue_one_now(cmd);
416
     no_reentry = false;
416
     no_reentry = false;
417
   }
417
   }
418
 
418
 
419
-  void lcd_enqueue_commands_P(PGM_P const cmd) {
419
+  void lcd_enqueue_one_now_P(PGM_P const cmd) {
420
     no_reentry = true;
420
     no_reentry = true;
421
-    enqueue_and_echo_commands_now_P(cmd);
421
+    queue.enqueue_now_P(cmd);
422
     no_reentry = false;
422
     no_reentry = false;
423
   }
423
   }
424
 
424
 

+ 2
- 2
Marlin/src/lcd/menu/menu.h View File

375
 #endif
375
 #endif
376
 
376
 
377
 #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE)
377
 #if ANY(AUTO_BED_LEVELING_UBL, PID_AUTOTUNE_MENU, ADVANCED_PAUSE_FEATURE)
378
-  void lcd_enqueue_command(const char * const cmd);
379
-  void lcd_enqueue_commands_P(PGM_P const cmd);
378
+  void lcd_enqueue_one_now(const char * const cmd);
379
+  void lcd_enqueue_one_now_P(PGM_P const cmd);
380
 #endif
380
 #endif
381
 
381
 
382
 #if ENABLED(LEVEL_BED_CORNERS)
382
 #if ENABLED(LEVEL_BED_CORNERS)

+ 2
- 2
Marlin/src/lcd/menu/menu_advanced.cpp View File

101
   // Set the home offset based on the current_position
101
   // Set the home offset based on the current_position
102
   //
102
   //
103
   void _lcd_set_home_offsets() {
103
   void _lcd_set_home_offsets() {
104
-    enqueue_and_echo_commands_P(PSTR("M428"));
104
+    queue.inject_P(PSTR("M428"));
105
     ui.return_to_status();
105
     ui.return_to_status();
106
   }
106
   }
107
 #endif
107
 #endif
255
         autotune_temp[e]
255
         autotune_temp[e]
256
       #endif
256
       #endif
257
     );
257
     );
258
-    lcd_enqueue_command(cmd);
258
+    lcd_enqueue_one_now(cmd);
259
   }
259
   }
260
 
260
 
261
 #endif // PID_AUTOTUNE_MENU
261
 #endif // PID_AUTOTUNE_MENU

+ 1
- 1
Marlin/src/lcd/menu/menu_bed_corners.cpp View File

120
   ui.defer_status_screen();
120
   ui.defer_status_screen();
121
   if (!all_axes_known()) {
121
   if (!all_axes_known()) {
122
     set_all_unhomed();
122
     set_all_unhomed();
123
-    enqueue_and_echo_commands_P(PSTR("G28"));
123
+    queue.inject_P(PSTR("G28"));
124
   }
124
   }
125
 
125
 
126
   // Disable leveling so the planner won't mess with us
126
   // Disable leveling so the planner won't mess with us

+ 5
- 5
Marlin/src/lcd/menu/menu_bed_leveling.cpp View File

105
         ui.wait_for_bl_move = true;
105
         ui.wait_for_bl_move = true;
106
         ui.goto_screen(_lcd_level_bed_done);
106
         ui.goto_screen(_lcd_level_bed_done);
107
         #if ENABLED(MESH_BED_LEVELING)
107
         #if ENABLED(MESH_BED_LEVELING)
108
-          enqueue_and_echo_commands_P(PSTR("G29 S2"));
108
+          queue.inject_P(PSTR("G29 S2"));
109
         #elif ENABLED(PROBE_MANUALLY)
109
         #elif ENABLED(PROBE_MANUALLY)
110
-          enqueue_and_echo_commands_P(PSTR("G29 V1"));
110
+          queue.inject_P(PSTR("G29 V1"));
111
         #endif
111
         #endif
112
       }
112
       }
113
       else
113
       else
157
     // G29 Records Z, moves, and signals when it pauses
157
     // G29 Records Z, moves, and signals when it pauses
158
     ui.wait_for_bl_move = true;
158
     ui.wait_for_bl_move = true;
159
     #if ENABLED(MESH_BED_LEVELING)
159
     #if ENABLED(MESH_BED_LEVELING)
160
-      enqueue_and_echo_commands_P(manual_probe_index ? PSTR("G29 S2") : PSTR("G29 S1"));
160
+      queue.inject_P(manual_probe_index ? PSTR("G29 S2") : PSTR("G29 S1"));
161
     #elif ENABLED(PROBE_MANUALLY)
161
     #elif ENABLED(PROBE_MANUALLY)
162
-      enqueue_and_echo_commands_P(PSTR("G29 V1"));
162
+      queue.inject_P(PSTR("G29 V1"));
163
     #endif
163
     #endif
164
   }
164
   }
165
 
165
 
194
     ui.defer_status_screen();
194
     ui.defer_status_screen();
195
     set_all_unhomed();
195
     set_all_unhomed();
196
     ui.goto_screen(_lcd_level_bed_homing);
196
     ui.goto_screen(_lcd_level_bed_homing);
197
-    enqueue_and_echo_commands_P(PSTR("G28"));
197
+    queue.inject_P(PSTR("G28"));
198
   }
198
   }
199
 
199
 
200
 #endif // PROBE_MANUALLY || MESH_BED_LEVELING
200
 #endif // PROBE_MANUALLY || MESH_BED_LEVELING

+ 1
- 1
Marlin/src/lcd/menu/menu_configuration.cpp View File

127
 
127
 
128
     auto _recalc_offsets = []{
128
     auto _recalc_offsets = []{
129
       if (active_extruder && all_axes_known()) {  // For the 2nd extruder re-home so the next tool-change gets the new offsets.
129
       if (active_extruder && all_axes_known()) {  // For the 2nd extruder re-home so the next tool-change gets the new offsets.
130
-        enqueue_and_echo_commands_P(PSTR("G28")); // In future, we can babystep the 2nd extruder (if active), making homing unnecessary.
130
+        queue.inject_P(PSTR("G28")); // In future, we can babystep the 2nd extruder (if active), making homing unnecessary.
131
         active_extruder = 0;
131
         active_extruder = 0;
132
       }
132
       }
133
     };
133
     };

+ 1
- 1
Marlin/src/lcd/menu/menu_custom.cpp View File

38
 #endif
38
 #endif
39
 
39
 
40
 void _lcd_user_gcode(PGM_P const cmd) {
40
 void _lcd_user_gcode(PGM_P const cmd) {
41
-  enqueue_and_echo_commands_P(cmd);
41
+  queue.inject_P(cmd);
42
   #if ENABLED(USER_SCRIPT_AUDIBLE_FEEDBACK)
42
   #if ENABLED(USER_SCRIPT_AUDIBLE_FEEDBACK)
43
     ui.completion_feedback();
43
     ui.completion_feedback();
44
   #endif
44
   #endif

+ 1
- 1
Marlin/src/lcd/menu/menu_delta_calibrate.cpp View File

73
   }
73
   }
74
 
74
 
75
   void _lcd_delta_calibrate_home() {
75
   void _lcd_delta_calibrate_home() {
76
-    enqueue_and_echo_commands_P(PSTR("G28"));
76
+    queue.inject_P(PSTR("G28"));
77
     ui.goto_screen(_lcd_calibrate_homing);
77
     ui.goto_screen(_lcd_calibrate_homing);
78
   }
78
   }
79
 
79
 

+ 1
- 1
Marlin/src/lcd/menu/menu_filament.cpp View File

58
   char cmd[11];
58
   char cmd[11];
59
   sprintf_P(cmd, _change_filament_temp_command(), _change_filament_temp_extruder);
59
   sprintf_P(cmd, _change_filament_temp_command(), _change_filament_temp_extruder);
60
   thermalManager.setTargetHotend(temperature, _change_filament_temp_extruder);
60
   thermalManager.setTargetHotend(temperature, _change_filament_temp_extruder);
61
-  lcd_enqueue_command(cmd);
61
+  lcd_enqueue_one_now(cmd);
62
 }
62
 }
63
 inline void _lcd_change_filament_temp_1_func()    { _change_filament_temp(ui.preheat_hotend_temp[0]); }
63
 inline void _lcd_change_filament_temp_1_func()    { _change_filament_temp(ui.preheat_hotend_temp[0]); }
64
 inline void _lcd_change_filament_temp_2_func()    { _change_filament_temp(ui.preheat_hotend_temp[1]); }
64
 inline void _lcd_change_filament_temp_2_func()    { _change_filament_temp(ui.preheat_hotend_temp[1]); }

+ 1
- 1
Marlin/src/lcd/menu/menu_job_recovery.cpp View File

35
 
35
 
36
 static void lcd_power_loss_recovery_resume() {
36
 static void lcd_power_loss_recovery_resume() {
37
   ui.return_to_status();
37
   ui.return_to_status();
38
-  enqueue_and_echo_commands_P(PSTR("M1000"));
38
+  queue.inject_P(PSTR("M1000"));
39
 }
39
 }
40
 
40
 
41
 static void lcd_power_loss_recovery_cancel() {
41
 static void lcd_power_loss_recovery_cancel() {

+ 35
- 35
Marlin/src/lcd/menu/menu_ubl.cpp View File

107
  * UBL Build Custom Mesh Command
107
  * UBL Build Custom Mesh Command
108
  */
108
  */
109
 void _lcd_ubl_build_custom_mesh() {
109
 void _lcd_ubl_build_custom_mesh() {
110
-  char UBL_LCD_GCODE[20];
111
-  enqueue_and_echo_commands_P(PSTR("G28"));
110
+  char ubl_lcd_gcode[20];
111
+  queue.inject_P(PSTR("G28"));
112
   #if HAS_HEATED_BED
112
   #if HAS_HEATED_BED
113
-    sprintf_P(UBL_LCD_GCODE, PSTR("M190 S%i"), custom_bed_temp);
114
-    lcd_enqueue_command(UBL_LCD_GCODE);
113
+    sprintf_P(ubl_lcd_gcode, PSTR("M190 S%i"), custom_bed_temp);
114
+    lcd_enqueue_one_now(ubl_lcd_gcode);
115
   #endif
115
   #endif
116
-  sprintf_P(UBL_LCD_GCODE, PSTR("M109 S%i"), custom_hotend_temp);
117
-  lcd_enqueue_command(UBL_LCD_GCODE);
118
-  enqueue_and_echo_commands_P(PSTR("G29 P1"));
116
+  sprintf_P(ubl_lcd_gcode, PSTR("M109 S%i"), custom_hotend_temp);
117
+  lcd_enqueue_one_now(ubl_lcd_gcode);
118
+  queue.inject_P(PSTR("G29 P1"));
119
 }
119
 }
120
 
120
 
121
 /**
121
 /**
141
  * UBL Adjust Mesh Height Command
141
  * UBL Adjust Mesh Height Command
142
  */
142
  */
143
 void _lcd_ubl_adjust_height_cmd() {
143
 void _lcd_ubl_adjust_height_cmd() {
144
-  char UBL_LCD_GCODE[16];
144
+  char ubl_lcd_gcode[16];
145
   const int ind = ubl_height_amount > 0 ? 9 : 10;
145
   const int ind = ubl_height_amount > 0 ? 9 : 10;
146
-  strcpy_P(UBL_LCD_GCODE, PSTR("G29 P6 C -"));
147
-  sprintf_P(&UBL_LCD_GCODE[ind], PSTR(".%i"), ABS(ubl_height_amount));
148
-  lcd_enqueue_command(UBL_LCD_GCODE);
146
+  strcpy_P(ubl_lcd_gcode, PSTR("G29 P6 C -"));
147
+  sprintf_P(&ubl_lcd_gcode[ind], PSTR(".%i"), ABS(ubl_height_amount));
148
+  lcd_enqueue_one_now(ubl_lcd_gcode);
149
 }
149
 }
150
 
150
 
151
 /**
151
 /**
187
  * UBL Validate Custom Mesh Command
187
  * UBL Validate Custom Mesh Command
188
  */
188
  */
189
 void _lcd_ubl_validate_custom_mesh() {
189
 void _lcd_ubl_validate_custom_mesh() {
190
-  char UBL_LCD_GCODE[24];
190
+  char ubl_lcd_gcode[24];
191
   const int temp =
191
   const int temp =
192
     #if HAS_HEATED_BED
192
     #if HAS_HEATED_BED
193
       custom_bed_temp
193
       custom_bed_temp
195
       0
195
       0
196
     #endif
196
     #endif
197
   ;
197
   ;
198
-  sprintf_P(UBL_LCD_GCODE, PSTR("G26 C B%i H%i P"), temp, custom_hotend_temp);
199
-  lcd_enqueue_commands_P(PSTR("G28"));
200
-  lcd_enqueue_command(UBL_LCD_GCODE);
198
+  sprintf_P(ubl_lcd_gcode, PSTR("G26 C B%i H%i P"), temp, custom_hotend_temp);
199
+  lcd_enqueue_one_now_P(PSTR("G28"));
200
+  lcd_enqueue_one_now(ubl_lcd_gcode);
201
 }
201
 }
202
 
202
 
203
 /**
203
 /**
228
  * UBL Grid Leveling Command
228
  * UBL Grid Leveling Command
229
  */
229
  */
230
 void _lcd_ubl_grid_level_cmd() {
230
 void _lcd_ubl_grid_level_cmd() {
231
-  char UBL_LCD_GCODE[12];
232
-  sprintf_P(UBL_LCD_GCODE, PSTR("G29 J%i"), side_points);
233
-  lcd_enqueue_command(UBL_LCD_GCODE);
231
+  char ubl_lcd_gcode[12];
232
+  sprintf_P(ubl_lcd_gcode, PSTR("G29 J%i"), side_points);
233
+  lcd_enqueue_one_now(ubl_lcd_gcode);
234
 }
234
 }
235
 
235
 
236
 /**
236
 /**
269
  * UBL Fill-in Amount Mesh Command
269
  * UBL Fill-in Amount Mesh Command
270
  */
270
  */
271
 void _lcd_ubl_fillin_amount_cmd() {
271
 void _lcd_ubl_fillin_amount_cmd() {
272
-  char UBL_LCD_GCODE[18];
273
-  sprintf_P(UBL_LCD_GCODE, PSTR("G29 P3 R C.%i"), ubl_fillin_amount);
274
-  lcd_enqueue_command(UBL_LCD_GCODE);
272
+  char ubl_lcd_gcode[18];
273
+  sprintf_P(ubl_lcd_gcode, PSTR("G29 P3 R C.%i"), ubl_fillin_amount);
274
+  lcd_enqueue_one_now(ubl_lcd_gcode);
275
 }
275
 }
276
 
276
 
277
 /**
277
 /**
361
  * UBL Load Mesh Command
361
  * UBL Load Mesh Command
362
  */
362
  */
363
 void _lcd_ubl_load_mesh_cmd() {
363
 void _lcd_ubl_load_mesh_cmd() {
364
-  char UBL_LCD_GCODE[25];
365
-  sprintf_P(UBL_LCD_GCODE, PSTR("G29 L%i"), ubl_storage_slot);
366
-  lcd_enqueue_command(UBL_LCD_GCODE);
367
-  sprintf_P(UBL_LCD_GCODE, PSTR("M117 " MSG_MESH_LOADED), ubl_storage_slot);
368
-  lcd_enqueue_command(UBL_LCD_GCODE);
364
+  char ubl_lcd_gcode[25];
365
+  sprintf_P(ubl_lcd_gcode, PSTR("G29 L%i"), ubl_storage_slot);
366
+  lcd_enqueue_one_now(ubl_lcd_gcode);
367
+  sprintf_P(ubl_lcd_gcode, PSTR("M117 " MSG_MESH_LOADED), ubl_storage_slot);
368
+  lcd_enqueue_one_now(ubl_lcd_gcode);
369
 }
369
 }
370
 
370
 
371
 /**
371
 /**
372
  * UBL Save Mesh Command
372
  * UBL Save Mesh Command
373
  */
373
  */
374
 void _lcd_ubl_save_mesh_cmd() {
374
 void _lcd_ubl_save_mesh_cmd() {
375
-  char UBL_LCD_GCODE[25];
376
-  sprintf_P(UBL_LCD_GCODE, PSTR("G29 S%i"), ubl_storage_slot);
377
-  lcd_enqueue_command(UBL_LCD_GCODE);
378
-  sprintf_P(UBL_LCD_GCODE, PSTR("M117 " MSG_MESH_SAVED), ubl_storage_slot);
379
-  lcd_enqueue_command(UBL_LCD_GCODE);
375
+  char ubl_lcd_gcode[25];
376
+  sprintf_P(ubl_lcd_gcode, PSTR("G29 S%i"), ubl_storage_slot);
377
+  lcd_enqueue_one_now(ubl_lcd_gcode);
378
+  sprintf_P(ubl_lcd_gcode, PSTR("M117 " MSG_MESH_SAVED), ubl_storage_slot);
379
+  lcd_enqueue_one_now(ubl_lcd_gcode);
380
 }
380
 }
381
 
381
 
382
 /**
382
 /**
420
  * UBL LCD "radar" map point editing
420
  * UBL LCD "radar" map point editing
421
  */
421
  */
422
 void _lcd_ubl_map_lcd_edit_cmd() {
422
 void _lcd_ubl_map_lcd_edit_cmd() {
423
-  char UBL_LCD_GCODE[50], str[10], str2[10];
423
+  char ubl_lcd_gcode[50], str[10], str2[10];
424
   dtostrf(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]), 0, 2, str);
424
   dtostrf(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]), 0, 2, str);
425
   dtostrf(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]), 0, 2, str2);
425
   dtostrf(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]), 0, 2, str2);
426
-  snprintf_P(UBL_LCD_GCODE, sizeof(UBL_LCD_GCODE), PSTR("G29 P4 X%s Y%s R%i"), str, str2, n_edit_pts);
427
-  lcd_enqueue_command(UBL_LCD_GCODE);
426
+  snprintf_P(ubl_lcd_gcode, sizeof(ubl_lcd_gcode), PSTR("G29 P4 X%s Y%s R%i"), str, str2, n_edit_pts);
427
+  lcd_enqueue_one_now(ubl_lcd_gcode);
428
 }
428
 }
429
 
429
 
430
 /**
430
 /**
529
 void _lcd_ubl_output_map_lcd_cmd() {
529
 void _lcd_ubl_output_map_lcd_cmd() {
530
   if (!all_axes_known()) {
530
   if (!all_axes_known()) {
531
     set_all_unhomed();
531
     set_all_unhomed();
532
-    enqueue_and_echo_commands_P(PSTR("G28"));
532
+    queue.inject_P(PSTR("G28"));
533
   }
533
   }
534
   ui.goto_screen(_lcd_ubl_map_homing);
534
   ui.goto_screen(_lcd_ubl_map_homing);
535
 }
535
 }

+ 4
- 4
Marlin/src/lcd/ultralcd.cpp View File

441
 
441
 
442
         #endif // HAS_LCD_MENU
442
         #endif // HAS_LCD_MENU
443
 
443
 
444
-        if (!homed && RRK(EN_KEYPAD_F1)) enqueue_and_echo_commands_P(PSTR("G28"));
444
+        if (!homed && RRK(EN_KEYPAD_F1)) queue.inject_P(PSTR("G28"));
445
         return true;
445
         return true;
446
       }
446
       }
447
 
447
 
1461
       #if HAS_SPI_LCD
1461
       #if HAS_SPI_LCD
1462
         lcd_pause_show_message(PAUSE_MESSAGE_PAUSING, PAUSE_MODE_PAUSE_PRINT);  // Show message immediately to let user know about pause in progress
1462
         lcd_pause_show_message(PAUSE_MESSAGE_PAUSING, PAUSE_MODE_PAUSE_PRINT);  // Show message immediately to let user know about pause in progress
1463
       #endif
1463
       #endif
1464
-      enqueue_and_echo_commands_front_P(PSTR("M25 P\nM24"));
1464
+      queue.inject_P(PSTR("M25 P\nM24"));
1465
     #elif ENABLED(SDSUPPORT)
1465
     #elif ENABLED(SDSUPPORT)
1466
-      enqueue_and_echo_commands_P(PSTR("M25"));
1466
+      queue.inject_P(PSTR("M25"));
1467
     #elif defined(ACTION_ON_PAUSE)
1467
     #elif defined(ACTION_ON_PAUSE)
1468
       host_action_pause();
1468
       host_action_pause();
1469
     #endif
1469
     #endif
1475
       wait_for_heatup = wait_for_user = false;
1475
       wait_for_heatup = wait_for_user = false;
1476
     #endif
1476
     #endif
1477
     #if ENABLED(SDSUPPORT)
1477
     #if ENABLED(SDSUPPORT)
1478
-      if (card.isPaused()) enqueue_and_echo_commands_P(PSTR("M24"));
1478
+      if (card.isPaused()) queue.inject_P(PSTR("M24"));
1479
     #endif
1479
     #endif
1480
     #ifdef ACTION_ON_RESUME
1480
     #ifdef ACTION_ON_RESUME
1481
       host_action_resume();
1481
       host_action_resume();

+ 1
- 1
Marlin/src/module/planner.h View File

735
       if (cleaning_buffer_counter) {
735
       if (cleaning_buffer_counter) {
736
         --cleaning_buffer_counter;
736
         --cleaning_buffer_counter;
737
         #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
737
         #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
738
-          if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
738
+          if (!cleaning_buffer_counter) queue.inject_P(PSTR(SD_FINISHED_RELEASECOMMAND));
739
         #endif
739
         #endif
740
       }
740
       }
741
     }
741
     }

+ 3
- 3
Marlin/src/sd/cardreader.cpp View File

367
   char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null
367
   char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null
368
   sprintf_P(cmd, PSTR("M23 %s"), name);
368
   sprintf_P(cmd, PSTR("M23 %s"), name);
369
   for (char *c = &cmd[4]; *c; c++) *c = tolower(*c);
369
   for (char *c = &cmd[4]; *c; c++) *c = tolower(*c);
370
-  enqueue_and_echo_command_now(cmd);
371
-  enqueue_and_echo_commands_P(PSTR("M24"));
370
+  queue.enqueue_one_now(cmd);
371
+  queue.inject_P(PSTR("M24"));
372
 }
372
 }
373
 
373
 
374
 void CardReader::startFileprint() {
374
 void CardReader::startFileprint() {
1001
     #endif
1001
     #endif
1002
 
1002
 
1003
     print_job_timer.stop();
1003
     print_job_timer.stop();
1004
-    if (print_job_timer.duration() > 60) enqueue_and_echo_commands_P(PSTR("M31"));
1004
+    if (print_job_timer.duration() > 60) queue.inject_P(PSTR("M31"));
1005
 
1005
 
1006
     #if ENABLED(SDCARD_SORT_ALPHA)
1006
     #if ENABLED(SDCARD_SORT_ALPHA)
1007
       presort();
1007
       presort();

Loading…
Cancel
Save