|
@@ -309,6 +309,66 @@ FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", b
|
309
|
309
|
return m29 && !NUMERIC(m29[3]);
|
310
|
310
|
}
|
311
|
311
|
|
|
312
|
+#define PS_NORMAL 0
|
|
313
|
+#define PS_EOL 1
|
|
314
|
+#define PS_QUOTED 2
|
|
315
|
+#define PS_PAREN 3
|
|
316
|
+#define PS_ESC 4
|
|
317
|
+
|
|
318
|
+inline void process_stream_char(const char c, uint8_t &sis, char (&buff)[MAX_CMD_SIZE], int &ind) {
|
|
319
|
+
|
|
320
|
+ if (sis == PS_EOL) return; // EOL comment or overflow
|
|
321
|
+
|
|
322
|
+ #if ENABLED(PAREN_COMMENTS)
|
|
323
|
+ else if (sis == PS_PAREN) { // Inline comment
|
|
324
|
+ if (c == ')') sis = PS_NORMAL;
|
|
325
|
+ return;
|
|
326
|
+ }
|
|
327
|
+ #endif
|
|
328
|
+
|
|
329
|
+ else if (sis >= PS_ESC) // End escaped char
|
|
330
|
+ sis -= PS_ESC;
|
|
331
|
+
|
|
332
|
+ else if (c == '\\') { // Start escaped char
|
|
333
|
+ sis += PS_ESC;
|
|
334
|
+ if (sis == PS_ESC) return; // Keep if quoting
|
|
335
|
+ }
|
|
336
|
+
|
|
337
|
+ #if ENABLED(GCODE_QUOTED_STRINGS)
|
|
338
|
+
|
|
339
|
+ else if (sis == PS_QUOTED) {
|
|
340
|
+ if (c == '"') sis = PS_NORMAL; // End quoted string
|
|
341
|
+ }
|
|
342
|
+ else if (c == '"') // Start quoted string
|
|
343
|
+ sis = PS_QUOTED;
|
|
344
|
+
|
|
345
|
+ #endif
|
|
346
|
+
|
|
347
|
+ else if (c == ';') { // Start end-of-line comment
|
|
348
|
+ sis = PS_EOL;
|
|
349
|
+ return;
|
|
350
|
+ }
|
|
351
|
+
|
|
352
|
+ #if ENABLED(PAREN_COMMENTS)
|
|
353
|
+ else if (c == '(') { // Start inline comment
|
|
354
|
+ sis = PS_PAREN;
|
|
355
|
+ return;
|
|
356
|
+ }
|
|
357
|
+ #endif
|
|
358
|
+
|
|
359
|
+ buff[ind++] = c;
|
|
360
|
+ if (ind >= MAX_CMD_SIZE - 1)
|
|
361
|
+ sis = PS_EOL; // Skip the rest on overflow
|
|
362
|
+}
|
|
363
|
+
|
|
364
|
+inline bool process_line_done(uint8_t &sis, char (&buff)[MAX_CMD_SIZE], int &ind) {
|
|
365
|
+ sis = PS_NORMAL;
|
|
366
|
+ if (!ind) { thermalManager.manage_heater(); return true; }
|
|
367
|
+ buff[ind] = 0;
|
|
368
|
+ ind = 0;
|
|
369
|
+ return false;
|
|
370
|
+}
|
|
371
|
+
|
312
|
372
|
/**
|
313
|
373
|
* Get all commands waiting on the serial port and queue them.
|
314
|
374
|
* Exit when the buffer is full or when no more characters are
|
|
@@ -316,11 +376,8 @@ FORCE_INLINE bool is_M29(const char * const cmd) { // matches "M29" & "M29 ", b
|
316
|
376
|
*/
|
317
|
377
|
void GCodeQueue::get_serial_commands() {
|
318
|
378
|
static char serial_line_buffer[NUM_SERIAL][MAX_CMD_SIZE];
|
319
|
|
- static bool serial_comment_mode[NUM_SERIAL] = { false }
|
320
|
|
- #if ENABLED(PAREN_COMMENTS)
|
321
|
|
- , serial_comment_paren_mode[NUM_SERIAL] = { false }
|
322
|
|
- #endif
|
323
|
|
- ;
|
|
379
|
+
|
|
380
|
+ static uint8_t serial_input_state[NUM_SERIAL] = { 0 };
|
324
|
381
|
|
325
|
382
|
#if ENABLED(BINARY_FILE_TRANSFER)
|
326
|
383
|
if (card.flag.binary_mode) {
|
|
@@ -350,27 +407,15 @@ void GCodeQueue::get_serial_commands() {
|
350
|
407
|
*/
|
351
|
408
|
while (length < BUFSIZE && serial_data_available()) {
|
352
|
409
|
for (uint8_t i = 0; i < NUM_SERIAL; ++i) {
|
353
|
|
- int c;
|
354
|
|
- if ((c = read_serial(i)) < 0) continue;
|
355
|
410
|
|
356
|
|
- char serial_char = c;
|
|
411
|
+ const int c = read_serial(i);
|
|
412
|
+ if (c < 0) continue;
|
357
|
413
|
|
358
|
|
- /**
|
359
|
|
- * If the character ends the line
|
360
|
|
- */
|
361
|
|
- if (serial_char == '\n' || serial_char == '\r') {
|
362
|
|
-
|
363
|
|
- // Start with comment mode off
|
364
|
|
- serial_comment_mode[i] = false;
|
365
|
|
- #if ENABLED(PAREN_COMMENTS)
|
366
|
|
- serial_comment_paren_mode[i] = false;
|
367
|
|
- #endif
|
|
414
|
+ const char serial_char = c;
|
368
|
415
|
|
369
|
|
- // Skip empty lines and comments
|
370
|
|
- if (!serial_count[i]) { thermalManager.manage_heater(); continue; }
|
|
416
|
+ if (serial_char == '\n' || serial_char == '\r') {
|
371
|
417
|
|
372
|
|
- serial_line_buffer[i][serial_count[i]] = 0; // Terminate string
|
373
|
|
- serial_count[i] = 0; // Reset buffer
|
|
418
|
+ process_line_done(serial_input_state[i], serial_line_buffer[i], serial_count[i]);
|
374
|
419
|
|
375
|
420
|
char* command = serial_line_buffer[i];
|
376
|
421
|
|
|
@@ -409,16 +454,17 @@ void GCodeQueue::get_serial_commands() {
|
409
|
454
|
return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i);
|
410
|
455
|
#endif
|
411
|
456
|
|
412
|
|
- // Movement commands alert when stopped
|
|
457
|
+ //
|
|
458
|
+ // Movement commands give an alert when the machine is stopped
|
|
459
|
+ //
|
|
460
|
+
|
413
|
461
|
if (IsStopped()) {
|
414
|
462
|
char* gpos = strchr(command, 'G');
|
415
|
463
|
if (gpos) {
|
416
|
464
|
switch (strtol(gpos + 1, nullptr, 10)) {
|
417
|
|
- case 0:
|
418
|
|
- case 1:
|
|
465
|
+ case 0: case 1:
|
419
|
466
|
#if ENABLED(ARC_SUPPORT)
|
420
|
|
- case 2:
|
421
|
|
- case 3:
|
|
467
|
+ case 2: case 3:
|
422
|
468
|
#endif
|
423
|
469
|
#if ENABLED(BEZIER_CURVE_SUPPORT)
|
424
|
470
|
case 5:
|
|
@@ -453,31 +499,9 @@ void GCodeQueue::get_serial_commands() {
|
453
|
499
|
#endif
|
454
|
500
|
);
|
455
|
501
|
}
|
456
|
|
- else if (serial_count[i] >= MAX_CMD_SIZE - 1) {
|
457
|
|
- // Keep fetching, but ignore normal characters beyond the max length
|
458
|
|
- // The command will be injected when EOL is reached
|
459
|
|
- }
|
460
|
|
- else if (serial_char == '\\') { // Handle escapes
|
461
|
|
- // if we have one more character, copy it over
|
462
|
|
- if ((c = read_serial(i)) >= 0 && !serial_comment_mode[i]
|
463
|
|
- #if ENABLED(PAREN_COMMENTS)
|
464
|
|
- && !serial_comment_paren_mode[i]
|
465
|
|
- #endif
|
466
|
|
- )
|
467
|
|
- serial_line_buffer[i][serial_count[i]++] = (char)c;
|
468
|
|
- }
|
469
|
|
- else { // it's not a newline, carriage return or escape char
|
470
|
|
- if (serial_char == ';') serial_comment_mode[i] = true;
|
471
|
|
- #if ENABLED(PAREN_COMMENTS)
|
472
|
|
- else if (serial_char == '(') serial_comment_paren_mode[i] = true;
|
473
|
|
- else if (serial_char == ')') serial_comment_paren_mode[i] = false;
|
474
|
|
- #endif
|
475
|
|
- else if (!serial_comment_mode[i]
|
476
|
|
- #if ENABLED(PAREN_COMMENTS)
|
477
|
|
- && ! serial_comment_paren_mode[i]
|
478
|
|
- #endif
|
479
|
|
- ) serial_line_buffer[i][serial_count[i]++] = serial_char;
|
480
|
|
- }
|
|
502
|
+ else
|
|
503
|
+ process_stream_char(serial_char, serial_input_state[i], serial_line_buffer[i], serial_count[i]);
|
|
504
|
+
|
481
|
505
|
} // for NUM_SERIAL
|
482
|
506
|
} // queue has space, serial has data
|
483
|
507
|
}
|
|
@@ -490,21 +514,17 @@ void GCodeQueue::get_serial_commands() {
|
490
|
514
|
* can also interrupt buffering.
|
491
|
515
|
*/
|
492
|
516
|
inline void GCodeQueue::get_sdcard_commands() {
|
493
|
|
- static bool sd_comment_mode = false
|
494
|
|
- #if ENABLED(PAREN_COMMENTS)
|
495
|
|
- , sd_comment_paren_mode = false
|
496
|
|
- #endif
|
497
|
|
- ;
|
|
517
|
+ static uint8_t sd_input_state = PS_NORMAL;
|
498
|
518
|
|
499
|
519
|
if (!IS_SD_PRINTING()) return;
|
500
|
520
|
|
501
|
|
- uint16_t sd_count = 0;
|
|
521
|
+ int sd_count = 0;
|
502
|
522
|
bool card_eof = card.eof();
|
503
|
523
|
while (length < BUFSIZE && !card_eof) {
|
504
|
524
|
const int16_t n = card.get();
|
505
|
|
- char sd_char = (char)n;
|
506
|
525
|
card_eof = card.eof();
|
507
|
|
- if (card_eof || n == -1 || sd_char == '\n' || sd_char == '\r') {
|
|
526
|
+ const char sd_char = (char)n;
|
|
527
|
+ if (card_eof || n < 0 || sd_char == '\n' || sd_char == '\r') {
|
508
|
528
|
if (card_eof) {
|
509
|
529
|
|
510
|
530
|
card.printingHasFinished();
|
|
@@ -527,19 +547,10 @@ void GCodeQueue::get_serial_commands() {
|
527
|
547
|
#endif // PRINTER_EVENT_LEDS
|
528
|
548
|
}
|
529
|
549
|
}
|
530
|
|
- else if (n == -1)
|
|
550
|
+ else if (n < 0)
|
531
|
551
|
SERIAL_ERROR_MSG(MSG_SD_ERR_READ);
|
532
|
552
|
|
533
|
|
- sd_comment_mode = false; // for new command
|
534
|
|
- #if ENABLED(PAREN_COMMENTS)
|
535
|
|
- sd_comment_paren_mode = false;
|
536
|
|
- #endif
|
537
|
|
-
|
538
|
|
- // Skip empty lines and comments
|
539
|
|
- if (!sd_count) { thermalManager.manage_heater(); continue; }
|
540
|
|
-
|
541
|
|
- command_buffer[index_w][sd_count] = '\0'; // terminate string
|
542
|
|
- sd_count = 0; // clear sd line buffer
|
|
553
|
+ process_line_done(sd_input_state, command_buffer[index_w], sd_count);
|
543
|
554
|
|
544
|
555
|
_commit_command(false);
|
545
|
556
|
|
|
@@ -547,24 +558,9 @@ void GCodeQueue::get_serial_commands() {
|
547
|
558
|
recovery.cmd_sdpos = card.getIndex(); // Prime for the next _commit_command
|
548
|
559
|
#endif
|
549
|
560
|
}
|
550
|
|
- else if (sd_count >= MAX_CMD_SIZE - 1) {
|
551
|
|
- /**
|
552
|
|
- * Keep fetching, but ignore normal characters beyond the max length
|
553
|
|
- * The command will be injected when EOL is reached
|
554
|
|
- */
|
555
|
|
- }
|
556
|
|
- else {
|
557
|
|
- if (sd_char == ';') sd_comment_mode = true;
|
558
|
|
- #if ENABLED(PAREN_COMMENTS)
|
559
|
|
- else if (sd_char == '(') sd_comment_paren_mode = true;
|
560
|
|
- else if (sd_char == ')') sd_comment_paren_mode = false;
|
561
|
|
- #endif
|
562
|
|
- else if (!sd_comment_mode
|
563
|
|
- #if ENABLED(PAREN_COMMENTS)
|
564
|
|
- && ! sd_comment_paren_mode
|
565
|
|
- #endif
|
566
|
|
- ) command_buffer[index_w][sd_count++] = sd_char;
|
567
|
|
- }
|
|
561
|
+ else
|
|
562
|
+ process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
|
|
563
|
+
|
568
|
564
|
}
|
569
|
565
|
}
|
570
|
566
|
|