/** Converts a ascii GCode line into a GCode structure. */ bool GCode::parseAscii(char *line,bool fromSerial) { char *pos = line; params = 0; params2 = 0; internalCommand = !fromSerial; bool hasChecksum = false; char c; while ( (c = *(pos++)) ) { if(c == '(' || c == '%') break; // alternative comment or program block switch(c) { case 'N': case 'n': { actLineNumber = parseLongValue(pos); params |=1; N = actLineNumber; break; } case 'G': case 'g': { G = parseLongValue(pos) & 0xffff; params |= 4; if(G > 255) params |= 4096; break; } case 'M': case 'm': { M = parseLongValue(pos) & 0xffff; params |= 2; if(M > 255) params |= 4096; // handle non standard text arguments that some M codes have if (M == 20 || M == 23 || M == 28 || M == 29 || M == 30 || M == 32 || M == 36 || M == 117) { // after M command we got a filename or text char digit; while( (digit = *pos) ) { if (digit < '0' || digit > '9') break; pos++; } while( (digit = *pos) ) { if (digit != ' ') break; pos++; // skip leading whitespaces (may be no white space) } text = pos; while (*pos) { if((M != 117 && M != 20 && *pos==' ') || *pos=='*') break; pos++; // find a space as file name end } *pos = 0; // truncate filename by erasing space with nul, also skips checksum waitUntilAllCommandsAreParsed = true; // don't risk string be deleted params |= 32768; } break; } case 'X': case 'x': { X = parseFloatValue(pos); params |= 8; break; } case 'Y': case 'y': { Y = parseFloatValue(pos); params |= 16; break; } case 'Z': case 'z': { Z = parseFloatValue(pos); params |= 32; break; } case 'E': case 'e': { E = parseFloatValue(pos); params |= 64; break; } case 'F': case 'f': { F = parseFloatValue(pos); params |= 256; break; } case 'T': case 't': { T = parseLongValue(pos) & 0xff; params |= 512; break; } case 'S': case 's': { S = parseLongValue(pos); params |= 1024; break; } case 'P': case 'p': { P = parseLongValue(pos); params |= 2048; break; } case 'I': case 'i': { I = parseFloatValue(pos); params2 |= 1; params |= 4096; // Needs V2 for saving break; } case 'J': case 'j': { J = parseFloatValue(pos); params2 |= 2; params |= 4096; // Needs V2 for saving break; } case 'R': case 'r': { R = parseFloatValue(pos); params2 |= 4; params |= 4096; // Needs V2 for saving break; } case 'D': case 'd': { D = parseFloatValue(pos); params2 |= 8; params |= 4096; // Needs V2 for saving break; } case 'C': case 'c': { D = parseFloatValue(pos); params2 |= 16; params |= 4096; // Needs V2 for saving break; } case 'H': case 'h': { D = parseFloatValue(pos); params2 |= 32; params |= 4096; // Needs V2 for saving break; } case 'A': case 'a': { D = parseFloatValue(pos); params2 |= 64; params |= 4096; // Needs V2 for saving break; } case 'B': case 'b': { D = parseFloatValue(pos); params2 |= 128; params |= 4096; // Needs V2 for saving break; } case 'K': case 'k': { D = parseFloatValue(pos); params2 |= 256; params |= 4096; // Needs V2 for saving break; } case 'L': case 'l': { D = parseFloatValue(pos); params2 |= 512; params |= 4096; // Needs V2 for saving break; } case 'O': case 'o': { D = parseFloatValue(pos); params2 |= 1024; params |= 4096; // Needs V2 for saving break; } case '*' : //checksum { uint8_t checksum_given = parseLongValue(pos); uint8_t checksum = 0; while(line != (pos - 1)) checksum ^= *line++; #if FEATURE_CHECKSUM_FORCED Printer::flag0 |= PRINTER_FLAG0_FORCE_CHECKSUM; #endif if(checksum != checksum_given) { if(Printer::debugErrors()) { Com::printErrorFLN(Com::tWrongChecksum); } return false; // mismatch } hasChecksum = true; break; } default: break; }// end switch }// end while if(wasLastCommandReceivedAsBinary && !hasChecksum) { Com::printErrorFLN("Checksum required when switching back to ASCII protocol."); return false; } if(hasFormatError() || (params & 518) == 0) // Must contain G, M or T command and parameter need to have variables! { formatErrors++; if(Printer::debugErrors()) Com::printErrorFLN(Com::tFormatError); if(formatErrors < 3) return false; } else formatErrors = 0; return true; }
/** Converts a ascii GCode line into a GCode structure. */ bool GCode::parseAscii(char *line,bool fromSerial) { bool has_checksum = false; char *pos; params = 0; params2 = 0; if((pos = strchr(line,'N'))!=0) // Line number detected { actLineNumber = parseLongValue(++pos); params |=1; N = actLineNumber & 0xffff; } if((pos = strchr(line,'M'))!=0) // M command { M = parseLongValue(++pos) & 0xffff; params |= 2; if(M>255) params |= 4096; } if(hasM() && (M == 23 || M == 28 || M == 29 || M == 30 || M == 32 || M == 117)) { // after M command we got a filename for sd card management char *sp = line; while(*sp!='M') sp++; // Search M command while(*sp!=' ') sp++; // search next whitespace while(*sp==' ') sp++; // skip leading whitespaces text = sp; while(*sp) { if((M != 117 && *sp==' ') || *sp=='*') break; // end of filename reached sp++; } *sp = 0; // Removes checksum, but we don't care. Could also be part of the string. waitUntilAllCommandsAreParsed = true; // don't risk string be deleted params |= 32768; } else { if((pos = strchr(line,'G'))!=0) // G command { G = parseLongValue(++pos) & 0xffff; params |= 4; if(G>255) params |= 4096; } if((pos = strchr(line,'X'))!=0) { X = parseFloatValue(++pos); params |= 8; } if((pos = strchr(line,'Y'))!=0) { Y = parseFloatValue(++pos); params |= 16; } if((pos = strchr(line,'Z'))!=0) { Z = parseFloatValue(++pos); params |= 32; } if((pos = strchr(line,'E'))!=0) { E = parseFloatValue(++pos); params |= 64; } if((pos = strchr(line,'F'))!=0) { F = parseFloatValue(++pos); params |= 256; } if((pos = strchr(line,'T'))!=0) // M command { T = parseLongValue(++pos) & 0xff; params |= 512; } if((pos = strchr(line,'S'))!=0) // M command { S = parseLongValue(++pos); params |= 1024; } if((pos = strchr(line,'P'))!=0) // M command { P = parseLongValue(++pos); params |= 2048; } if((pos = strchr(line,'I'))!=0) { I = parseFloatValue(++pos); params2 |= 1; params |= 4096; // Needs V2 for saving } if((pos = strchr(line,'J'))!=0) { J = parseFloatValue(++pos); params2 |= 2; params |= 4096; // Needs V2 for saving } if((pos = strchr(line,'R'))!=0) { R = parseFloatValue(++pos); params2 |= 4; params |= 4096; // Needs V2 for saving } } if((pos = strchr(line,'*'))!=0) // checksum { uint8_t checksum_given = parseLongValue(pos+1); uint8_t checksum = 0; while(line!=pos) checksum ^= *line++; #if FEATURE_CHECKSUM_FORCED Printer::flag0 |= PRINTER_FLAG0_FORCE_CHECKSUM; #endif if(checksum!=checksum_given) { if(Printer::debugErrors()) { Com::printErrorFLN(Com::tWrongChecksum); } return false; // mismatch } } #if FEATURE_CHECKSUM_FORCED else { if(!fromSerial) return true; if(hasM() && (M == 110 || hasString())) return true; if(Printer::debugErrors()) { Com::printErrorFLN(Com::tMissingChecksum); } return false; } #endif if(hasFormatError() || (params & 518)==0) // Must contain G, M or T command and parameter need to have variables! { formatErrors++; if(Printer::debugErrors()) Com::printErrorFLN(Com::tFormatError); if(formatErrors<3) return false; } else formatErrors = 0; return true; }
bool CompactQik2s9v1::hasFormatError() { return hasFormatError(false); }