From d7fd1866ffbfbb87229fa89ae2c7add48307cd8a Mon Sep 17 00:00:00 2001 From: Christian Hammacher Date: Thu, 29 Jul 2021 19:04:19 +0200 Subject: Further improvements Added support for expression lists (untested in standalone mode) M23/M32 are invoked again by DSF in SBC mode Increased SBC task priority Bug fix: CAN diagnostics output extra NL Bug fix: M999 P"ERASE" was not working on the Mini5+ series --- src/GCodes/GCodeBuffer/BinaryParser.cpp | 121 +++++++++++++++++++++++----- src/GCodes/GCodeBuffer/BinaryParser.h | 2 +- src/GCodes/GCodeBuffer/ExpressionParser.cpp | 6 +- src/GCodes/GCodeBuffer/ExpressionParser.h | 2 +- src/GCodes/GCodeBuffer/StringParser.cpp | 8 +- src/GCodes/GCodes.cpp | 12 +-- src/GCodes/GCodes2.cpp | 14 +++- src/GCodes/GCodes3.cpp | 8 +- 8 files changed, 128 insertions(+), 45 deletions(-) (limited to 'src/GCodes') diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp index 78145ef1..de4b7b02 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.cpp +++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp @@ -457,17 +457,17 @@ void BinaryParser::GetPossiblyQuotedString(const StringRef& str, bool allowEmpty void BinaryParser::GetFloatArray(float arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::Float); } void BinaryParser::GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::Int); } void BinaryParser::GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS(GCodeException) { - GetArray(arr, length, doPad); + GetArray(arr, length, doPad, DataType::UInt); } // Get a :-separated list of drivers after a key letter @@ -498,6 +498,17 @@ void BinaryParser::GetDriverIdArray(DriverId arr[], size_t& length) THROWS(GCode length = seenParameter->intValue; break; + case DataType::Expression: + { + float temp[seenParameter->intValue]; + GetArray(temp, length, false, DataType::Float); + for (int i = 0; i < seenParameter->intValue; i++) + { + SetDriverIdFromBinary(arr[i], temp[i]); + } + break; + } + default: length = 0; return; @@ -562,7 +573,7 @@ void BinaryParser::AppendFullCommand(const StringRef &s) const noexcept } } -template void BinaryParser::GetArray(T arr[], size_t& length, bool doPad) THROWS(GCodeException) +template void BinaryParser::GetArray(T arr[], size_t& length, bool doPad, DataType type) THROWS(GCodeException) { if (seenParameter == nullptr) { @@ -617,34 +628,104 @@ template void BinaryParser::GetArray(T arr[], size_t& length, bool d break; case DataType::Expression: - //TODO need a way to pass multi-element array-valued expressions. For now we support only single-element expressions. + { + const char *pos = seenParameterValue, *endPos = seenParameterValue + seenParameter->intValue; + + // Check if the whole expression is encapsulated in curly braces and remove them if necessary + if (*pos == '{' && pos != endPos) { - ExpressionParser parser(gb, seenParameterValue, seenParameterValue + seenParameter->intValue, -1); - const ExpressionValue val = parser.Parse(); - switch ((TypeCode)val.type) + bool isEncapsulated = true, inQuotes = false; + size_t numBraces = 1; + for (const char *str = pos + 1; str < endPos; str++) + { + if (inQuotes) + { + inQuotes = (*str != '"'); + } + else if (*str == '"') + { + inQuotes = true; + } + else if (*str == '{') + { + numBraces++; + } + else if (*str == '}') + { + numBraces--; + if (numBraces == 0) + { + const char *curPos = str; + while (str != endPos && strchr("\t ", *++str) != nullptr) { } + if (str == endPos) + { + endPos = curPos + 1; + } + else + { + isEncapsulated = false; + } + break; + } + } + } + + if (isEncapsulated) { - case TypeCode::Int32: - arr[0] = (T)val.iVal; - lastIndex = 0; + pos++; + endPos--; + } + } + + // Read array expression + for (;;) + { + if (lastIndex >= (int)length) + { + throw ConstructParseException("array too long, max length = %u", (uint32_t)length); + } + + // Read the next expression value + ExpressionParser parser(gb, pos, endPos, -1); + switch (type) + { + case DataType::Int: + arr[++lastIndex] = (T)parser.ParseInteger(); break; - case TypeCode::Float: - arr[0] = (T)val.fVal; - lastIndex = 0; + case DataType::UInt: + arr[++lastIndex] = (T)parser.ParseUnsigned(); break; - case TypeCode::Uint32: - case TypeCode::DriverId: - arr[0] = (T)val.uVal; - lastIndex = 0; + case DataType::Float: + arr[++lastIndex] = (T)parser.ParseFloat(); break; default: - throw ConstructParseException("invalid expression type"); + throw ConstructParseException("Unsupported array data type"); + } + parser.CheckForExtraCharacters(true); + pos = parser.GetEndptr(); + + if (pos++ >= endPos) + { + break; + } + } + + if (doPad && lastIndex == 0) + { + for (size_t i = 1; i < length; i++) + { + arr[i] = arr[0]; } - parser.CheckForExtraCharacters(); + } + else + { + length = lastIndex + 1; } break; + } default: length = 0; diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h index 5a4bcc38..3495d9c8 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.h +++ b/src/GCodes/GCodeBuffer/BinaryParser.h @@ -72,7 +72,7 @@ private: GCodeException ConstructParseException(const char *str, uint32_t param) const noexcept; size_t AddPadding(size_t bytesRead) const noexcept { return (bytesRead + 3u) & (~3u); } - template void GetArray(T arr[], size_t& length, bool doPad) THROWS(GCodeException) SPEED_CRITICAL; + template void GetArray(T arr[], size_t& length, bool doPad, DataType type) THROWS(GCodeException) SPEED_CRITICAL; void WriteParameters(const StringRef& s, bool quoteStrings) const noexcept; size_t bufferLength; diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.cpp b/src/GCodes/GCodeBuffer/ExpressionParser.cpp index 133ed763..0e3ac432 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.cpp +++ b/src/GCodes/GCodeBuffer/ExpressionParser.cpp @@ -713,10 +713,12 @@ void ExpressionParser::SkipWhiteSpace() noexcept } } -void ExpressionParser::CheckForExtraCharacters() THROWS(GCodeException) +void ExpressionParser::CheckForExtraCharacters(bool isArrayExpression) THROWS(GCodeException) { SkipWhiteSpace(); - if (CurrentCharacter() != 0) + + char c = CurrentCharacter(); + if (c != 0 && (!isArrayExpression || (c != EXPRESSION_LIST_SEPARATOR && c != LIST_SEPARATOR))) { ThrowParseException("Unexpected characters after expression"); } diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.h b/src/GCodes/GCodeBuffer/ExpressionParser.h index fc8dc1b3..bfd4de4e 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.h +++ b/src/GCodes/GCodeBuffer/ExpressionParser.h @@ -26,7 +26,7 @@ public: uint32_t ParseUnsigned() THROWS(GCodeException); void SkipWhiteSpace() noexcept; - void CheckForExtraCharacters() THROWS(GCodeException); + void CheckForExtraCharacters(bool isArrayExpression = false) THROWS(GCodeException); const char *GetEndptr() const noexcept { return currentp; } private: diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index 691be0ac..9247c577 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -1086,7 +1086,7 @@ void StringParser::GetFloatArray(float arr[], size_t& returnedLength, bool doPad { CheckArrayLength(length, returnedLength); arr[length++] = ReadFloatValue(); - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1123,7 +1123,7 @@ void StringParser::GetIntArray(int32_t arr[], size_t& returnedLength, bool doPad CheckArrayLength(length, returnedLength); arr[length] = ReadIValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1159,7 +1159,7 @@ void StringParser::GetUnsignedArray(uint32_t arr[], size_t& returnedLength, bool CheckArrayLength(length, returnedLength); arr[length] = ReadUIValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } @@ -1196,7 +1196,7 @@ void StringParser::GetDriverIdArray(DriverId arr[], size_t& returnedLength) THRO CheckArrayLength(length, returnedLength); arr[length] = ReadDriverIdValue(); length++; - if (gb.buffer[readPointer] != LIST_SEPARATOR) + if (gb.buffer[readPointer] != EXPRESSION_LIST_SEPARATOR && gb.buffer[readPointer] != LIST_SEPARATOR) { break; } diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 1a932bd0..9c716f3b 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -478,16 +478,10 @@ void GCodes::Spin() noexcept #if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) + // Need to check if the print has been stopped by the SBC + if (reprap.UsingLinuxInterface() && reprap.GetLinuxInterface().HasPrintStopped()) { - if (reprap.GetLinuxInterface().HasPrintStarted()) - { - StartPrinting(true); - } - else if (reprap.GetLinuxInterface().HasPrintStopped()) - { - StopPrint(reprap.GetLinuxInterface().GetPrintStopReason()); - } + StopPrint(reprap.GetLinuxInterface().GetPrintStopReason()); } #endif diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 894630b0..d5dc4af4 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -831,7 +831,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx result = MassStorage::Unmount(card, reply); } break; +#endif +#if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE case 23: // Set file to print case 32: // Select file and start SD print // We now allow a file that is being printed to chain to another file. This is required for the resume-after-power-fail functionality. @@ -849,7 +851,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { String filename; gb.GetUnprecedentedString(filename.GetRef()); - if (QueueFileToPrint(filename.c_str(), reply)) + if ( +#if HAS_LINUX_INTERFACE + reprap.UsingLinuxInterface() +# if HAS_MASS_STORAGE + || +# endif +#endif +#if HAS_MASS_STORAGE + QueueFileToPrint(filename.c_str(), reply) +#endif + ) { reprap.GetPrintMonitor().StartingPrint(filename.c_str()); if (gb.LatestMachineState().compatibility == Compatibility::Marlin) diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 3f991bf0..5bed126e 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -432,13 +432,7 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const simulationMode = 1; reprap.GetMove().Simulate(simulationMode); reprap.GetPrintMonitor().StartingPrint(file.c_str()); -# if HAS_LINUX_INTERFACE - if (!reprap.UsingLinuxInterface()) -# endif - { - // If using a SBC, this is already called when the print file info is set - StartPrinting(true); - } + StartPrinting(true); reply.printf("Simulating print of file %s", file.c_str()); return GCodeResult::ok; } -- cgit v1.2.3