From 99fb1bc3e8953170440a7b9dd18f965fa632f5bb Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Thu, 5 Mar 2015 15:22:37 -0500 Subject: [PATCH 1/2] Attempt to resolve #1568 and add basic escape character support --- Marlin/Marlin_main.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 79416850be..b6a1ee2b6e 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -730,7 +730,6 @@ void get_command() serial_char = MYSERIAL.read(); if(serial_char == '\n' || serial_char == '\r' || - (serial_char == ':' && comment_mode == false) || serial_count >= (MAX_CMD_SIZE - 1) ) { if(!serial_count) { //if empty line @@ -739,7 +738,6 @@ void get_command() } cmdbuffer[bufindw][serial_count] = 0; //terminate string if(!comment_mode){ - comment_mode = false; //for new command fromsd[bufindw] = false; if(strchr(cmdbuffer[bufindw], 'N') != NULL) { @@ -823,10 +821,19 @@ void get_command() } serial_count = 0; //clear buffer } - else - { - if(serial_char == ';') comment_mode = true; - if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; + else if(serial_char == '\\') { //Handle escapes + + if(MYSERIAL.available() > 0 && buflen < BUFSIZE) { + // if we have one more character, copy it over + MYSERIAL.read(); + cmdbuffer[bufindw][serial_count++] = serial_char; + } + + //otherwise do nothing + } + else { // its not a newline, carriage return or escape char + if(serial_char == ';') comment_mode = true; + if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; } } #ifdef SDSUPPORT From 63b62d8d4ebbd700758771c0098e100cc40dd17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 5 Mar 2015 23:30:34 +0100 Subject: [PATCH 2/2] Fixed in-line comments and escaping * "G1 X1 ; test" was not executing "G1 X1" due to never leaving comment mode. * "M117 Hello \;)" printed "Hello \" to the display due to not replacing serial_char properly. Tested with the following commands: * M117 Hello ; test => displays "Hello" on display, ignores "test" * G1 X1 ; foo => moves 1mm in X, ignores "foo" * ; test => completely ignored, not even acknowledged * M117 Hello \;) => displays "Hello ;)" on display * M117 Hello \\;) => displays "Hello \" on display, ignores ")" --- Documentation/GCodes.md | 22 ++++++ Marlin/Marlin_main.cpp | 145 ++++++++++++++++++++-------------------- 2 files changed, 96 insertions(+), 71 deletions(-) diff --git a/Documentation/GCodes.md b/Documentation/GCodes.md index 253fb7fc81..fde8435932 100644 --- a/Documentation/GCodes.md +++ b/Documentation/GCodes.md @@ -101,3 +101,25 @@ * M908 - Control digital trimpot directly. * M928 - Start SD logging (M928 filename.g) - ended by M29 * M999 - Restart after being stopped by error + +# Comments + +Comments start at a `;` (semicolon) and end with the end of the line: + + N3 T0*57 ; This is a comment + N4 G92 E0*67 + ; So is this + N5 G28*22 + +(example taken from the [RepRap wiki](http://reprap.org/wiki/Gcode#Comments)) + +If you need to use a literal `;` somewhere (for example within `M117`), you can escape semicolons with a `\` +(backslash): + + M117 Hello \;) + +`\` can also be used to escape `\` itself, if you need a literal `\` in front of a `;`: + + M117 backslash: \\;and a comment + +Please note that hosts should strip any comments before sending GCODE to the printer in order to save bandwidth. \ No newline at end of file diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index b6a1ee2b6e..c759a78c0c 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -732,100 +732,103 @@ void get_command() serial_char == '\r' || serial_count >= (MAX_CMD_SIZE - 1) ) { - if(!serial_count) { //if empty line - comment_mode = false; //for new command + // end of line == end of comment + comment_mode = false; + + if(!serial_count) { + // short cut for empty lines return; } cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - fromsd[bufindw] = false; - if(strchr(cmdbuffer[bufindw], 'N') != NULL) + + fromsd[bufindw] = false; + if(strchr(cmdbuffer[bufindw], 'N') != NULL) + { + strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); + gcode_N = (strtol(strchr_pointer + 1, NULL, 10)); + if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer[bufindw], PSTR("M110")) == NULL) ) { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_LINE_NO); + SERIAL_ERRORLN(gcode_LastN); + //Serial.println(gcode_N); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + + if(strchr(cmdbuffer[bufindw], '*') != NULL) { - strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); - gcode_N = (strtol(strchr_pointer + 1, NULL, 10)); - if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer[bufindw], PSTR("M110")) == NULL) ) { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_LINE_NO); - SERIAL_ERRORLN(gcode_LastN); - //Serial.println(gcode_N); - FlushSerialRequestResend(); - serial_count = 0; - return; - } + byte checksum = 0; + byte count = 0; + while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; + strchr_pointer = strchr(cmdbuffer[bufindw], '*'); - if(strchr(cmdbuffer[bufindw], '*') != NULL) - { - byte checksum = 0; - byte count = 0; - while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; - strchr_pointer = strchr(cmdbuffer[bufindw], '*'); - - if( (int)(strtod(strchr_pointer + 1, NULL)) != checksum) { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); - SERIAL_ERRORLN(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { + if( (int)(strtod(strchr_pointer + 1, NULL)) != checksum) { SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); + SERIAL_ERRORPGM(MSG_ERR_CHECKSUM_MISMATCH); SERIAL_ERRORLN(gcode_LastN); FlushSerialRequestResend(); serial_count = 0; return; } - - gcode_LastN = gcode_N; //if no errors, continue parsing } - else // if we don't receive 'N' but still see '*' + else { - if((strchr(cmdbuffer[bufindw], '*') != NULL)) - { - SERIAL_ERROR_START; - SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); - SERIAL_ERRORLN(gcode_LastN); - serial_count = 0; - return; - } - } - if((strchr(cmdbuffer[bufindw], 'G') != NULL)){ - strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); - switch((int)((strtod(strchr_pointer + 1, NULL)))){ - case 0: - case 1: - case 2: - case 3: - if (Stopped == true) { - SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); - LCD_MESSAGEPGM(MSG_STOPPED); - } - break; - default: - break; - } - + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_NO_CHECKSUM); + SERIAL_ERRORLN(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; } - //If command was e-stop process now - if(strcmp(cmdbuffer[bufindw], "M112") == 0) - kill(); - - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; + gcode_LastN = gcode_N; + //if no errors, continue parsing } + else // if we don't receive 'N' but still see '*' + { + if((strchr(cmdbuffer[bufindw], '*') != NULL)) + { + SERIAL_ERROR_START; + SERIAL_ERRORPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM); + SERIAL_ERRORLN(gcode_LastN); + serial_count = 0; + return; + } + } + if((strchr(cmdbuffer[bufindw], 'G') != NULL)){ + strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); + switch((int)((strtod(strchr_pointer + 1, NULL)))){ + case 0: + case 1: + case 2: + case 3: + if (Stopped == true) { + SERIAL_ERRORLNPGM(MSG_ERR_STOPPED); + LCD_MESSAGEPGM(MSG_STOPPED); + } + break; + default: + break; + } + + } + + //If command was e-stop process now + if(strcmp(cmdbuffer[bufindw], "M112") == 0) + kill(); + + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + serial_count = 0; //clear buffer } else if(serial_char == '\\') { //Handle escapes if(MYSERIAL.available() > 0 && buflen < BUFSIZE) { // if we have one more character, copy it over - MYSERIAL.read(); + serial_char = MYSERIAL.read(); cmdbuffer[bufindw][serial_count++] = serial_char; }