|
@@ -141,7 +141,7 @@
|
141
|
141
|
* M112 - Emergency stop
|
142
|
142
|
* M114 - Output current position to serial port
|
143
|
143
|
* M115 - Capabilities string
|
144
|
|
- * M117 - display message
|
|
144
|
+ * M117 - Display a message on the controller screen
|
145
|
145
|
* M119 - Output Endstop status to serial port
|
146
|
146
|
* M120 - Enable endstop detection
|
147
|
147
|
* M121 - Disable endstop detection
|
|
@@ -236,6 +236,7 @@ bool axis_known_position[3] = { false };
|
236
|
236
|
|
237
|
237
|
static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
|
238
|
238
|
|
|
239
|
+static char *current_command, *current_command_args;
|
239
|
240
|
static int cmd_queue_index_r = 0;
|
240
|
241
|
static int cmd_queue_index_w = 0;
|
241
|
242
|
static int commands_in_queue = 0;
|
|
@@ -265,7 +266,7 @@ static bool relative_mode = false; //Determines Absolute or Relative Coordinate
|
265
|
266
|
static char serial_char;
|
266
|
267
|
static int serial_count = 0;
|
267
|
268
|
static boolean comment_mode = false;
|
268
|
|
-static char *strchr_pointer; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
|
|
269
|
+static char *seen_pointer; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
|
269
|
270
|
const char* queued_commands_P= NULL; /* pointer to the current line in the active sequence of commands, or NULL when none */
|
270
|
271
|
const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
|
271
|
272
|
// Inactivity shutdown
|
|
@@ -785,21 +786,20 @@ void get_command() {
|
785
|
786
|
fromsd[cmd_queue_index_w] = false;
|
786
|
787
|
#endif
|
787
|
788
|
|
788
|
|
- if (strchr(command, 'N') != NULL) {
|
789
|
|
- strchr_pointer = strchr(command, 'N');
|
790
|
|
- gcode_N = (strtol(strchr_pointer + 1, NULL, 10));
|
|
789
|
+ char *npos = strchr(command, 'N');
|
|
790
|
+ char *apos = strchr(command, '*');
|
|
791
|
+ if (npos) {
|
|
792
|
+ gcode_N = strtol(npos + 1, NULL, 10);
|
791
|
793
|
if (gcode_N != gcode_LastN + 1 && strstr_P(command, PSTR("M110")) == NULL) {
|
792
|
794
|
gcode_line_error(PSTR(MSG_ERR_LINE_NO));
|
793
|
795
|
return;
|
794
|
796
|
}
|
795
|
797
|
|
796
|
|
- if (strchr(command, '*') != NULL) {
|
797
|
|
- byte checksum = 0;
|
798
|
|
- byte count = 0;
|
|
798
|
+ if (apos) {
|
|
799
|
+ byte checksum = 0, count = 0;
|
799
|
800
|
while (command[count] != '*') checksum ^= command[count++];
|
800
|
|
- strchr_pointer = strchr(command, '*');
|
801
|
801
|
|
802
|
|
- if (strtol(strchr_pointer + 1, NULL, 10) != checksum) {
|
|
802
|
+ if (strtol(apos + 1, NULL, 10) != checksum) {
|
803
|
803
|
gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH));
|
804
|
804
|
return;
|
805
|
805
|
}
|
|
@@ -813,28 +813,26 @@ void get_command() {
|
813
|
813
|
gcode_LastN = gcode_N;
|
814
|
814
|
// if no errors, continue parsing
|
815
|
815
|
}
|
816
|
|
- else { // if we don't receive 'N' but still see '*'
|
817
|
|
- if ((strchr(command, '*') != NULL)) {
|
818
|
|
- gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
|
819
|
|
- return;
|
820
|
|
- }
|
|
816
|
+ else if (apos) { // No '*' without 'N'
|
|
817
|
+ gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
|
|
818
|
+ return;
|
821
|
819
|
}
|
822
|
820
|
|
823
|
|
- if (strchr(command, 'G') != NULL) {
|
824
|
|
- strchr_pointer = strchr(command, 'G');
|
825
|
|
- switch (strtol(strchr_pointer + 1, NULL, 10)) {
|
826
|
|
- case 0:
|
827
|
|
- case 1:
|
828
|
|
- case 2:
|
829
|
|
- case 3:
|
830
|
|
- if (IsStopped()) {
|
|
821
|
+ // Movement commands alert when stopped
|
|
822
|
+ if (IsStopped()) {
|
|
823
|
+ char *gpos = strchr(command, 'G');
|
|
824
|
+ if (gpos) {
|
|
825
|
+ int codenum = strtol(gpos + 1, NULL, 10);
|
|
826
|
+ switch (codenum) {
|
|
827
|
+ case 0:
|
|
828
|
+ case 1:
|
|
829
|
+ case 2:
|
|
830
|
+ case 3:
|
831
|
831
|
SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
|
832
|
832
|
LCD_MESSAGEPGM(MSG_STOPPED);
|
833
|
|
- }
|
834
|
|
- break;
|
835
|
|
- default:
|
836
|
|
- break;
|
837
|
|
- }
|
|
833
|
+ break;
|
|
834
|
+ }
|
|
835
|
+ }
|
838
|
836
|
}
|
839
|
837
|
|
840
|
838
|
// If command was e-stop process now
|
|
@@ -916,32 +914,32 @@ void get_command() {
|
916
|
914
|
|
917
|
915
|
bool code_has_value() {
|
918
|
916
|
int i = 1;
|
919
|
|
- char c = strchr_pointer[i];
|
920
|
|
- if (c == '-' || c == '+') c = strchr_pointer[++i];
|
921
|
|
- if (c == '.') c = strchr_pointer[++i];
|
|
917
|
+ char c = seen_pointer[i];
|
|
918
|
+ if (c == '-' || c == '+') c = seen_pointer[++i];
|
|
919
|
+ if (c == '.') c = seen_pointer[++i];
|
922
|
920
|
return (c >= '0' && c <= '9');
|
923
|
921
|
}
|
924
|
922
|
|
925
|
923
|
float code_value() {
|
926
|
924
|
float ret;
|
927
|
|
- char *e = strchr(strchr_pointer, 'E');
|
|
925
|
+ char *e = strchr(seen_pointer, 'E');
|
928
|
926
|
if (e) {
|
929
|
927
|
*e = 0;
|
930
|
|
- ret = strtod(strchr_pointer+1, NULL);
|
|
928
|
+ ret = strtod(seen_pointer+1, NULL);
|
931
|
929
|
*e = 'E';
|
932
|
930
|
}
|
933
|
931
|
else
|
934
|
|
- ret = strtod(strchr_pointer+1, NULL);
|
|
932
|
+ ret = strtod(seen_pointer+1, NULL);
|
935
|
933
|
return ret;
|
936
|
934
|
}
|
937
|
935
|
|
938
|
|
-long code_value_long() { return strtol(strchr_pointer + 1, NULL, 10); }
|
|
936
|
+long code_value_long() { return strtol(seen_pointer + 1, NULL, 10); }
|
939
|
937
|
|
940
|
|
-int16_t code_value_short() { return (int16_t)strtol(strchr_pointer + 1, NULL, 10); }
|
|
938
|
+int16_t code_value_short() { return (int16_t)strtol(seen_pointer + 1, NULL, 10); }
|
941
|
939
|
|
942
|
940
|
bool code_seen(char code) {
|
943
|
|
- strchr_pointer = strchr(command_queue[cmd_queue_index_r], code);
|
944
|
|
- return (strchr_pointer != NULL); //Return True if a character was found
|
|
941
|
+ seen_pointer = strchr(current_command_args, code); // +3 since "G0 " is the shortest prefix
|
|
942
|
+ return (seen_pointer != NULL); //Return True if a character was found
|
945
|
943
|
}
|
946
|
944
|
|
947
|
945
|
#define DEFINE_PGM_READ_ANY(type, reader) \
|
|
@@ -1792,6 +1790,13 @@ void gcode_get_destination() {
|
1792
|
1790
|
}
|
1793
|
1791
|
}
|
1794
|
1792
|
|
|
1793
|
+void unknown_command_error() {
|
|
1794
|
+ SERIAL_ECHO_START;
|
|
1795
|
+ SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
|
|
1796
|
+ SERIAL_ECHO(current_command);
|
|
1797
|
+ SERIAL_ECHOPGM("\"\n");
|
|
1798
|
+}
|
|
1799
|
+
|
1795
|
1800
|
/**
|
1796
|
1801
|
* G0, G1: Coordinated movement of X Y Z E axes
|
1797
|
1802
|
*/
|
|
@@ -2843,7 +2848,7 @@ inline void gcode_G92() {
|
2843
|
2848
|
* M1: // M1 - Conditional stop - Wait for user button press on LCD
|
2844
|
2849
|
*/
|
2845
|
2850
|
inline void gcode_M0_M1() {
|
2846
|
|
- char *src = strchr_pointer + 2;
|
|
2851
|
+ char *args = current_command_args;
|
2847
|
2852
|
|
2848
|
2853
|
millis_t codenum = 0;
|
2849
|
2854
|
bool hasP = false, hasS = false;
|
|
@@ -2855,11 +2860,9 @@ inline void gcode_G92() {
|
2855
|
2860
|
codenum = code_value() * 1000; // seconds to wait
|
2856
|
2861
|
hasS = codenum > 0;
|
2857
|
2862
|
}
|
2858
|
|
- char* starpos = strchr(src, '*');
|
2859
|
|
- if (starpos != NULL) *(starpos) = '\0';
|
2860
|
|
- while (*src == ' ') ++src;
|
2861
|
|
- if (!hasP && !hasS && *src != '\0')
|
2862
|
|
- lcd_setstatus(src, true);
|
|
2863
|
+
|
|
2864
|
+ if (!hasP && !hasS && *args != '\0')
|
|
2865
|
+ lcd_setstatus(args, true);
|
2863
|
2866
|
else {
|
2864
|
2867
|
LCD_MESSAGEPGM(MSG_USERWAIT);
|
2865
|
2868
|
#if defined(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
|
|
@@ -2932,10 +2935,7 @@ inline void gcode_M17() {
|
2932
|
2935
|
* M23: Select a file
|
2933
|
2936
|
*/
|
2934
|
2937
|
inline void gcode_M23() {
|
2935
|
|
- char* codepos = strchr_pointer + 4;
|
2936
|
|
- char* starpos = strchr(codepos, '*');
|
2937
|
|
- if (starpos) *starpos = '\0';
|
2938
|
|
- card.openFile(codepos, true);
|
|
2938
|
+ card.openFile(current_command_args, true);
|
2939
|
2939
|
}
|
2940
|
2940
|
|
2941
|
2941
|
/**
|
|
@@ -2972,14 +2972,7 @@ inline void gcode_M17() {
|
2972
|
2972
|
* M28: Start SD Write
|
2973
|
2973
|
*/
|
2974
|
2974
|
inline void gcode_M28() {
|
2975
|
|
- char* codepos = strchr_pointer + 4;
|
2976
|
|
- char* starpos = strchr(codepos, '*');
|
2977
|
|
- if (starpos) {
|
2978
|
|
- char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
|
2979
|
|
- strchr_pointer = strchr(npos, ' ') + 1;
|
2980
|
|
- *(starpos) = '\0';
|
2981
|
|
- }
|
2982
|
|
- card.openFile(codepos, false);
|
|
2975
|
+ card.openFile(current_command_args, false);
|
2983
|
2976
|
}
|
2984
|
2977
|
|
2985
|
2978
|
/**
|
|
@@ -2996,13 +2989,7 @@ inline void gcode_M17() {
|
2996
|
2989
|
inline void gcode_M30() {
|
2997
|
2990
|
if (card.cardOK) {
|
2998
|
2991
|
card.closefile();
|
2999
|
|
- char* starpos = strchr(strchr_pointer + 4, '*');
|
3000
|
|
- if (starpos) {
|
3001
|
|
- char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
|
3002
|
|
- strchr_pointer = strchr(npos, ' ') + 1;
|
3003
|
|
- *(starpos) = '\0';
|
3004
|
|
- }
|
3005
|
|
- card.removeFile(strchr_pointer + 4);
|
|
2992
|
+ card.removeFile(current_command_args);
|
3006
|
2993
|
}
|
3007
|
2994
|
}
|
3008
|
2995
|
|
|
@@ -3032,23 +3019,18 @@ inline void gcode_M31() {
|
3032
|
3019
|
if (card.sdprinting)
|
3033
|
3020
|
st_synchronize();
|
3034
|
3021
|
|
3035
|
|
- char* codepos = strchr_pointer + 4;
|
3036
|
|
-
|
3037
|
|
- char* namestartpos = strchr(codepos, '!'); //find ! to indicate filename string start.
|
3038
|
|
- if (! namestartpos)
|
3039
|
|
- namestartpos = codepos; //default name position, 4 letters after the M
|
|
3022
|
+ char* namestartpos = strchr(current_command_args, '!'); // Find ! to indicate filename string start.
|
|
3023
|
+ if (!namestartpos)
|
|
3024
|
+ namestartpos = current_command_args; // Default name position, 4 letters after the M
|
3040
|
3025
|
else
|
3041
|
3026
|
namestartpos++; //to skip the '!'
|
3042
|
3027
|
|
3043
|
|
- char* starpos = strchr(codepos, '*');
|
3044
|
|
- if (starpos) *(starpos) = '\0';
|
3045
|
|
-
|
3046
|
|
- bool call_procedure = code_seen('P') && (strchr_pointer < namestartpos);
|
|
3028
|
+ bool call_procedure = code_seen('P') && (seen_pointer < namestartpos);
|
3047
|
3029
|
|
3048
|
3030
|
if (card.cardOK) {
|
3049
|
3031
|
card.openFile(namestartpos, true, !call_procedure);
|
3050
|
3032
|
|
3051
|
|
- if (code_seen('S') && strchr_pointer < namestartpos) // "S" (must occur _before_ the filename!)
|
|
3033
|
+ if (code_seen('S') && seen_pointer < namestartpos) // "S" (must occur _before_ the filename!)
|
3052
|
3034
|
card.setIndex(code_value_short());
|
3053
|
3035
|
|
3054
|
3036
|
card.startFileprint();
|
|
@@ -3061,13 +3043,7 @@ inline void gcode_M31() {
|
3061
|
3043
|
* M928: Start SD Write
|
3062
|
3044
|
*/
|
3063
|
3045
|
inline void gcode_M928() {
|
3064
|
|
- char* starpos = strchr(strchr_pointer + 5, '*');
|
3065
|
|
- if (starpos) {
|
3066
|
|
- char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
|
3067
|
|
- strchr_pointer = strchr(npos, ' ') + 1;
|
3068
|
|
- *(starpos) = '\0';
|
3069
|
|
- }
|
3070
|
|
- card.openLogFile(strchr_pointer + 5);
|
|
3046
|
+ card.openLogFile(current_command_args);
|
3071
|
3047
|
}
|
3072
|
3048
|
|
3073
|
3049
|
#endif // SDSUPPORT
|
|
@@ -3864,16 +3840,12 @@ inline void gcode_M115() {
|
3864
|
3840
|
SERIAL_PROTOCOLPGM(MSG_M115_REPORT);
|
3865
|
3841
|
}
|
3866
|
3842
|
|
3867
|
|
-#ifdef ULTIPANEL
|
3868
|
|
-
|
3869
|
|
- /**
|
3870
|
|
- * M117: Set LCD Status Message
|
3871
|
|
- */
|
3872
|
|
- inline void gcode_M117() {
|
3873
|
|
- lcd_setstatus(strchr_pointer + 5);
|
3874
|
|
- }
|
3875
|
|
-
|
3876
|
|
-#endif
|
|
3843
|
+/**
|
|
3844
|
+ * M117: Set LCD Status Message
|
|
3845
|
+ */
|
|
3846
|
+inline void gcode_M117() {
|
|
3847
|
+ lcd_setstatus(current_command_args);
|
|
3848
|
+}
|
3877
|
3849
|
|
3878
|
3850
|
/**
|
3879
|
3851
|
* M119: Output endstop states to serial output
|
|
@@ -4161,10 +4133,7 @@ inline void gcode_M206() {
|
4161
|
4133
|
autoretract_enabled = true;
|
4162
|
4134
|
break;
|
4163
|
4135
|
default:
|
4164
|
|
- SERIAL_ECHO_START;
|
4165
|
|
- SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
|
4166
|
|
- SERIAL_ECHO(command_queue[cmd_queue_index_r]);
|
4167
|
|
- SERIAL_ECHOLNPGM("\"");
|
|
4136
|
+ unknown_command_error();
|
4168
|
4137
|
return;
|
4169
|
4138
|
}
|
4170
|
4139
|
for (int i=0; i<EXTRUDERS; i++) retracted[i] = false;
|
|
@@ -5084,8 +5053,7 @@ inline void gcode_M999() {
|
5084
|
5053
|
*
|
5085
|
5054
|
* F[mm/min] Set the movement feedrate
|
5086
|
5055
|
*/
|
5087
|
|
-inline void gcode_T() {
|
5088
|
|
- uint16_t tmp_extruder = code_value_short();
|
|
5056
|
+inline void gcode_T(uint8_t tmp_extruder) {
|
5089
|
5057
|
if (tmp_extruder >= EXTRUDERS) {
|
5090
|
5058
|
SERIAL_ECHO_START;
|
5091
|
5059
|
SERIAL_CHAR('T');
|
|
@@ -5188,21 +5156,52 @@ inline void gcode_T() {
|
5188
|
5156
|
}
|
5189
|
5157
|
|
5190
|
5158
|
/**
|
5191
|
|
- * Process Commands and dispatch them to handlers
|
|
5159
|
+ * Process a single command and dispatch it to its handler
|
5192
|
5160
|
* This is called from the main loop()
|
5193
|
5161
|
*/
|
5194
|
5162
|
void process_next_command() {
|
|
5163
|
+ current_command = command_queue[cmd_queue_index_r];
|
5195
|
5164
|
|
5196
|
5165
|
if ((marlin_debug_flags & DEBUG_ECHO)) {
|
5197
|
5166
|
SERIAL_ECHO_START;
|
5198
|
|
- SERIAL_ECHOLN(command_queue[cmd_queue_index_r]);
|
|
5167
|
+ SERIAL_ECHOLN(current_command);
|
|
5168
|
+ }
|
|
5169
|
+
|
|
5170
|
+ // Sanitize the current command:
|
|
5171
|
+ // - Skip leading spaces
|
|
5172
|
+ // - Bypass N...
|
|
5173
|
+ // - Overwrite * with nul to mark the end
|
|
5174
|
+ while (*current_command == ' ') ++current_command;
|
|
5175
|
+ if (*current_command == 'N' && current_command[1] >= '0' && current_command[1] <= '9') {
|
|
5176
|
+ while (*current_command != ' ') ++current_command;
|
|
5177
|
+ while (*current_command == ' ') ++current_command;
|
5199
|
5178
|
}
|
|
5179
|
+ char *starpos = strchr(current_command, '*'); // * should always be the last parameter
|
|
5180
|
+ if (starpos) *starpos = '\0';
|
|
5181
|
+
|
|
5182
|
+ // Get the command code, which must be G, M, or T
|
|
5183
|
+ char command_code = *current_command;
|
|
5184
|
+
|
|
5185
|
+ // The code must have a numeric value
|
|
5186
|
+ bool code_is_good = (current_command[1] >= '0' && current_command[1] <= '9');
|
|
5187
|
+
|
|
5188
|
+ int codenum; // define ahead of goto
|
5200
|
5189
|
|
5201
|
|
- if (code_seen('G')) {
|
|
5190
|
+ // Bail early if there's no code
|
|
5191
|
+ if (!code_is_good) goto ExitUnknownCommand;
|
5202
|
5192
|
|
5203
|
|
- int codenum = code_value_short();
|
|
5193
|
+ // Args pointer optimizes code_seen, especially those taking XYZEF
|
|
5194
|
+ // This wastes a little cpu on commands that expect no arguments.
|
|
5195
|
+ current_command_args = current_command;
|
|
5196
|
+ while (*current_command_args != ' ') ++current_command_args;
|
|
5197
|
+ while (*current_command_args == ' ') ++current_command_args;
|
5204
|
5198
|
|
5205
|
|
- switch (codenum) {
|
|
5199
|
+ // Interpret the code int
|
|
5200
|
+ codenum = code_value_short();
|
|
5201
|
+
|
|
5202
|
+ // Handle a known G, M, or T
|
|
5203
|
+ switch(command_code) {
|
|
5204
|
+ case 'G': switch (codenum) {
|
5206
|
5205
|
|
5207
|
5206
|
// G0, G1
|
5208
|
5207
|
case 0:
|
|
@@ -5271,11 +5270,12 @@ void process_next_command() {
|
5271
|
5270
|
case 92: // G92
|
5272
|
5271
|
gcode_G92();
|
5273
|
5272
|
break;
|
|
5273
|
+
|
|
5274
|
+ default: code_is_good = false;
|
5274
|
5275
|
}
|
5275
|
|
- }
|
|
5276
|
+ break;
|
5276
|
5277
|
|
5277
|
|
- else if (code_seen('M')) {
|
5278
|
|
- switch(code_value_short()) {
|
|
5278
|
+ case 'M': switch (codenum) {
|
5279
|
5279
|
#ifdef ULTIPANEL
|
5280
|
5280
|
case 0: // M0 - Unconditional stop - Wait for user button press on LCD
|
5281
|
5281
|
case 1: // M1 - Conditional stop - Wait for user button press on LCD
|
|
@@ -5350,8 +5350,7 @@ void process_next_command() {
|
5350
|
5350
|
|
5351
|
5351
|
case 105: // M105: Read current temperature
|
5352
|
5352
|
gcode_M105();
|
5353
|
|
- return;
|
5354
|
|
- break;
|
|
5353
|
+ return; // "ok" already printed
|
5355
|
5354
|
|
5356
|
5355
|
case 109: // M109: Wait for temperature
|
5357
|
5356
|
gcode_M109();
|
|
@@ -5425,13 +5424,9 @@ void process_next_command() {
|
5425
|
5424
|
case 115: // M115: Report capabilities
|
5426
|
5425
|
gcode_M115();
|
5427
|
5426
|
break;
|
5428
|
|
-
|
5429
|
|
- #ifdef ULTIPANEL
|
5430
|
|
- case 117: // M117: Set LCD message text
|
5431
|
|
- gcode_M117();
|
5432
|
|
- break;
|
5433
|
|
- #endif
|
5434
|
|
-
|
|
5427
|
+ case 117: // M117: Set LCD message text, if possible
|
|
5428
|
+ gcode_M117();
|
|
5429
|
+ break;
|
5435
|
5430
|
case 114: // M114: Report current position
|
5436
|
5431
|
gcode_M114();
|
5437
|
5432
|
break;
|
|
@@ -5701,19 +5696,20 @@ void process_next_command() {
|
5701
|
5696
|
case 999: // M999: Restart after being Stopped
|
5702
|
5697
|
gcode_M999();
|
5703
|
5698
|
break;
|
|
5699
|
+
|
|
5700
|
+ default: code_is_good = false;
|
5704
|
5701
|
}
|
5705
|
|
- }
|
|
5702
|
+ break;
|
5706
|
5703
|
|
5707
|
|
- else if (code_seen('T')) {
|
5708
|
|
- gcode_T();
|
|
5704
|
+ case 'T':
|
|
5705
|
+ gcode_T(codenum);
|
|
5706
|
+ break;
|
5709
|
5707
|
}
|
5710
|
5708
|
|
5711
|
|
- else {
|
5712
|
|
- SERIAL_ECHO_START;
|
5713
|
|
- SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
|
5714
|
|
- SERIAL_ECHO(command_queue[cmd_queue_index_r]);
|
5715
|
|
- SERIAL_ECHOLNPGM("\"");
|
5716
|
|
- }
|
|
5709
|
+ExitUnknownCommand:
|
|
5710
|
+
|
|
5711
|
+ // Still unknown command? Throw an error
|
|
5712
|
+ if (!code_is_good) unknown_command_error();
|
5717
|
5713
|
|
5718
|
5714
|
ok_to_send();
|
5719
|
5715
|
}
|