|
@@ -276,9 +276,7 @@ const char echomagic[] PROGMEM = "echo:";
|
276
|
276
|
const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
|
277
|
277
|
|
278
|
278
|
static bool relative_mode = false; //Determines Absolute or Relative Coordinates
|
279
|
|
-static char serial_char;
|
280
|
279
|
static int serial_count = 0;
|
281
|
|
-static boolean comment_mode = false;
|
282
|
280
|
static char* seen_pointer; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
|
283
|
281
|
const char* queued_commands_P = NULL; /* pointer to the current line in the active sequence of commands, or NULL when none */
|
284
|
282
|
const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
|
|
@@ -409,9 +407,7 @@ static uint8_t target_extruder;
|
409
|
407
|
static bool filrunoutEnqueued = false;
|
410
|
408
|
#endif
|
411
|
409
|
|
412
|
|
-#if ENABLED(SDSUPPORT)
|
413
|
|
- static bool fromsd[BUFSIZE];
|
414
|
|
-#endif
|
|
410
|
+static bool send_ok[BUFSIZE];
|
415
|
411
|
|
416
|
412
|
#if HAS_SERVOS
|
417
|
413
|
Servo servo[NUM_SERVOS];
|
|
@@ -483,7 +479,7 @@ static bool drain_queued_commands_P() {
|
483
|
479
|
char c;
|
484
|
480
|
while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
|
485
|
481
|
cmd[i] = '\0';
|
486
|
|
- if (enqueuecommand(cmd)) { // buffer was not full (else we will retry later)
|
|
482
|
+ if (enqueue_and_echo_command(cmd)) { // buffer was not full (else we will retry later)
|
487
|
483
|
if (c)
|
488
|
484
|
queued_commands_P += i + 1; // move to next command
|
489
|
485
|
else
|
|
@@ -497,32 +493,45 @@ static bool drain_queued_commands_P() {
|
497
|
493
|
* Aborts the current queue, if any.
|
498
|
494
|
* Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards
|
499
|
495
|
*/
|
500
|
|
-void enqueuecommands_P(const char* pgcode) {
|
|
496
|
+void enqueue_and_echo_commands_P(const char* pgcode) {
|
501
|
497
|
queued_commands_P = pgcode;
|
502
|
498
|
drain_queued_commands_P(); // first command executed asap (when possible)
|
503
|
499
|
}
|
504
|
500
|
|
505
|
501
|
/**
|
506
|
|
- * Copy a command directly into the main command buffer, from RAM.
|
507
|
|
- *
|
508
|
|
- * This is done in a non-safe way and needs a rework someday.
|
509
|
|
- * Returns false if it doesn't add any command
|
|
502
|
+ * Once a new command is in the ring buffer, call this to commit it
|
510
|
503
|
*/
|
511
|
|
-bool enqueuecommand(const char* cmd) {
|
512
|
|
- if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
|
513
|
|
-
|
514
|
|
- // This is dangerous if a mixing of serial and this happens
|
515
|
|
- char* command = command_queue[cmd_queue_index_w];
|
516
|
|
- strcpy(command, cmd);
|
517
|
|
- SERIAL_ECHO_START;
|
518
|
|
- SERIAL_ECHOPGM(MSG_Enqueueing);
|
519
|
|
- SERIAL_ECHO(command);
|
520
|
|
- SERIAL_ECHOLNPGM("\"");
|
|
504
|
+inline void _commit_command(bool say_ok) {
|
|
505
|
+ send_ok[cmd_queue_index_w] = say_ok;
|
521
|
506
|
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
|
522
|
507
|
commands_in_queue++;
|
|
508
|
+}
|
|
509
|
+
|
|
510
|
+/**
|
|
511
|
+ * Copy a command directly into the main command buffer, from RAM.
|
|
512
|
+ * Returns true if successfully adds the command
|
|
513
|
+ */
|
|
514
|
+inline bool _enqueuecommand(const char* cmd, bool say_ok=false) {
|
|
515
|
+ if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
|
|
516
|
+ strcpy(command_queue[cmd_queue_index_w], cmd);
|
|
517
|
+ _commit_command(say_ok);
|
523
|
518
|
return true;
|
524
|
519
|
}
|
525
|
520
|
|
|
521
|
+/**
|
|
522
|
+ * Enqueue with Serial Echo
|
|
523
|
+ */
|
|
524
|
+bool enqueue_and_echo_command(const char* cmd, bool say_ok/*=false*/) {
|
|
525
|
+ if (_enqueuecommand(cmd, say_ok)) {
|
|
526
|
+ SERIAL_ECHO_START;
|
|
527
|
+ SERIAL_ECHOPGM(MSG_Enqueueing);
|
|
528
|
+ SERIAL_ECHO(cmd);
|
|
529
|
+ SERIAL_ECHOLNPGM("\"");
|
|
530
|
+ return true;
|
|
531
|
+ }
|
|
532
|
+ return false;
|
|
533
|
+}
|
|
534
|
+
|
526
|
535
|
void setup_killpin() {
|
527
|
536
|
#if HAS_KILL
|
528
|
537
|
SET_INPUT(KILL_PIN);
|
|
@@ -679,9 +688,8 @@ void setup() {
|
679
|
688
|
SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES);
|
680
|
689
|
SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE);
|
681
|
690
|
|
682
|
|
- #if ENABLED(SDSUPPORT)
|
683
|
|
- for (int8_t i = 0; i < BUFSIZE; i++) fromsd[i] = false;
|
684
|
|
- #endif
|
|
691
|
+ // Send "ok" after commands by default
|
|
692
|
+ for (int8_t i = 0; i < BUFSIZE; i++) send_ok[i] = true;
|
685
|
693
|
|
686
|
694
|
// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
|
687
|
695
|
Config_RetrieveSettings();
|
|
@@ -740,7 +748,7 @@ void setup() {
|
740
|
748
|
* - Call LCD update
|
741
|
749
|
*/
|
742
|
750
|
void loop() {
|
743
|
|
- if (commands_in_queue < BUFSIZE - 1) get_command();
|
|
751
|
+ if (commands_in_queue < BUFSIZE) get_command();
|
744
|
752
|
|
745
|
753
|
#if ENABLED(SDSUPPORT)
|
746
|
754
|
card.checkautostart(false);
|
|
@@ -800,9 +808,12 @@ void gcode_line_error(const char* err, bool doFlush = true) {
|
800
|
808
|
*/
|
801
|
809
|
void get_command() {
|
802
|
810
|
|
|
811
|
+ static char serial_line_buffer[MAX_CMD_SIZE];
|
|
812
|
+ static boolean serial_comment_mode = false;
|
|
813
|
+
|
803
|
814
|
if (drain_queued_commands_P()) return; // priority is given to non-serial commands
|
804
|
815
|
|
805
|
|
- #if ENABLED(NO_TIMEOUTS)
|
|
816
|
+ #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
|
806
|
817
|
static millis_t last_command_time = 0;
|
807
|
818
|
millis_t ms = millis();
|
808
|
819
|
|
|
@@ -817,29 +828,21 @@ void get_command() {
|
817
|
828
|
//
|
818
|
829
|
while (commands_in_queue < BUFSIZE && MYSERIAL.available() > 0) {
|
819
|
830
|
|
820
|
|
- #if ENABLED(NO_TIMEOUTS)
|
821
|
|
- last_command_time = ms;
|
822
|
|
- #endif
|
823
|
|
-
|
824
|
|
- serial_char = MYSERIAL.read();
|
|
831
|
+ char serial_char = MYSERIAL.read();
|
825
|
832
|
|
826
|
833
|
//
|
827
|
|
- // If the character ends the line, or the line is full...
|
|
834
|
+ // If the character ends the line
|
828
|
835
|
//
|
829
|
|
- if (serial_char == '\n' || serial_char == '\r' || serial_count >= MAX_CMD_SIZE - 1) {
|
|
836
|
+ if (serial_char == '\n' || serial_char == '\r') {
|
830
|
837
|
|
831
|
|
- // end of line == end of comment
|
832
|
|
- comment_mode = false;
|
|
838
|
+ serial_comment_mode = false; // end of line == end of comment
|
833
|
839
|
|
834
|
840
|
if (!serial_count) return; // empty lines just exit
|
835
|
841
|
|
836
|
|
- char* command = command_queue[cmd_queue_index_w];
|
837
|
|
- command[serial_count] = 0; // terminate string
|
|
842
|
+ serial_line_buffer[serial_count] = 0; // terminate string
|
|
843
|
+ serial_count = 0; //reset buffer
|
838
|
844
|
|
839
|
|
- // this item in the queue is not from sd
|
840
|
|
- #if ENABLED(SDSUPPORT)
|
841
|
|
- fromsd[cmd_queue_index_w] = false;
|
842
|
|
- #endif
|
|
845
|
+ char* command = serial_line_buffer;
|
843
|
846
|
|
844
|
847
|
while (*command == ' ') command++; // skip any leading spaces
|
845
|
848
|
char* npos = (*command == 'N') ? command : NULL; // Require the N parameter to start the line
|
|
@@ -904,44 +907,56 @@ void get_command() {
|
904
|
907
|
// If command was e-stop process now
|
905
|
908
|
if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
|
906
|
909
|
|
907
|
|
- cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
|
908
|
|
- commands_in_queue += 1;
|
|
910
|
+ #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
|
|
911
|
+ last_command_time = ms;
|
|
912
|
+ #endif
|
909
|
913
|
|
910
|
|
- serial_count = 0; //clear buffer
|
|
914
|
+ // Add the command to the queue
|
|
915
|
+ _enqueuecommand(serial_line_buffer, true);
|
|
916
|
+ }
|
|
917
|
+ else if (serial_count >= MAX_CMD_SIZE - 1) {
|
|
918
|
+ // Keep fetching, but ignore normal characters beyond the max length
|
|
919
|
+ // The command will be injected when EOL is reached
|
911
|
920
|
}
|
912
|
921
|
else if (serial_char == '\\') { // Handle escapes
|
913
|
|
- if (MYSERIAL.available() > 0 && commands_in_queue < BUFSIZE) {
|
|
922
|
+ if (MYSERIAL.available() > 0) {
|
914
|
923
|
// if we have one more character, copy it over
|
915
|
924
|
serial_char = MYSERIAL.read();
|
916
|
|
- command_queue[cmd_queue_index_w][serial_count++] = serial_char;
|
|
925
|
+ serial_line_buffer[serial_count++] = serial_char;
|
917
|
926
|
}
|
918
|
927
|
// otherwise do nothing
|
919
|
928
|
}
|
920
|
|
- else { // its not a newline, carriage return or escape char
|
921
|
|
- if (serial_char == ';') comment_mode = true;
|
922
|
|
- if (!comment_mode) command_queue[cmd_queue_index_w][serial_count++] = serial_char;
|
|
929
|
+ else { // it's not a newline, carriage return or escape char
|
|
930
|
+ if (serial_char == ';') serial_comment_mode = true;
|
|
931
|
+ if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
|
923
|
932
|
}
|
924
|
|
- }
|
|
933
|
+
|
|
934
|
+ } // queue has space, serial has data
|
925
|
935
|
|
926
|
936
|
#if ENABLED(SDSUPPORT)
|
927
|
937
|
|
928
|
|
- if (!card.sdprinting || serial_count) return;
|
|
938
|
+ static bool stop_buffering = false,
|
|
939
|
+ sd_comment_mode = false;
|
|
940
|
+
|
|
941
|
+ if (!card.sdprinting) return;
|
929
|
942
|
|
930
|
943
|
// '#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
|
931
|
|
- // if it occurs, stop_buffering is triggered and the buffer is ran dry.
|
|
944
|
+ // if it occurs, stop_buffering is triggered and the buffer is run dry.
|
932
|
945
|
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
|
933
|
946
|
|
934
|
|
- static bool stop_buffering = false;
|
935
|
947
|
if (commands_in_queue == 0) stop_buffering = false;
|
936
|
948
|
|
937
|
|
- while (!card.eof() && commands_in_queue < BUFSIZE && !stop_buffering) {
|
|
949
|
+ uint16_t sd_count = 0;
|
|
950
|
+ bool card_eof = card.eof();
|
|
951
|
+ while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) {
|
938
|
952
|
int16_t n = card.get();
|
939
|
|
- serial_char = (char)n;
|
940
|
|
- if (serial_char == '\n' || serial_char == '\r' ||
|
941
|
|
- ((serial_char == '#' || serial_char == ':') && !comment_mode) ||
|
942
|
|
- serial_count >= (MAX_CMD_SIZE - 1) || n == -1
|
|
953
|
+ char sd_char = (char)n;
|
|
954
|
+ card_eof = card.eof();
|
|
955
|
+ if (card_eof || n == -1
|
|
956
|
+ || sd_char == '\n' || sd_char == '\r'
|
|
957
|
+ || ((sd_char == '#' || sd_char == ':') && !sd_comment_mode)
|
943
|
958
|
) {
|
944
|
|
- if (card.eof()) {
|
|
959
|
+ if (card_eof) {
|
945
|
960
|
SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
|
946
|
961
|
print_job_stop_ms = millis();
|
947
|
962
|
char time[30];
|
|
@@ -954,24 +969,24 @@ void get_command() {
|
954
|
969
|
card.printingHasFinished();
|
955
|
970
|
card.checkautostart(true);
|
956
|
971
|
}
|
957
|
|
- if (serial_char == '#') stop_buffering = true;
|
|
972
|
+ if (sd_char == '#') stop_buffering = true;
|
958
|
973
|
|
959
|
|
- if (!serial_count) {
|
960
|
|
- comment_mode = false; //for new command
|
961
|
|
- return; //if empty line
|
962
|
|
- }
|
963
|
|
- command_queue[cmd_queue_index_w][serial_count] = 0; //terminate string
|
964
|
|
- // if (!comment_mode) {
|
965
|
|
- fromsd[cmd_queue_index_w] = true;
|
966
|
|
- commands_in_queue += 1;
|
967
|
|
- cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
|
968
|
|
- // }
|
969
|
|
- comment_mode = false; //for new command
|
970
|
|
- serial_count = 0; //clear buffer
|
|
974
|
+ sd_comment_mode = false; //for new command
|
|
975
|
+
|
|
976
|
+ if (!sd_count) continue; //skip empty lines
|
|
977
|
+
|
|
978
|
+ command_queue[cmd_queue_index_w][sd_count] = '\0'; //terminate string
|
|
979
|
+ sd_count = 0; //clear buffer
|
|
980
|
+
|
|
981
|
+ _commit_command(false);
|
|
982
|
+ }
|
|
983
|
+ else if (sd_count >= MAX_CMD_SIZE - 1) {
|
|
984
|
+ // Keep fetching, but ignore normal characters beyond the max length
|
|
985
|
+ // The command will be injected when EOL is reached
|
971
|
986
|
}
|
972
|
987
|
else {
|
973
|
|
- if (serial_char == ';') comment_mode = true;
|
974
|
|
- if (!comment_mode) command_queue[cmd_queue_index_w][serial_count++] = serial_char;
|
|
988
|
+ if (sd_char == ';') sd_comment_mode = true;
|
|
989
|
+ if (!sd_comment_mode) command_queue[cmd_queue_index_w][sd_count++] = sd_char;
|
975
|
990
|
}
|
976
|
991
|
}
|
977
|
992
|
|
|
@@ -2654,7 +2669,7 @@ inline void gcode_G28() {
|
2654
|
2669
|
case MeshStart:
|
2655
|
2670
|
mbl.reset();
|
2656
|
2671
|
probe_point = 0;
|
2657
|
|
- enqueuecommands_P(PSTR("G28\nG29 S2"));
|
|
2672
|
+ enqueue_and_echo_commands_P(PSTR("G28\nG29 S2"));
|
2658
|
2673
|
break;
|
2659
|
2674
|
|
2660
|
2675
|
case MeshNext:
|
|
@@ -2693,7 +2708,7 @@ inline void gcode_G28() {
|
2693
|
2708
|
SERIAL_PROTOCOLLNPGM("Mesh probing done.");
|
2694
|
2709
|
probe_point = -1;
|
2695
|
2710
|
mbl.active = 1;
|
2696
|
|
- enqueuecommands_P(PSTR("G28"));
|
|
2711
|
+ enqueue_and_echo_commands_P(PSTR("G28"));
|
2697
|
2712
|
}
|
2698
|
2713
|
break;
|
2699
|
2714
|
|
|
@@ -3215,7 +3230,7 @@ inline void gcode_G28() {
|
3215
|
3230
|
SERIAL_ECHOLNPGM(Z_PROBE_END_SCRIPT);
|
3216
|
3231
|
}
|
3217
|
3232
|
#endif
|
3218
|
|
- enqueuecommands_P(PSTR(Z_PROBE_END_SCRIPT));
|
|
3233
|
+ enqueue_and_echo_commands_P(PSTR(Z_PROBE_END_SCRIPT));
|
3219
|
3234
|
st_synchronize();
|
3220
|
3235
|
#endif
|
3221
|
3236
|
|
|
@@ -3374,7 +3389,7 @@ inline void gcode_M17() {
|
3374
|
3389
|
}
|
3375
|
3390
|
|
3376
|
3391
|
/**
|
3377
|
|
- * M23: Select a file
|
|
3392
|
+ * M23: Open a file
|
3378
|
3393
|
*/
|
3379
|
3394
|
inline void gcode_M23() {
|
3380
|
3395
|
card.openFile(current_command_args, true);
|
|
@@ -5244,7 +5259,7 @@ inline void gcode_M428() {
|
5244
|
5259
|
SERIAL_ERRORLNPGM(MSG_ERR_M428_TOO_FAR);
|
5245
|
5260
|
LCD_ALERTMESSAGEPGM("Err: Too far!");
|
5246
|
5261
|
#if HAS_BUZZER
|
5247
|
|
- enqueuecommands_P(PSTR("M300 S40 P200"));
|
|
5262
|
+ enqueue_and_echo_commands_P(PSTR("M300 S40 P200"));
|
5248
|
5263
|
#endif
|
5249
|
5264
|
err = true;
|
5250
|
5265
|
break;
|
|
@@ -5258,7 +5273,7 @@ inline void gcode_M428() {
|
5258
|
5273
|
sync_plan_position();
|
5259
|
5274
|
LCD_ALERTMESSAGEPGM("Offset applied.");
|
5260
|
5275
|
#if HAS_BUZZER
|
5261
|
|
- enqueuecommands_P(PSTR("M300 S659 P200\nM300 S698 P200"));
|
|
5276
|
+ enqueue_and_echo_commands_P(PSTR("M300 S659 P200\nM300 S698 P200"));
|
5262
|
5277
|
#endif
|
5263
|
5278
|
}
|
5264
|
5279
|
}
|
|
@@ -6304,9 +6319,7 @@ void FlushSerialRequestResend() {
|
6304
|
6319
|
|
6305
|
6320
|
void ok_to_send() {
|
6306
|
6321
|
refresh_cmd_timeout();
|
6307
|
|
- #if ENABLED(SDSUPPORT)
|
6308
|
|
- if (fromsd[cmd_queue_index_r]) return;
|
6309
|
|
- #endif
|
|
6322
|
+ if (!send_ok[cmd_queue_index_r]) return;
|
6310
|
6323
|
SERIAL_PROTOCOLPGM(MSG_OK);
|
6311
|
6324
|
#if ENABLED(ADVANCED_OK)
|
6312
|
6325
|
char* p = command_queue[cmd_queue_index_r];
|
|
@@ -6997,7 +7010,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
6997
|
7010
|
filrunout();
|
6998
|
7011
|
#endif
|
6999
|
7012
|
|
7000
|
|
- if (commands_in_queue < BUFSIZE - 1) get_command();
|
|
7013
|
+ if (commands_in_queue < BUFSIZE) get_command();
|
7001
|
7014
|
|
7002
|
7015
|
millis_t ms = millis();
|
7003
|
7016
|
|
|
@@ -7054,7 +7067,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
7054
|
7067
|
const int HOME_DEBOUNCE_DELAY = 2500;
|
7055
|
7068
|
if (!READ(HOME_PIN)) {
|
7056
|
7069
|
if (!homeDebounceCount) {
|
7057
|
|
- enqueuecommands_P(PSTR("G28"));
|
|
7070
|
+ enqueue_and_echo_commands_P(PSTR("G28"));
|
7058
|
7071
|
LCD_MESSAGEPGM(MSG_AUTO_HOME);
|
7059
|
7072
|
}
|
7060
|
7073
|
if (homeDebounceCount < HOME_DEBOUNCE_DELAY)
|
|
@@ -7180,7 +7193,7 @@ void kill(const char* lcd_msg) {
|
7180
|
7193
|
void filrunout() {
|
7181
|
7194
|
if (!filrunoutEnqueued) {
|
7182
|
7195
|
filrunoutEnqueued = true;
|
7183
|
|
- enqueuecommands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
|
|
7196
|
+ enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
|
7184
|
7197
|
st_synchronize();
|
7185
|
7198
|
}
|
7186
|
7199
|
}
|