diff options
author | Christian Hammacher <bmasterc@gmail.com> | 2022-10-28 11:49:51 +0300 |
---|---|---|
committer | Christian Hammacher <bmasterc@gmail.com> | 2022-10-28 11:49:51 +0300 |
commit | ea1c2d1c15a7fb34dd1e8d4ff18b56d6e481fc06 (patch) | |
tree | d6650b8cf3d9667a34cd211f4fd5f47a6b6a3492 | |
parent | 03edcc635b371c118ea217086142d7bf26f833c4 (diff) | |
parent | d4bea3d3c623da8ae91484ab3a87d006e078cabb (diff) |
Merge remote-tracking branch 'origin/3.5-dev' into v3-chrishamm
58 files changed, 792 insertions, 607 deletions
diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index 9cb8b0c0..d692c7c7 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -919,7 +919,7 @@ extern "C" [[noreturn]] void CanReceiverLoop(void *) noexcept // This one is used by ATE GCodeResult CanInterface::EnableRemoteDrivers(const CanDriversList& drivers, const StringRef& reply) noexcept { - return SetRemoteDriverStates(drivers, reply, DriverStateControl(DriverStateControl::driverActive)); + return SetRemoteDriverStates(drivers, reply, DriverStateControl(DriverStateControl::driverActive, reprap.GetGCodes().GetMotorBrakeOffDelay())); } // This one is used by Prepare and by M17 @@ -932,7 +932,7 @@ void CanInterface::EnableRemoteDrivers(const CanDriversList& drivers) noexcept // This one is used by ATE GCodeResult CanInterface::DisableRemoteDrivers(const CanDriversList& drivers, const StringRef& reply) noexcept { - return SetRemoteDriverStates(drivers, reply, DriverStateControl(DriverStateControl::driverDisabled)); + return SetRemoteDriverStates(drivers, reply, DriverStateControl(DriverStateControl::driverDisabled, reprap.GetGCodes().GetMotorBrakeOnDelay())); } // This one is used by Prepare @@ -945,7 +945,7 @@ void CanInterface::DisableRemoteDrivers(const CanDriversList& drivers) noexcept void CanInterface::SetRemoteDriversIdle(const CanDriversList& drivers, float idleCurrentFactor) noexcept { String<1> dummy; - (void)SetRemoteDriverStates(drivers, dummy.GetRef(), DriverStateControl(DriverStateControl::driverIdle, lrintf(idleCurrentFactor * 100))); + (void)SetRemoteDriverStates(drivers, dummy.GetRef(), DriverStateControl(DriverStateControl::driverIdle, (uint16_t)lrintf(idleCurrentFactor * 100) << 4)); } GCodeResult CanInterface::SetRemoteStandstillCurrentPercent(const CanDriversData<float>& data, const StringRef& reply) noexcept @@ -979,7 +979,7 @@ pre(driver.IsRemote()) case 0: if (gb.SeenAny("RS")) { - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -993,7 +993,7 @@ pre(driver.IsRemote()) case 1: if (gb.SeenAny("STERID")) { - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/CAN/CommandProcessor.cpp b/src/CAN/CommandProcessor.cpp index a430d366..545cc677 100644 --- a/src/CAN/CommandProcessor.cpp +++ b/src/CAN/CommandProcessor.cpp @@ -353,14 +353,17 @@ static GCodeResult EutGetInfo(const CanMessageReturnInfo& msg, const StringRef& extra = LastDiagnosticsPart; { const size_t driver = msg.type - (CanMessageReturnInfo::typeDiagnosticsPart0 + 1); - reply.lcatf("Driver %u: position %" PRIi32 ", %.1f steps/mm" + if (driver < NumDirectDrivers) // we have up to 7 drivers on the Duet 3 Mini but only 6 on the 6HC and 6XD + { + reply.lcatf("Driver %u: position %" PRIi32 ", %.1f steps/mm" #if HAS_SMART_DRIVERS - "," + "," #endif - , driver, reprap.GetMove().GetEndPoint(driver), (double)reprap.GetPlatform().DriveStepsPerUnit(driver)); + , driver, reprap.GetMove().GetEndPoint(driver), (double)reprap.GetPlatform().DriveStepsPerUnit(driver)); #if HAS_SMART_DRIVERS - SmartDrivers::AppendDriverStatus(driver, reply); + SmartDrivers::AppendDriverStatus(driver, reply); #endif + } } break; diff --git a/src/Comms/PanelDueUpdater.cpp b/src/Comms/PanelDueUpdater.cpp index bd381e6d..164bf130 100644 --- a/src/Comms/PanelDueUpdater.cpp +++ b/src/Comms/PanelDueUpdater.cpp @@ -24,8 +24,6 @@ public: SerialPort::StopBit stop = SerialPort::StopBitOne) noexcept override { return true; } void close() noexcept override {} - bool isUsb() noexcept override { return false; } - int read(uint8_t* data, int size) noexcept override; int write(const uint8_t* data, int size) noexcept override { return this->uart.write(data, size); } int get() noexcept override; @@ -33,8 +31,6 @@ public: bool timeout(int millisecs) noexcept override { _timeout = millisecs; return true; } void flush() noexcept override { this->uart.flush(); } - void setDTR(bool dtr) noexcept override {} - void setRTS(bool rts) noexcept override {} private: AsyncSerial& uart; diff --git a/src/Display/ButtonMenuItem.h b/src/Display/ButtonMenuItem.h index 5e723c17..eed53756 100644 --- a/src/Display/ButtonMenuItem.h +++ b/src/Display/ButtonMenuItem.h @@ -15,8 +15,7 @@ class ButtonMenuItem final : public MenuItem { public: - void* operator new(size_t sz) noexcept { return FreelistManager::Allocate<ButtonMenuItem>(); } - void operator delete(void* p) noexcept { FreelistManager::Release<ButtonMenuItem>(p); } + DECLARE_FREELIST_NEW_DELETE(ButtonMenuItem) ButtonMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, FontNumber fn, const char *t, const char *cmd, const char *acFile) noexcept; void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight) noexcept override; diff --git a/src/Display/FilesMenuItem.h b/src/Display/FilesMenuItem.h index 93e4ebc7..1166acad 100644 --- a/src/Display/FilesMenuItem.h +++ b/src/Display/FilesMenuItem.h @@ -15,8 +15,7 @@ class FilesMenuItem final : public MenuItem { public: - void* operator new(size_t sz) noexcept { return FreelistManager::Allocate<FilesMenuItem>(); } - void operator delete(void* p) noexcept { FreelistManager::Release<FilesMenuItem>(p); } + DECLARE_FREELIST_NEW_DELETE(FilesMenuItem) FilesMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, FontNumber fn, const char *_ecv_array cmd, const char *_ecv_array dir, const char *_ecv_array acFile, unsigned int nf) noexcept; void Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight) noexcept override; diff --git a/src/Display/ImageMenuItem.h b/src/Display/ImageMenuItem.h index bc7005f2..fa301190 100644 --- a/src/Display/ImageMenuItem.h +++ b/src/Display/ImageMenuItem.h @@ -15,8 +15,7 @@ class ImageMenuItem final : public MenuItem { public: - void* operator new(size_t sz) noexcept { return FreelistManager::Allocate<ImageMenuItem>(); } - void operator delete(void* p) noexcept { FreelistManager::Release<ImageMenuItem>(p); } + DECLARE_FREELIST_NEW_DELETE(ImageMenuItem) ImageMenuItem(PixelNumber r, PixelNumber c, const char *_ecv_array pFileName) noexcept; diff --git a/src/Display/TextMenuItem.h b/src/Display/TextMenuItem.h index 6e75765f..2da2492b 100644 --- a/src/Display/TextMenuItem.h +++ b/src/Display/TextMenuItem.h @@ -15,8 +15,7 @@ class TextMenuItem final : public MenuItem { public: - void* operator new(size_t sz) noexcept { return FreelistManager::Allocate<TextMenuItem>(); } - void operator delete(void* p) noexcept { FreelistManager::Release<TextMenuItem>(p); } + DECLARE_FREELIST_NEW_DELETE(TextMenuItem) TextMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignment a, FontNumber fn, const char *_ecv_array t) noexcept; void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight) noexcept override; diff --git a/src/Display/ValueMenuItem.h b/src/Display/ValueMenuItem.h index fb22738c..2660bb7e 100644 --- a/src/Display/ValueMenuItem.h +++ b/src/Display/ValueMenuItem.h @@ -17,8 +17,7 @@ class ValueMenuItem final : public MenuItem { public: - void* operator new(size_t sz) noexcept { return FreelistManager::Allocate<ValueMenuItem>(); } - void operator delete(void* p) noexcept { FreelistManager::Release<ValueMenuItem>(p); } + DECLARE_FREELIST_NEW_DELETE(ValueMenuItem) ValueMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignment a, FontNumber fn, bool adj, const char *_ecv_array _ecv_null om, unsigned int v, unsigned int d) noexcept; void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight) noexcept override; diff --git a/src/Endstops/EndstopsManager.cpp b/src/Endstops/EndstopsManager.cpp index feb6b9de..acf8869b 100644 --- a/src/Endstops/EndstopsManager.cpp +++ b/src/Endstops/EndstopsManager.cpp @@ -376,7 +376,7 @@ GCodeResult EndstopsManager::HandleM574(GCodeBuffer& gb, const StringRef& reply, } // If we get here then axes were specified so we are setting endstop parameters - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/Fans/LedStripDriver.cpp b/src/Fans/LedStripDriver.cpp index ccb6ae35..81c2a65a 100644 --- a/src/Fans/LedStripDriver.cpp +++ b/src/Fans/LedStripDriver.cpp @@ -508,7 +508,7 @@ GCodeResult LedStripDriver::SetColours(GCodeBuffer& gb, const StringRef& reply) // Interrupts are disabled while bit-banging data, which will mess up the step timing. So make sure movement has stopped if we are going to use bit-banging if (MustStopMovement(gb)) { - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/GCodes/CollisionAvoider.cpp b/src/GCodes/CollisionAvoider.cpp index 8c5c879e..7e095951 100644 --- a/src/GCodes/CollisionAvoider.cpp +++ b/src/GCodes/CollisionAvoider.cpp @@ -23,12 +23,18 @@ bool CollisionAvoider::IsValid() const noexcept } // Reset the position accumulators -void CollisionAvoider::ResetPositions(const float positions[]) noexcept +void CollisionAvoider::ResetPositions(const float positions[], AxesBitmap whichPositions) noexcept { if (IsValid()) { - lowerAxisMax = positions[lowerAxis]; - upperAxisMin = positions[upperAxis]; + if (whichPositions.IsBitSet(lowerAxis)) + { + lowerAxisMax = positions[lowerAxis]; + } + if (whichPositions.IsBitSet(upperAxis)) + { + upperAxisMin = positions[upperAxis]; + } } } @@ -38,7 +44,8 @@ void CollisionAvoider::Set(int axisL, int axisH, float sep, const float position lowerAxis = axisL; upperAxis = axisH; minSeparation = sep; - ResetPositions(positions); + lowerAxisMax = positions[lowerAxis]; + upperAxisMin = positions[upperAxis]; } bool CollisionAvoider::UpdatePositions(const float axisPositions[]) noexcept diff --git a/src/GCodes/CollisionAvoider.h b/src/GCodes/CollisionAvoider.h index a8fda29e..27f60942 100644 --- a/src/GCodes/CollisionAvoider.h +++ b/src/GCodes/CollisionAvoider.h @@ -25,7 +25,7 @@ public: float GetMinSeparation()const noexcept { return minSeparation; } // Reset the position accumulators - void ResetPositions(const float positions[]) noexcept; + void ResetPositions(const float positions[], AxesBitmap whichPositions) noexcept; // If the new move doesn't risk a collision, update the position accumulators and return true; else return false bool UpdatePositions(const float axisPositions[]) noexcept; diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp index 9c6f9d8f..fbe0ec4c 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.cpp +++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp @@ -26,6 +26,24 @@ void BinaryParser::Init() noexcept gb.bufferState = GCodeBufferState::parseNotStarted; seenParameter = nullptr; seenParameterValue = nullptr; + parametersPresent.Clear(); + if (bufferLength != 0 && header->numParameters != 0) + { + const char *parameterStart = reinterpret_cast<const char*>(gb.buffer) + sizeof(CodeHeader); + for (size_t i = 0; i < header->numParameters; i++) + { + const CodeParameter *param = reinterpret_cast<const CodeParameter*>(parameterStart + i * sizeof(CodeParameter)); + const char paramLetter = param->letter; + if (paramLetter >= 'A' && paramLetter <= 'Z') + { + parametersPresent.SetBit(paramLetter - 'A'); + } + else if (paramLetter >= 'a' && paramLetter <= 'f') + { + parametersPresent.SetBit(paramLetter - ('a' - 26)); + } + } + } } // Add an entire binary G-Code, overwriting any existing content @@ -88,25 +106,6 @@ bool BinaryParser::Seen(char c) noexcept return false; } -// Return true if any of the parameter letters in the bitmap were seen -bool BinaryParser::SeenAny(Bitmap<uint32_t> bm) const noexcept -{ - if (bufferLength != 0 && header->numParameters != 0) - { - const char *parameterStart = reinterpret_cast<const char*>(gb.buffer) + sizeof(CodeHeader); - for (size_t i = 0; i < header->numParameters; i++) - { - const CodeParameter *param = reinterpret_cast<const CodeParameter*>(parameterStart + i * sizeof(CodeParameter)); - const char paramLetter = param->letter; - if (paramLetter >= 'A' && paramLetter <= 'Z' && bm.IsBitSet(paramLetter - 'A')) - { - return true; - } - } - } - return false; -} - char BinaryParser::GetCommandLetter() const noexcept { return (bufferLength != 0) ? header->letter : 'Q'; diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h index 199d1901..76ab98cf 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.h +++ b/src/GCodes/GCodeBuffer/BinaryParser.h @@ -28,7 +28,7 @@ public: void Put(const uint32_t *data, size_t len) noexcept; // Add an entire binary code, overwriting any existing content void DecodeCommand() noexcept; // Print the buffer content in debug mode and prepare for execution bool Seen(char c) noexcept SPEED_CRITICAL; // Is a character present? - bool SeenAny(Bitmap<uint32_t> bm) const noexcept; // Return true if any of the parameter letters in the bitmap were seen + ParameterLettersBitmap AllParameters() const noexcept { return parametersPresent; } // Return the bitmap of all parameters seen char GetCommandLetter() const noexcept; bool HasCommandNumber() const noexcept; @@ -81,6 +81,7 @@ private: const CodeHeader *header; int reducedBytesRead; + ParameterLettersBitmap parametersPresent; const CodeParameter *seenParameter; const char *seenParameterValue; }; diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.cpp b/src/GCodes/GCodeBuffer/ExpressionParser.cpp index fdc112dd..b41a8370 100644 --- a/src/GCodes/GCodeBuffer/ExpressionParser.cpp +++ b/src/GCodes/GCodeBuffer/ExpressionParser.cpp @@ -33,7 +33,7 @@ namespace StackUsage // These can't be declared locally inside ParseIdentifierExpression because NamedEnum includes static data NamedEnum(NamedConstant, unsigned int, _false, iterations, line, _null, pi, _result, _true, input); -NamedEnum(Function, unsigned int, abs, acos, asin, atan, atan2, cos, datetime, degrees, exists, floor, isnan, max, min, mod, radians, random, sin, sqrt, tan); +NamedEnum(Function, unsigned int, abs, acos, asin, atan, atan2, cos, datetime, degrees, fileexists, exists, floor, isnan, max, min, mod, radians, random, sin, sqrt, tan); const char * const InvalidExistsMessage = "invalid 'exists' expression"; @@ -1408,6 +1408,32 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva } break; + case Function::fileexists: + ConvertToString(rslt, evaluate); + { + bool b; + switch (rslt.GetType()) + { + case TypeCode::CString: + b = reprap.GetPlatform().SysFileExists(rslt.sVal); + break; + + case TypeCode::HeapString: + { + ReadLockedPointer<const char> p = rslt.shVal.Get(); + // We assume that calling SysFileExists doesn't need to use the heap, so we are OK keeping the lock around the call and we don't need to copy the string + b = reprap.GetPlatform().SysFileExists(p.Ptr()); + } + break; + + default: + b = false; + break; + } + rslt.SetBool(b); + } + break; + default: THROW_INTERNAL_ERROR; } diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp index 91a7369c..62b64e19 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp @@ -381,7 +381,7 @@ bool GCodeBuffer::IsLaterThan(const GCodeBuffer& other) const noexcept // If the command was or called a macro then there will be no command in the buffer, so we must return true for this case also. bool GCodeBuffer::IsLastCommand() const noexcept { - return IS_BINARY_OR((bufferState != GCodeBufferState::ready && bufferState != GCodeBufferState::executing) || stringParser.IsLastCommand()); + return IS_BINARY_OR((bufferState != GCodeBufferState::ready && bufferState != GCodeBufferState::executing) || stringParser.IsLastCommand()); } bool GCodeBuffer::ContainsExpression() const noexcept @@ -395,10 +395,9 @@ bool GCodeBuffer::Seen(char c) noexcept return PARSER_OPERATION(Seen(c)); } -// Return true if any of the parameter letters in the bitmap were seen -bool GCodeBuffer::SeenAny(Bitmap<uint32_t> bm) const noexcept +ParameterLettersBitmap GCodeBuffer::AllParameters() const noexcept { - return PARSER_OPERATION(SeenAny(bm)); + return PARSER_OPERATION(AllParameters()); } // Test for character present, throw error if not diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.h b/src/GCodes/GCodeBuffer/GCodeBuffer.h index 4fc40cbc..1d653a63 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.h +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.h @@ -76,7 +76,11 @@ public: bool Seen(char c) noexcept SPEED_CRITICAL; // Is a character present? void MustSee(char c) THROWS(GCodeException); // Test for character present, throw error if not char MustSee(char c1, char c2) THROWS(GCodeException); // Test for one of two characters present, throw error if not - inline bool SeenAny(const char *s) const noexcept { return SeenAny(Bitmap<uint32_t>(ParametersToBitmap(s))); } + ParameterLettersBitmap AllParameters() const noexcept; // Return a bitmap of all parameters in the command + bool SeenAny(ParameterLettersBitmap bm) const noexcept // Return true if any of the parameter letters in the bitmap were seen + { return AllParameters().Intersects(bm); } + bool SeenAny(const char *s) const noexcept // Return true if any of the parameter letters in the string were seen + { return SeenAny(ParameterLettersBitmap(ParametersToBitmap(s))); } float GetFValue() THROWS(GCodeException) SPEED_CRITICAL; // Get a float after a key letter float GetPositiveFValue() THROWS(GCodeException) SPEED_CRITICAL; // Get a float after a key letter and check that it is greater than zero @@ -298,8 +302,6 @@ protected: DECLARE_OBJECT_MODEL private: - bool SeenAny(Bitmap<uint32_t> bm) const noexcept; // Return true if any of the parameter letters in the bitmap were seen - // Convert a string of uppercase parameter letters to a bit map static inline constexpr uint32_t ParametersToBitmap(const char *s) noexcept { diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index a57ef337..35f555fa 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -984,40 +984,56 @@ void StringParser::DecodeCommand() noexcept void StringParser::FindParameters() noexcept { bool inQuotes = false; + bool escaped = false; unsigned int localBraceCount = 0; parametersPresent.Clear(); for (commandEnd = parameterStart; commandEnd < gcodeLineEnd; ++commandEnd) { const char c = gb.buffer[commandEnd]; - if (c == '"') + if (c == '\'') { - inQuotes = !inQuotes; + escaped = !inQuotes; } - else if (!inQuotes) + else { - if (c == '{') + if (c == '"') { - ++localBraceCount; + inQuotes = !inQuotes; } - else if (localBraceCount != 0) + else if (!inQuotes) { - if (c == '}') + if (c == '{') { - --localBraceCount; + ++localBraceCount; } - } - else - { - const char c2 = toupper(c); - if ((c2 == 'G' || c2 == 'M') && gb.buffer[commandEnd - 1] != '\'') + else if (localBraceCount != 0) { - break; + if (c == '}') + { + --localBraceCount; + } } - if (c2 >= 'A' && c2 <= 'Z' && (c2 != 'E' || commandEnd == parameterStart || !isdigit(gb.buffer[commandEnd - 1]))) + else { - parametersPresent.SetBit(c2 - 'A'); + const char c2 = toupper(c); + if (escaped) + { + if (c2 >= 'A' && c2 <= 'F' && (c2 != 'E' || commandEnd == parameterStart || !isdigit(gb.buffer[commandEnd - 1]))) + { + parametersPresent.SetBit(c2 - ('A' - 26)); + } + } + else if (c2 == 'G' || c2 == 'M') + { + break; + } + else if (c2 >= 'A' && c2 <= 'Z' && (c2 != 'E' || commandEnd == parameterStart || !isdigit(gb.buffer[commandEnd - 1]))) + { + parametersPresent.SetBit(c2 - 'A'); + } } } + escaped = false; } } } @@ -1109,16 +1125,22 @@ bool StringParser::IsLastCommand() const noexcept return commandEnd >= gcodeLineEnd; // using >= here also covers the case where the buffer is empty and gcodeLineEnd has been set to zero } -// Is 'c' in the G Code string? +// Is 'c' in the G Code string? 'c' must be in A..Z or a..f // Leave the pointer one after it for a subsequent read. bool StringParser::Seen(char c) noexcept { - bool wantLowerCase = (c >= 'a'); + const bool wantLowerCase = (c >= 'a'); + unsigned int bit; if (wantLowerCase) { + bit = c - ('a' - 26); c = toupper(c); } - else if (!parametersPresent.IsBitSet(c - 'A')) + else + { + bit = c - 'A'; + } + if (bit >= ParameterLettersBitmap::MaxBits() || !parametersPresent.IsBitSet(c - 'A')) { return false; } @@ -1166,12 +1188,6 @@ bool StringParser::Seen(char c) noexcept return false; } -// Return true if any of the parameter letters in the bitmap were seen -bool StringParser::SeenAny(Bitmap<uint32_t> bm) const noexcept -{ - return parametersPresent.Intersects(bm); -} - // Get a float after a G Code letter found by a call to Seen() float StringParser::GetFValue() THROWS(GCodeException) { diff --git a/src/GCodes/GCodeBuffer/StringParser.h b/src/GCodes/GCodeBuffer/StringParser.h index 5c9953f8..e3686506 100644 --- a/src/GCodes/GCodeBuffer/StringParser.h +++ b/src/GCodes/GCodeBuffer/StringParser.h @@ -44,15 +44,15 @@ public: bool IsLastCommand() const noexcept; bool ContainsExpression() const noexcept { return seenExpression; } - bool Seen(char c) noexcept SPEED_CRITICAL; // Is a character present? - bool SeenAny(Bitmap<uint32_t> bm) const noexcept; // Return true if any of the parameter letters in the bitmap were seen - float GetFValue() THROWS(GCodeException) SPEED_CRITICAL; // Get a float after a key letter - float GetDistance() THROWS(GCodeException) SPEED_CRITICAL; // Get a distance or coordinate and convert it from inches to mm if necessary - int32_t GetIValue() THROWS(GCodeException) SPEED_CRITICAL; // Get an integer after a key letter - uint32_t GetUIValue() THROWS(GCodeException); // Get an unsigned integer value - DriverId GetDriverId() THROWS(GCodeException); // Get a driver ID - void GetIPAddress(IPAddress& returnedIp) THROWS(GCodeException); // Get an IP address quad after a key letter - void GetMacAddress(MacAddress& mac) THROWS(GCodeException); // Get a MAC address sextet after a key letter + bool Seen(char c) noexcept SPEED_CRITICAL; // Is a character present? + ParameterLettersBitmap AllParameters() const noexcept { return parametersPresent; } // Return the bitmap of all parameters seen + float GetFValue() THROWS(GCodeException) SPEED_CRITICAL; // Get a float after a key letter + float GetDistance() THROWS(GCodeException) SPEED_CRITICAL; // Get a distance or coordinate and convert it from inches to mm if necessary + int32_t GetIValue() THROWS(GCodeException) SPEED_CRITICAL; // Get an integer after a key letter + uint32_t GetUIValue() THROWS(GCodeException); // Get an unsigned integer value + DriverId GetDriverId() THROWS(GCodeException); // Get a driver ID + void GetIPAddress(IPAddress& returnedIp) THROWS(GCodeException); // Get an IP address quad after a key letter + void GetMacAddress(MacAddress& mac) THROWS(GCodeException); // Get a MAC address sextet after a key letter void GetUnprecedentedString(const StringRef& str, bool allowEmpty) THROWS(GCodeException); // Get a string with no preceding key letter void GetCompleteParameters(const StringRef& str) const noexcept; // Get the complete parameter string void GetQuotedString(const StringRef& str, bool allowEmpty) THROWS(GCodeException); // Get and copy a quoted string @@ -135,7 +135,7 @@ private: unsigned int commandLength; // Number of characters we read to build this command including the final \r or \n unsigned int braceCount; // how many nested { } we are inside unsigned int gcodeLineEnd; // Number of characters in the entire line of gcode - Bitmap<uint32_t> parametersPresent; // which parameters are present in this command + ParameterLettersBitmap parametersPresent; // which parameters are present in this command int readPointer; // Where in the buffer to read next, or -1 FileStore *fileBeingWritten; // If we are copying GCodes to a file, which file it is diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index ee813e0e..6d5d58e0 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -174,6 +174,9 @@ void GCodes::Init() noexcept axisLetters[0] = 'X'; axisLetters[1] = 'Y'; axisLetters[2] = 'Z'; +#if SUPPORT_ASYNC_MOVES + allAxisLetters = ParameterLettersBitmap((1u << ('X'-'A')) | (1u << ('Y'-'A')) | (1u << ('Z'-'A'))); +#endif numExtruders = 0; @@ -197,8 +200,6 @@ void GCodes::Init() noexcept laserMaxPower = DefaultMaxLaserPower; laserPowerSticky = false; - heaterFaultTimeout = DefaultHeaterFaultTimeout; - #if SUPPORT_SCANNER reprap.GetScanner().SetGCodeBuffer(UsbGCode()); #endif @@ -256,10 +257,18 @@ void GCodes::Reset() noexcept g68Angle = g68Centre[0] = g68Centre[1] = 0.0; // no coordinate rotation #endif +#if SUPPORT_ASYNC_MOVES + reprap.GetMove().GetKinematics().GetAssumedInitialPosition(numVisibleAxes, lastKnownMachinePositions); +#endif + for (MovementState& ms : moveStates) { ms.Reset(); +#if SUPPORT_ASYNC_MOVES + memcpyf(ms.coords, lastKnownMachinePositions, numVisibleAxes); +#else reprap.GetMove().GetKinematics().GetAssumedInitialPosition(numVisibleAxes, ms.coords); +#endif ToolOffsetInverseTransform(ms); } @@ -608,12 +617,22 @@ bool GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) noexcept { if (gb.IsFileFinished()) { - if (!LockMovementAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up + const bool printFileFinished = (gb.LatestMachineState().GetPrevious() == nullptr); +# if SUPPORT_ASYNC_MOVES + if (printFileFinished) { - return false; + DoSync(gb); // wait until the other input stream has caught up + } + else +# endif + { + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up + { + return false; + } } - if (gb.LatestMachineState().GetPrevious() == nullptr) + if (printFileFinished) { // Finished printing SD card file. // We never get here if the file ends in M0 because CancelPrint gets called directly in that case. @@ -747,14 +766,24 @@ bool GCodes::DoFilePrint(GCodeBuffer& gb, const StringRef& reply) noexcept return true; } - gb.Init(); // mark buffer as empty + gb.Init(); // mark buffer as empty - if (!LockMovementAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up + const bool printFileFinished = (gb.LatestMachineState().GetPrevious() == nullptr); +# if SUPPORT_ASYNC_MOVES + if (printFileFinished) { - return false; + DoSync(gb); // wait until the other input stream has caught up + } + else +# endif + { + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up + { + return false; + } } - if (gb.LatestMachineState().GetPrevious() == nullptr) + if (printFileFinished) { // Finished printing SD card file. // We never get here if the file ends in M0 because CancelPrint gets called directly in that case. @@ -874,7 +903,7 @@ void GCodes::DoEmergencyStop() noexcept bool GCodes::DoSynchronousPause(GCodeBuffer& gb, PrintPausedReason reason, GCodeState newState) noexcept { // Pausing because of a command in the file itself - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -1495,22 +1524,47 @@ void GCodes::Diagnostics(MessageType mtype) noexcept } } +#if SUPPORT_ASYNC_MOVES + +// Lock the movement system that we currently use and wait for it to stop +bool GCodes::LockCurrentMovementSystemAndWaitForStandstill(GCodeBuffer& gb) noexcept +{ + return LockMovementSystemAndWaitForStandstill(gb, gb.GetActiveQueueNumber()); +} + +// Lock all movement systems and wait for them to stop +bool GCodes::LockAllMovementSystemsAndWaitForStandstill(GCodeBuffer& gb) noexcept +{ + unsigned int i = 0; + while (LockMovementSystemAndWaitForStandstill(gb, i)) + { + ++i; + if (i == NumMovementSystems) + { + return true; + } + } + + // We failed to lock the ith movement system. To avoid possible deadlock we need to release any later locks that we have. + UnlockMovementFrom(gb, i + 1); + return false; +} + +#endif + // Lock movement and wait for pending moves to finish. // Return true if successful, false if we need to try again later. // As a side-effect it updates the user coordinates from the machine coordinates. -bool GCodes::LockMovementAndWaitForStandstill(GCodeBuffer& gb -#if SUPPORT_ASYNC_MOVES - , bool sync -#endif - ) noexcept + +bool GCodes::LockMovementSystemAndWaitForStandstill(GCodeBuffer& gb, unsigned int msNumber) noexcept { // Lock movement to stop another source adding moves to the queue - if (!LockMovement(gb)) + if (!LockResource(gb, MoveResourceBase + msNumber)) { return false; } - MovementState& ms = GetMovementState(gb); + MovementState& ms = moveStates[msNumber]; if (ms.segmentsLeft != 0) // has the last move generated been fully transferred to the movement queue? { return false; // if no @@ -1522,71 +1576,16 @@ bool GCodes::LockMovementAndWaitForStandstill(GCodeBuffer& gb case GCodeChannel::Queue2: break; -#if SUPPORT_ASYNC_MOVES - case GCodeChannel::File: - if (!reprap.GetMove().WaitingForAllMovesFinished(0)) - { - return false; - } - if (!(QueuedGCode()->IsIdle() && moveStates[0].codeQueue->IsIdle())) - { - return false; - } - - // Now that we know that pending commands for this queue are completed, we can try to sync with other GCode buffers - if (sync && !gb.ExecutingAll() && File2GCode()->IsDoingFile()) - { - const bool ret = SyncWith(gb, *File2GCode()); - if (ret) - { - gb.MotionStopped(); - } - //if (!ret) { debugPrintf("Lock wait 7, queue %u\n", gb.GetQueueNumberToLock()); } - return ret; - } - break; - - case GCodeChannel::File2: - if (!reprap.GetMove().WaitingForAllMovesFinished(1)) - { - return false; - } - if (!(Queue2GCode()->IsIdle() && moveStates[1].codeQueue->IsIdle())) - { - return false; - } - - // Now that we know that pending commands for this queue are completed, we can try to sync with other GCode buffers - if (sync && !gb.ExecutingAll() && FileGCode()->IsDoingFile()) - { - const bool ret = SyncWith(gb, *FileGCode()); - if (ret) - { - gb.MotionStopped(); - } - return ret; - } - break; -#endif - default: - if ( !reprap.GetMove().WaitingForAllMovesFinished(0) -#if SUPPORT_ASYNC_MOVES - || !reprap.GetMove().WaitingForAllMovesFinished(1) -#endif - ) + if (!reprap.GetMove().WaitingForAllMovesFinished(msNumber)) { return false; } - - if ( !(QueuedGCode()->IsIdle() && moveStates[0].codeQueue->IsIdle()) -#if SUPPORT_ASYNC_MOVES - && !(Queue2GCode()->IsIdle() && moveStates[1].codeQueue->IsIdle()) -#endif - ) + if (!(QueuedGCode()->IsIdle() && moveStates[msNumber].codeQueue->IsIdle())) { return false; } + break; } gb.MotionStopped(); // must do this after we have finished waiting, so that we don't stop waiting when executing G4 @@ -1597,23 +1596,17 @@ bool GCodes::LockMovementAndWaitForStandstill(GCodeBuffer& gb #if SUPPORT_ASYNC_MOVES // Get the position of all axes by combining positions from the queues Move& move = reprap.GetMove(); - float coords[MaxAxes]; - move.GetPartialMachinePosition(coords, AxesBitmap::MakeLowestNBits(numTotalAxes), 0); - move.GetPartialMachinePosition(coords, moveStates[1].axesAndExtrudersOwned, 1); - memcpyf(moveStates[0].coords, coords, MaxAxes); - memcpyf(moveStates[1].coords, coords, MaxAxes); - move.InverseAxisAndBedTransform(moveStates[0].coords, moveStates[0].currentTool); - move.InverseAxisAndBedTransform(moveStates[1].coords, moveStates[1].currentTool); - UpdateUserPositionFromMachinePosition(gb, moveStates[0]); //TODO problem when using coordinate rotation! - UpdateUserPositionFromMachinePosition(gb, moveStates[1]); - move.SetNewPosition(coords, true, 0); - move.SetNewPosition(coords, true, 1); - - // Release all axes and extruders - axesAndExtrudersMoved.Clear(); - moveStates[0].axesAndExtrudersOwned.Clear(); - moveStates[1].axesAndExtrudersOwned.Clear(); - collisionChecker.ResetPositions(moveStates[0].coords); + const AxesBitmap ownedAxes = moveStates[msNumber].axesAndExtrudersOwned; + move.GetPartialMachinePosition(lastKnownMachinePositions, ownedAxes, msNumber); + memcpyf(moveStates[msNumber].coords, lastKnownMachinePositions, MaxAxes); + move.InverseAxisAndBedTransform(lastKnownMachinePositions, moveStates[msNumber].currentTool); + UpdateUserPositionFromMachinePosition(gb, moveStates[msNumber]); + collisionChecker.ResetPositions(lastKnownMachinePositions, ownedAxes); + + // Release the axes and extruders that this movement system owns + axesAndExtrudersMoved.ClearBits(ownedAxes); + moveStates[msNumber].axesAndExtrudersOwned.Clear(); + ms.ownedAxisLetters.Clear(); #else UpdateCurrentUserPosition(gb); #endif @@ -1844,6 +1837,18 @@ bool GCodes::CheckEnoughAxesHomed(AxesBitmap axesToMove) noexcept bool GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) THROWS(GCodeException) { MovementState& ms = GetMovementState(gb); + +#if SUPPORT_ASYNC_MOVES + // We need to check for moving unowned axes right at the start in case we need to fetch axis positions before processing the command + ParameterLettersBitmap axisLettersMentioned = gb.AllParameters() & allAxisLetters; + axisLettersMentioned.ClearBits(ms.ownedAxisLetters); + if (axisLettersMentioned.IsNonEmpty()) + { + //TODO problem! this ignores axis mapping and coordinate rotation!!! + AllocateAxisLetters(gb, ms, axisLettersMentioned); + } +#endif + if (ms.moveFractionToSkip > 0.0) { ms.initialUserC0 = ms.restartInitialUserC0; @@ -1872,7 +1877,7 @@ bool GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) THROWS(GCodeExc const int ival = gb.GetIValue(); if (ival >= 1 && ival <= 4) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -2679,7 +2684,7 @@ void GCodes::FinaliseMove(GCodeBuffer& gb, MovementState& ms) noexcept // But the expected position was saved by buildObjects when the state changed from printing a cancelled object to printing a live object. bool GCodes::TravelToStartPoint(GCodeBuffer& gb) noexcept { - if (!LockMovementAndWaitForStandstill(gb)) // update the user position from the machine position + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // update the user position from the machine position { return false; } @@ -3232,7 +3237,7 @@ GCodeResult GCodes::DoDwell(GCodeBuffer& gb) THROWS(GCodeException) // This is so that G4 can be used in a trigger or daemon macro file without pausing motion, when the macro doesn't itself command any motion. if (gb.WasMotionCommanded()) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -3542,7 +3547,7 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) if (seen) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -4725,57 +4730,57 @@ bool GCodes::LockFileSystem(const GCodeBuffer &gb) noexcept return LockResource(gb, FileSystemResource); } +#if SUPPORT_ASYNC_MOVES + // The movement lock is special because we have one for each motion system -// Lock movement + +// Lock the movement system that we currently use bool GCodes::LockMovement(const GCodeBuffer& gb) noexcept { -#if SUPPORT_ASYNC_MOVES - return LockResource(gb, MoveResourceBase + gb.GetQueueNumberToLock()); -#else - return LockResource(gb, MoveResourceBase); -#endif + return LockMovement(gb, gb.GetQueueNumberToLock()); } // Lock movement on all motion systems bool GCodes::LockAllMovement(const GCodeBuffer& gb) noexcept { -#if SUPPORT_ASYNC_MOVES - for (Resource r = MoveResourceBase; r < MoveResourceBase + NumMovementSystems; ++r) + for (unsigned int i = 0; i < NumMovementSystems; ++i) { - if (!LockResource(gb, r)) + if (!LockMovement(gb, i)) { + UnlockMovementFrom(gb, i + 1); // release any higher locks we own to avoid deadlock return false; } } return true; -#else - return LockMovement(gb); -#endif } -// Grab the movement lock even if another channel owns it -void GCodes::GrabMovement(const GCodeBuffer& gb) noexcept +// Release movement locks greater than the specified one +void GCodes::UnlockMovementFrom(const GCodeBuffer& gb, unsigned int msNumber) noexcept { -#if SUPPORT_ASYNC_MOVES - GrabResource(gb, MoveResourceBase + gb.GetQueueNumberToLock()); -#else - GrabResource(gb, MoveResourceBase); -#endif + while (msNumber < NumMovementSystems) + { + UnlockMovement(gb, msNumber); + ++msNumber; + } } -// Release the movement lock +// Release all movement locks that we own void GCodes::UnlockMovement(const GCodeBuffer& gb) noexcept { -#if SUPPORT_ASYNC_MOVES - for (Resource r = MoveResourceBase; r < MoveResourceBase + NumMovementSystems; ++r) + UnlockMovementFrom(gb, 0); +} + +// Grab all movement locks even if other channels owns them +void GCodes::GrabMovement(const GCodeBuffer& gb) noexcept +{ + for (unsigned int i = 0; i < NumMovementSystems; ++i) { - UnlockResource(gb, r); + GrabResource(gb, MoveResourceBase + i); } -#else - UnlockResource(gb, MoveResourceBase); -#endif } +#endif + // Unlock the resource if we own it void GCodes::UnlockResource(const GCodeBuffer& gb, Resource r) noexcept { @@ -4921,7 +4926,7 @@ const MovementState& GCodes::GetCurrentMovementState(const ObjectExplorationCont return GetConstMovementState(*gb); } -// Allocate an axis to a movement state returning true if successful, false if another movement state owns it already +// Allocate additional axes and/or extruders to a movement state returning true if successful, false if another movement state owns it already // This relies on cooperative scheduling between different GCodeBuffer objects void GCodes::AllocateAxes(const GCodeBuffer& gb, MovementState& ms, AxesBitmap axes) THROWS(GCodeException) { @@ -4933,11 +4938,32 @@ void GCodes::AllocateAxes(const GCodeBuffer& gb, MovementState& ms, AxesBitmap a ms.axesAndExtrudersOwned |= axes; } +// Allocate additional axes by letter +void GCodes::AllocateAxisLetters(const GCodeBuffer& gb, MovementState& ms, ParameterLettersBitmap axLetters) THROWS(GCodeException) +{ + AxesBitmap newAxes; + for (size_t axis = 0; axis < numVisibleAxes; ++axis) + { + const char c = axisLetters[axis]; + const unsigned int axisLetterBit = (c >= 'a') ? c - ('a' - 26) : c - 'A'; + if (axLetters.IsBitSet(axisLetterBit)) + { + newAxes.SetBit(axis); + } + } + AllocateAxes(gb, ms, newAxes); + ms.ownedAxisLetters |= axLetters; +} + // Synchronise motion systems and update user coordinates. -// This is called after we have checked that the motion system for thisGb has completed all moves. // Return true if synced, false if we need to wait longer. bool GCodes::SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept { + if (!LockCurrentMovementSystemAndWaitForStandstill(thisGb)) + { + return false; + } + switch (thisGb.syncState) { case GCodeBuffer::SyncState::running: @@ -4950,7 +4976,7 @@ bool GCodes::SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept if (otherGb.IsLaterThan(thisGb)) { // Other input channel has skipped this sync point - UpdateUserCoordinatesAndReleaseOwnedAxes(thisGb, otherGb); // it's arguable whether updating machine coordinates from the other channel is worth doing here + UpdateAllCoordinates(thisGb); thisGb.syncState = GCodeBuffer::SyncState::running; return true; } @@ -4959,7 +4985,7 @@ bool GCodes::SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept } // If we get here then the other input channel is also syncing, so it's safe to use the machine axis coordinates of the axes it owns to update our user coordinates - UpdateUserCoordinatesAndReleaseOwnedAxes(thisGb, otherGb); + UpdateAllCoordinates(thisGb); // Now that we no longer need to read axis coordinates from the other motion system, flag that we have finished syncing thisGb.syncState = GCodeBuffer::SyncState::synced; @@ -4984,7 +5010,7 @@ bool GCodes::SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept thisGb.syncState = GCodeBuffer::SyncState::running; return true; } - // We are not the primary, so wait for the other onput channel to complete the current command + // We are not the primary, so wait for the other output channel to complete the current command return otherGb.IsLaterThan(thisGb); } } @@ -4992,22 +5018,22 @@ bool GCodes::SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept return false; // unreachable code, to keep Eclipse happy } -void GCodes::UpdateUserCoordinatesAndReleaseOwnedAxes(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept +// Synchronise the other motion system with this one. Return true if done, false if we need to wait for it to catch up. +bool GCodes::DoSync(GCodeBuffer& gb) noexcept { - // Get the position of all axes by combining positions from the queues - const MovementState& otherMs = GetConstMovementState(otherGb); - Move& move = reprap.GetMove(); - float coords[MaxAxes]; - move.GetPartialMachinePosition(coords, AxesBitmap::MakeLowestNBits(numTotalAxes), thisGb.GetOwnQueueNumber()); - move.GetPartialMachinePosition(coords, otherMs.axesAndExtrudersOwned, otherGb.GetOwnQueueNumber()); - MovementState& thisMs = GetMovementState(thisGb); - move.InverseAxisAndBedTransform(coords, thisMs.currentTool); - UpdateUserPositionFromMachinePosition(thisGb, thisMs); - move.SetNewPosition(coords, true, thisGb.GetOwnQueueNumber()); + const bool rslt = (&gb == FileGCode()) ? SyncWith(gb, *File2GCode()) + : (&gb == File2GCode()) ? SyncWith(gb, *FileGCode()) + : true; + return rslt; +} - // Release all axes and extruders that we were using - axesAndExtrudersMoved &= ~thisMs.axesAndExtrudersOwned; - thisMs.axesAndExtrudersOwned.Clear(); +void GCodes::UpdateAllCoordinates(GCodeBuffer& gb) noexcept +{ + const unsigned int msNumber = gb.GetOwnQueueNumber(); + memcpyf(moveStates[msNumber].coords, lastKnownMachinePositions, MaxAxes); + reprap.GetMove().InverseAxisAndBedTransform(moveStates[msNumber].coords, moveStates[msNumber].currentTool); + UpdateUserPositionFromMachinePosition(gb, moveStates[msNumber]); + reprap.GetMove().SetNewPosition(moveStates[msNumber].coords, true, msNumber); } #endif diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index df8ece5c..c5118440 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -187,12 +187,11 @@ public: const char *GetAxisLetters() const noexcept { return axisLetters; } // Return a null-terminated string of axis letters indexed by drive size_t GetAxisNumberForLetter(const char axisLetter) const noexcept; MachineType GetMachineType() const noexcept { return machineType; } - bool LockMovementAndWaitForStandstill(GCodeBuffer& gb -#if SUPPORT_ASYNC_MOVES - , bool sync = true -#endif - ) noexcept; // Lock movement and wait for pending moves to finish - bool LockMovementAndWaitForStandstillNoSync(GCodeBuffer& gb) noexcept; // Lock movement and wait for pending moves to finish but don't sync if using multiple movement queues + bool LockMovementSystemAndWaitForStandstill(GCodeBuffer& gb, unsigned int msNumber) noexcept; // Lock a movement system and wait for pending moves to finish + bool LockCurrentMovementSystemAndWaitForStandstill(GCodeBuffer& gb) noexcept; // Lock movement and wait for pending moves to finish + bool LockAllMovementSystemsAndWaitForStandstill(GCodeBuffer& gb) noexcept; // Lock movement and wait for all motion systems to reach standstill + uint16_t GetMotorBrakeOnDelay() const noexcept { return 200; } // Get the delay between brake on and motors off, in milliseconds TODO make this configurable + uint16_t GetMotorBrakeOffDelay() const noexcept { return 25; } // Get the delay between motors on and brake off, in milliseconds #if SUPPORT_DIRECT_LCD void SetPrimarySpeedFactor(float factor) noexcept; // Set the speed factor @@ -290,7 +289,7 @@ public: void SetRemotePrinting(bool isPrinting) noexcept { isRemotePrinting = isPrinting; } #endif - static constexpr const char *AllowedAxisLetters = "XYZUVWABCDabcdefghijkl"; + static constexpr const char *AllowedAxisLetters = "XYZUVWABCDabcdef"; // Standard macro filenames #define DEPLOYPROBE "deployprobe" @@ -342,12 +341,17 @@ private: bool LockResource(const GCodeBuffer& gb, Resource r) noexcept; // Lock the resource, returning true if success bool LockFileSystem(const GCodeBuffer& gb) noexcept; // Lock the unshareable parts of the file system - bool LockMovement(const GCodeBuffer& gb) noexcept; // Lock movement - bool LockAllMovement(const GCodeBuffer& gb) noexcept; // Lock movement on all queues + bool LockMovement(const GCodeBuffer& gb) noexcept; // Lock the movement system we are using + bool LockMovement(const GCodeBuffer& gb, unsigned int msNumber) noexcept; // Lock a particular movement system + bool LockAllMovement(const GCodeBuffer& gb) noexcept; // Lock all movement systems void GrabResource(const GCodeBuffer& gb, Resource r) noexcept; // Grab a resource even if it is already owned - void GrabMovement(const GCodeBuffer& gb) noexcept; // Grab the movement lock even if it is already owned + void GrabMovement(const GCodeBuffer& gb) noexcept; // Grab all movement locks even if they are already owned void UnlockResource(const GCodeBuffer& gb, Resource r) noexcept; // Unlock the resource if we own it - void UnlockMovement(const GCodeBuffer& gb) noexcept; // Unlock the movement resource if we own it + void UnlockMovement(const GCodeBuffer& gb) noexcept; // Unlock the movement system we are using, if we own it + void UnlockMovement(const GCodeBuffer& gb, unsigned int msNumber) noexcept; // Unlock a particular movement system, if we own it +#if SUPPORT_ASYNC_MOVES + void UnlockMovementFrom(const GCodeBuffer& gb, unsigned int firstMsNumber) noexcept; // Release movement locks greater or equal to than the specified one +#endif bool SpinGCodeBuffer(GCodeBuffer& gb) noexcept; // Do some work on an input channel bool StartNextGCode(GCodeBuffer& gb, const StringRef& reply) noexcept; // Fetch a new or old GCode and process it @@ -546,11 +550,16 @@ private: MovementState& GetMovementState(const GCodeBuffer& gb) noexcept; // Get a reference to the movement state associated with the specified GCode buffer #if SUPPORT_ASYNC_MOVES - GCodeResult SelectMovementQueue(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M596 - GCodeResult CollisionAvoidance(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M597 + GCodeResult SelectMovementQueue(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M596 + GCodeResult CollisionAvoidance(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M597 + GCodeResult SyncMovementSystems(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M598 + GCodeResult ExecuteM400(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException); // Handle M400 void AllocateAxes(const GCodeBuffer& gb, MovementState& ms, AxesBitmap axes) THROWS(GCodeException); // allocate axes to a movement state - bool SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept; // synchronise motion systems - void UpdateUserCoordinatesAndReleaseOwnedAxes(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept; + void AllocateAxisLetters(const GCodeBuffer& gb, MovementState& ms, ParameterLettersBitmap axLetters) THROWS(GCodeException); + // allocate axes by letter + bool DoSync(GCodeBuffer& gb) noexcept; // sync with the other stream returning true if done, false if we need to wait for it + bool SyncWith(GCodeBuffer& thisGb, const GCodeBuffer& otherGb) noexcept; // synchronise motion systems + void UpdateAllCoordinates(GCodeBuffer& gb) noexcept; #endif #if SUPPORT_COORDINATE_ROTATION @@ -642,6 +651,9 @@ private: FileData fileToPrint; // The next file to print #endif +#if SUPPORT_ASYNC_MOVES + ParameterLettersBitmap allAxisLetters; // Which axis letters are in use +#endif char axisLetters[MaxAxes + 1]; // The names of the axes, with a null terminator bool limitAxes; // Don't think outside the box bool noMovesBeforeHoming; // Don't allow movement prior to homing the associates axes @@ -706,9 +718,6 @@ private: float laserMaxPower; bool laserPowerSticky; // true if G1 S parameters are remembered across G1 commands - // Heater fault handler - uint32_t heaterFaultTimeout; // how long we wait for the user to fix it before turning everything off - // Object cancellation ObjectTracker buildObjects; @@ -719,6 +728,7 @@ private: #if SUPPORT_ASYNC_MOVES AxesBitmap axesAndExtrudersMoved; // axes and extruders that have moved since the last sync CollisionAvoider collisionChecker; + float lastKnownMachinePositions[MaxAxes]; #endif #if HAS_MASS_STORAGE @@ -753,18 +763,28 @@ inline float GCodes::GetTotalBabyStepOffset(size_t axis) const noexcept return currentBabyStepOffsets[axis]; } -#if SUPPORT_ASYNC_MOVES +// Lock a particular movement system +inline bool GCodes::LockMovement(const GCodeBuffer& gb, unsigned int msNumber) noexcept +{ + return LockResource(gb, MoveResourceBase + msNumber); +} -inline bool GCodes::LockMovementAndWaitForStandstillNoSync(GCodeBuffer& gb) noexcept +// Unlock a particular movement system, if we own it +inline void GCodes::UnlockMovement(const GCodeBuffer& gb, unsigned int msNumber) noexcept { - return LockMovementAndWaitForStandstill(gb, false); + return UnlockResource(gb, MoveResourceBase + msNumber); } -#else +#if !SUPPORT_ASYNC_MOVES + +inline bool GCodes::LockCurrentMovementSystemAndWaitForStandstill(GCodeBuffer& gb) noexcept +{ + return LockMovementSystemAndWaitForStandstill(gb, 0); +} -inline bool GCodes::LockMovementAndWaitForStandstillNoSync(GCodeBuffer& gb) noexcept +inline bool GCodes::LockAllMovementSystemsAndWaitForStandstill(GCodeBuffer& gb) noexcept { - return LockMovementAndWaitForStandstill(gb); + return LockMovementSystemAndWaitForStandstill(gb, 0); } // Get a reference to the movement state associated with the specified GCode buffer @@ -783,6 +803,30 @@ inline const MovementState& GCodes::GetCurrentMovementState(const ObjectExplorat return moveStates[0]; } +// Lock the movement system we are using +inline bool GCodes::LockMovement(const GCodeBuffer& gb) noexcept +{ + return LockResource(gb, MoveResourceBase); +} + +// Lock all movement systems +inline bool GCodes::LockAllMovement(const GCodeBuffer& gb) noexcept +{ + return LockResource(gb, MoveResourceBase); +} + +// Unlock the movement system we are using, if we own it +inline void GCodes::UnlockMovement(const GCodeBuffer& gb) noexcept +{ + return UnlockResource(gb, MoveResourceBase); +} + +// Grab all movement locks even if they are already owned +inline void GCodes::GrabMovement(const GCodeBuffer& gb) noexcept +{ + GrabResource(gb, MoveResourceBase); +} + #endif //***************************************************************************************************** diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 11abc249..8b0f75ed 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -285,7 +285,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 17: // Select XY plane for G2/G3 case 18: // Select XZ plane case 19: // Select YZ plane - if (!LockMovementAndWaitForStandstill(gb)) // do this in case a G2 or G3 command is in progress + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // do this in case a G2 or G3 command is in progress { return false; } @@ -301,7 +301,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 28: // Home - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -310,7 +310,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 29: // Grid-based bed probing - if (!LockMovementAndWaitForStandstill(gb)) // do this first to make sure that a new grid isn't being defined + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // do this first to make sure that a new grid isn't being defined { return false; } @@ -375,7 +375,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 30: // Z probe/manually set at a position and set that as point P - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -398,7 +398,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 32: // Probe Z at multiple positions and generate the bed transform - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -414,7 +414,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 38: // Straight probe - move until either the probe is triggered or the commanded move ends - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -464,12 +464,12 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; #if SUPPORT_COORDINATE_ROTATION - case 68: + case 68: // Coordinate rotation result = HandleG68(gb, reply); break; - case 69: - if (!LockMovementAndWaitForStandstill(gb)) + case 69: // Cancel coordinate rotation + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -557,34 +557,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // These commands are executed by all GCode processors, at least to start with break; - case 17: - case 18: - case 81: - case 84: - case 190: - case 191: - case 206: - case 375: - case 451: - case 452: - case 453: - case 561: - case 574: - case 665: - case 666: - case 669: - case 671: - case 918: - // These commands cause synchronisation but are then executed by just the primary processor. The code to implement the command also calls LockMovementAndWaitForStandstill. - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - // no break default: // All remaining commands are executed by the primary processor only HandleReply(gb, GCodeResult::ok, ""); - return true; // we don't simulate most M codes + return true; } } #endif @@ -658,10 +634,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (gb.IsFileChannel()) { // Stopping a job because of a command in the file - if (!LockMovementAndWaitForStandstill(gb)) // wait until everything has stopped and deferred command queue has caught up +#if SUPPORT_ASYNC_MOVES + if (!DoSync(gb)) + { + return false; + } +#else + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until everything has stopped and deferred command queue has caught up { return false; } +#endif if (&gb == FileGCode()) { isWaiting = cancelWait = false; // we may have been waiting for temperatures to be reached @@ -671,7 +654,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx else if (pauseState == PauseState::paused) { // Cancelling a print that has been paused - if (!LockMovementAndWaitForStandstill(gb)) // make sure everything has stopped + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) // make sure everything has stopped { return false; } @@ -808,7 +791,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 17: // Motors on case 18: // Motors off case 84: - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -995,7 +978,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; } - if (code == 32 && !LockMovementAndWaitForStandstill(gb)) + if (code == 32 && !LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -1045,7 +1028,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } else { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -1442,7 +1425,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 81: // ATX power off - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -1478,7 +1461,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { if (gb.Seen(axisLetters[axis])) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -1492,7 +1475,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (gb.Seen(extrudeLetter)) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -1669,7 +1652,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx MoveResourceBase #endif ); - if (!LockMovementAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution { return false; } @@ -1738,7 +1721,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (code == 109 && ms.currentTool == nullptr) { // Switch to the tool - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } @@ -1893,7 +1876,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 116: // Wait for set temperatures - if (!LockMovementAndWaitForStandstillNoSync(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution { return false; } @@ -2228,7 +2211,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 190: // Set bed temperature and wait case 191: // Set chamber temperature and wait - if (!LockMovementAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait until movement has finished and deferred command queue has caught up to avoid out-of-order execution { return false; } @@ -2731,7 +2714,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx bool seen = false; if (gb.Seen('P')) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2740,7 +2723,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } if (gb.Seen('S')) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2749,7 +2732,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx } if (gb.Seen('R')) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2810,7 +2793,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { if (gb.Seen(axisLetters[axis])) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2832,7 +2815,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (gb.Seen(extrudeLetter)) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2885,7 +2868,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 375: // Load grid and height map from file and enable compensation - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -2912,10 +2895,14 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 400: // Wait for current moves to finish - if (!LockMovementAndWaitForStandstill(gb)) +#if SUPPORT_ASYNC_MOVES + result = ExecuteM400(gb, reply); +#else + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } +#endif break; case 401: // Deploy Z probe @@ -3012,7 +2999,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 451: // Select FFF printer mode - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3025,7 +3012,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #if SUPPORT_LASER case 452: // Select laser mode - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3060,7 +3047,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #endif case 453: // Select CNC mode - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3131,7 +3118,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 502: // Revert to default "factory settings" ignoring values in config-override.g if (!gb.LatestMachineState().runningM502) // avoid recursion { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3196,7 +3183,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (gb.Seen('P')) { // Lock movement to try to prevent other threads opening system files while we change the system path - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3431,7 +3418,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #endif case 561: // Set identity transform and disable height map - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3580,23 +3567,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 570: // Set/report heater monitoring - { - bool seen = false; - if (gb.Seen('S')) - { - seen = true; - heaterFaultTimeout = gb.GetUIValue() * (60 * 1000); - } - if (gb.Seen('H')) - { - seen = true; - result = reprap.GetHeat().ConfigureHeaterMonitoring(gb.GetUIValue(), gb, reply); - } - if (!seen) - { - reply.printf("Print will be terminated if a heater fault is not reset within %" PRIu32 " minutes", heaterFaultTimeout/(60 * 1000)); - } - } + gb.MustSee('H'); + result = reprap.GetHeat().ConfigureHeaterMonitoring(gb.GetUIValue(), gb, reply); break; case 571: // Set output on extrude @@ -3610,11 +3582,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // case 573 was report heater average PWM but is no longer supported because you can use "echo heat/heaters[N].avgPwm" instead case 574: // Set endstop configuration - // We may be about to delete endstops, so make sure we are not executing a move that uses them - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } result = platform.GetEndstops().HandleM574(gb, reply, outBuf); break; @@ -3878,6 +3845,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 597: // Collision avoidance result = CollisionAvoidance(gb, reply); break; + + case 598: // Sync + result = SyncMovementSystems(gb, reply); + break; #endif // For cases 600 and 601, see 226 @@ -3885,7 +3856,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #if SUPPORT_LINEAR_DELTA case 665: // Set delta configuration - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3928,7 +3899,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 666: // Set delta endstop adjustments - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -3950,7 +3921,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; case 669: // Set kinematics and parameters for non-delta kinematics - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -4008,7 +3979,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #endif case 671: // Set Z leadscrew positions - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -4029,7 +4000,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx reply.copy("Insufficient axes configured"); result = GCodeResult::error; } - else if (!LockMovementAndWaitForStandstillNoSync(gb)) + else if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { result = GCodeResult::notFinished; } @@ -4384,7 +4355,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #endif ) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -4402,7 +4373,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx #endif ) { - if (!LockMovementAndWaitForStandstillNoSync(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -4575,7 +4546,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 918: // Configure direct-connect display # ifdef DUET_NG // On Duet 2 configuring the display may affect the number of supported stepper drivers, so wait until there is no movement - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return false; } @@ -4797,11 +4768,7 @@ bool GCodes::HandleTcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx if (seen) { - if (!LockMovementAndWaitForStandstill(gb -#if SUPPORT_ASYNC_MOVES - , false // the other motion system can run concurrently with the tool change -#endif - )) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return false; } diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index b69a2101..779043fb 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -82,7 +82,7 @@ GCodeResult GCodes::SetPositions(GCodeBuffer& gb, const StringRef& reply) THROWS const float axisValue = gb.GetFValue(); if (axesIncluded.IsEmpty()) { - if (!LockMovementAndWaitForStandstill(gb)) // lock movement and get current coordinates + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) // lock movement and get current coordinates { return GCodeResult::notFinished; } @@ -134,7 +134,7 @@ GCodeResult GCodes::OffsetAxes(GCodeBuffer& gb, const StringRef& reply) { if (gb.Seen(axisLetters[axis])) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -188,7 +188,7 @@ GCodeResult GCodes::GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef& const float coord = gb.GetDistance(); if (!seen) { - if (!LockMovementAndWaitForStandstill(gb)) // make sure the user coordinates are stable and up to date + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) // make sure the user coordinates are stable and up to date { return GCodeResult::notFinished; } @@ -305,7 +305,7 @@ GCodeResult GCodes::ChangeSimulationMode(GCodeBuffer& gb, const StringRef &reply { if (newSimMode != simulationMode) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -395,7 +395,7 @@ GCodeResult GCodes::CheckTrigger(GCodeBuffer& gb, const StringRef& reply) THROWS // Deal with a M584 GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) { - if (!LockMovementAndWaitForStandstill(gb)) // we also rely on this to retrieve the current motor positions to moveBuffer + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) // we also rely on this to retrieve the current motor positions to moveBuffer { return GCodeResult::notFinished; } @@ -477,6 +477,9 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THRO { // We are creating a new axis axisLetters[drive] = c; // assign the drive to this drive letter +#if SUPPORT_ASYNC_MOVES + allAxisLetters.SetBit((c >= 'a') ? c - ('a' - 26) : c - 'A'); // update the map of all parameters that can be axis letters +#endif const AxisWrapType wrapType = (newAxesType != AxisWrapType::undefined) ? newAxesType : (c >= 'A' && c <= 'D') ? AxisWrapType::wrapAt360 // default A thru D to rotational but not continuous : AxisWrapType::noWrap; // default other axes to linear @@ -764,7 +767,7 @@ GCodeResult GCodes::ProbeTool(GCodeBuffer& gb, const StringRef& reply) THROWS(GC return GCodeResult::error; } - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -858,7 +861,7 @@ GCodeResult GCodes::FindCenterOfCavity(GCodeBuffer& gb, const StringRef& reply) return GCodeResult::error; } - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -983,7 +986,7 @@ GCodeResult GCodes::SetDateTime(GCodeBuffer& gb, const StringRef& reply) THROWS( // Handle M997 GCodeResult GCodes::UpdateFirmware(GCodeBuffer& gb, const StringRef &reply) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -1295,7 +1298,7 @@ GCodeResult GCodes::ConfigureLocalDriverBasicParameters(GCodeBuffer& gb, const S { if (gb.SeenAny("RS")) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -1513,7 +1516,7 @@ GCodeResult GCodes::ConfigureLocalDriverBasicParameters(GCodeBuffer& gb, const S // Handle G68 GCodeResult GCodes::HandleG68(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) { - if (!LockMovementAndWaitForStandstill(gb)) + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp index c26d7f7e..4a9e169f 100644 --- a/src/GCodes/GCodes4.cpp +++ b/src/GCodes/GCodes4.cpp @@ -45,7 +45,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept { case GCodeState::waitingForSpecialMoveToComplete: case GCodeState::abortWhenMovementFinished: - if ( LockMovementAndWaitForStandstill(gb) // movement should already be locked, but we need to wait for standstill and fetch the current position + if ( LockCurrentMovementSystemAndWaitForStandstill(gb) // movement should already be locked, but we need to wait for standstill and fetch the current position #if SUPPORT_CAN_EXPANSION && CanMotion::FinishedReverting() #endif @@ -88,7 +88,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case SegmentedMoveState::aborted: // move terminated abnormally - if (!LockMovementAndWaitForStandstill(gb)) // update the the user position from the machine position at which we stop + if (!LockCurrentMovementSystemAndWaitForStandstill(gb)) // update the the user position from the machine position at which we stop { break; } @@ -133,7 +133,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::probingToolOffset4: // executing M585, probing move has started - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { if (m585Settings.useProbe) { @@ -169,7 +169,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::findCenterOfCavity1: // Executing M675 using a Z probe, have already deployed the probe case GCodeState::probingToolOffset1: // Executing M585 using a probe, which we have deployed - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { lastProbedTime = millis(); // start the recovery timer const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); @@ -202,7 +202,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::findCenterOfCavity3: // Executing M675, min probing move has started - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); zp->SetProbing(false); @@ -223,7 +223,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::findCenterOfCavity4: // Executing M675, backoff move from min has started - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { if (SetupM675ProbingMove(gb, false)) { @@ -240,7 +240,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::findCenterOfCavity5: // Executing M675, max probing move has started - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { reprap.GetHeat().SuspendHeaters(false); const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); @@ -261,7 +261,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::findCenterOfCavity6: // Executing M675, move to centre has started - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { gb.SetState(GCodeState::normal); RetractZProbe(gb); @@ -305,7 +305,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::homing2: - if (LockMovementAndWaitForStandstill(gb)) // movement should already be locked, but we need to wait for the previous homing move to complete + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) // movement should already be locked, but we need to wait for the previous homing move to complete { // Test whether the previous homing move homed any axes if (toBeHomed.Disjoint(axesHomed)) @@ -351,11 +351,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::toolChange1: // release the old tool (if any), then run tpre for the new tool case GCodeState::m109ToolChange1: // release the old tool (if any), then run tpre for the new tool - if (LockMovementAndWaitForStandstill(gb -#if SUPPORT_ASYNC_MOVES - , false -#endif - )) // wait for tfree.g to finish executing + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait for tfree.g to finish executing { if (ms.currentTool != nullptr) { @@ -378,11 +374,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::toolChange2: // select the new tool if it exists and run tpost case GCodeState::m109ToolChange2: // select the new tool if it exists and run tpost - if (LockMovementAndWaitForStandstill(gb -#if SUPPORT_ASYNC_MOVES - , false -#endif - )) // wait for tpre.g to finish executing + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait for tpre.g to finish executing { ms.SelectTool(ms.newToolNumber, IsSimulating()); UpdateCurrentUserPosition(gb); // get the actual position of the new tool @@ -399,11 +391,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::toolChangeComplete: case GCodeState::m109ToolChangeComplete: - if (LockMovementAndWaitForStandstill(gb -#if SUPPORT_ASYNC_MOVES - , false -#endif - )) // wait for the move to height to finish + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) // wait for the move to height to finish { gb.LatestMachineState().feedRate = ms.toolChangeRestorePoint.feedRate; // We don't restore the default fan speed in case the user wants to use a different one for the new tool @@ -435,7 +423,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::pausing1: case GCodeState::eventPausing1: - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { gb.AdvanceState(); if (AllAxesAreHomed()) @@ -446,7 +434,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::filamentChangePause1: - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { gb.AdvanceState(); if (AllAxesAreHomed()) @@ -461,7 +449,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::pausing2: case GCodeState::filamentChangePause2: - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { reply.printf((gb.GetState() == GCodeState::filamentChangePause2) ? "Printing paused for filament change at" : "Printing paused at"); for (size_t axis = 0; axis < numVisibleAxes; ++axis) @@ -478,7 +466,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::eventPausing2: - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { pauseState = PauseState::paused; #if HAS_SBC_INTERFACE @@ -492,7 +480,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::resuming2: // Here when we have just finished running the resume macro file. // Move the head back to the paused location - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { const float currentZ = ms.coords[Z_AXIS]; for (size_t axis = 0; axis < numVisibleAxes; ++axis) @@ -519,7 +507,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::resuming3: - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { // We no longer restore the paused fan speeds automatically on resuming, because that messes up the print cooling fan speed if a tool change has been done // They can be restored manually in resume.g if required @@ -540,7 +528,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::cancelling: - if (LockMovementAndWaitForStandstill(gb)) // wait until cancel.g has completely finished + if (LockAllMovementSystemsAndWaitForStandstill(gb)) // wait until cancel.g has completely finished { pauseState = PauseState::notPaused; gb.SetState(GCodeState::normal); @@ -621,7 +609,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::stopping: // here when a print has finished, need to execute stop.g - if (LockMovementAndWaitForStandstill(gb)) + if (LockAllMovementSystemsAndWaitForStandstill(gb)) { #if SUPPORT_ASYNC_MOVES gb.ExecuteAll(); // only fileGCode gets here so it needs to execute moves for all commands @@ -683,7 +671,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::gridProbing2a: // ready to probe the current grid probe point (we return to this state when doing the second and subsequent taps) - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { gb.AdvanceState(); if (platform.GetZProbeOrDefault(currentZProbeNumber)->GetProbeType() == ZProbeType::blTouch) @@ -694,7 +682,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::gridProbing2b: // ready to probe the current grid probe point - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { lastProbedTime = millis(); // start the recovery timer const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); @@ -753,7 +741,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::gridProbing4: // ready to lift the probe after probing the current grid probe point - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { doingManualBedProbe = false; ++tapsDone; @@ -802,7 +790,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::gridProbing5: // finished probing a point and moved back to the dive height - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // See whether we need to do any more taps const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); @@ -944,7 +932,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::probingAtPoint1: // The move to raise/lower the head to the correct dive height has been commanded. - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // Head is at the dive height but needs to be moved to the correct XY position. The XY coordinates have already been stored. SetMoveBufferDefaults(ms); @@ -963,7 +951,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::probingAtPoint2a: // note we return to this state when doing the second and subsequent taps // Executing G30 with a P parameter. The move to put the head at the specified XY coordinates has been commanded. // OR initial state when executing G30 with no P parameter (must call InitialiseTaps first) - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { gb.AdvanceState(); if (platform.GetZProbeOrDefault(currentZProbeNumber)->GetProbeType() == ZProbeType::blTouch) // bltouch needs to be redeployed prior to each probe point @@ -974,7 +962,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::probingAtPoint2b: - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // Head has finished moving to the correct XY position and BLTouch has been deployed lastProbedTime = millis(); // start the probe recovery timer @@ -1032,8 +1020,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept ? platform.AxisMinimum(Z_AXIS) - zp->GetDiveHeight() + zp->GetActualTriggerHeight() // Z axis has been homed, so no point in going very far : -1.1 * platform.AxisTotalLength(Z_AXIS); // Z axis not homed yet, so treat this as a homing move ms.feedRate = zp->GetProbingSpeed(tapsDone); - NewSingleSegmentMoveAvailable(ms); ms.linearAxesMentioned = true; + NewSingleSegmentMoveAvailable(ms); gb.AdvanceState(); } } @@ -1042,7 +1030,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::probingAtPoint4: // Executing G30. The probe wasn't triggered at the start of the move, and the probing move has been commanded. - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // Probing move has stopped reprap.GetHeat().SuspendHeaters(false); @@ -1134,7 +1122,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::probingAtPoint5: // Here when we have moved the head back up to the dive height - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // See whether we need to do any more taps const auto zp = platform.GetZProbeOrDefault(currentZProbeNumber); @@ -1200,7 +1188,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::probingAtPoint6: // Here when we have finished probing and have retracted the probe if necessary - if (LockMovementAndWaitForStandstill(gb)) // retracting the Z probe + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) // retracting the Z probe { if (g30SValue == 1) { @@ -1256,7 +1244,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::straightProbe0: // ready to deploy the probe - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { gb.AdvanceState(); currentZProbeNumber = straightProbeSettings.GetZProbeToUse(); @@ -1265,7 +1253,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept break; case GCodeState::straightProbe1: - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { const auto zp = platform.GetEndstops().GetZProbe(straightProbeSettings.GetZProbeToUse()); lastProbedTime = millis(); // start the probe recovery timer @@ -1333,7 +1321,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::straightProbe3: // Executing G38. The probe wasn't in target state at the start of the move, and the probing move has been commanded. - if (LockMovementAndWaitForStandstill(gb)) + if (LockCurrentMovementSystemAndWaitForStandstill(gb)) { // Probing move has stopped reprap.GetHeat().SuspendHeaters(false); diff --git a/src/GCodes/GCodes5.cpp b/src/GCodes/GCodes5.cpp index 833b7ff7..79db28f4 100644 --- a/src/GCodes/GCodes5.cpp +++ b/src/GCodes/GCodes5.cpp @@ -57,6 +57,14 @@ void GCodes::ReportToolTemperatures(const StringRef& reply, const Tool *tool, bo #if SUPPORT_ASYNC_MOVES +// Handle M400 +GCodeResult GCodes::ExecuteM400(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) +{ + const unsigned int param = (gb.Seen('P')) ? gb.GetLimitedUIValue('P', 2) : 0; + const bool finished = (param == 1) ? LockAllMovementSystemsAndWaitForStandstill(gb) : LockCurrentMovementSystemAndWaitForStandstill(gb); + return (finished) ? GCodeResult::ok : GCodeResult::notFinished; +} + // Handle M596 GCodeResult GCodes::SelectMovementQueue(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) { @@ -130,6 +138,12 @@ GCodeResult GCodes::CollisionAvoidance(GCodeBuffer& gb, const StringRef& reply) return GCodeResult::ok; } +// Handle M598 +GCodeResult GCodes::SyncMovementSystems(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) +{ + return (DoSync(gb)) ? GCodeResult::ok : GCodeResult::notFinished; +} + #endif GCodeResult GCodes::HandleM486(GCodeBuffer &gb, const StringRef &reply, OutputBuffer*& buf) THROWS(GCodeException) diff --git a/src/Hardware/SAM4E/sam4e8e_flash.ld b/src/Hardware/SAM4E/sam4e8e_flash.ld index e7fc0113..fa10bf24 100644 --- a/src/Hardware/SAM4E/sam4e8e_flash.ld +++ b/src/Hardware/SAM4E/sam4e8e_flash.ld @@ -120,6 +120,9 @@ SECTIONS _firmware_end = _etext + (_erelocate - _srelocate); /* Embedded files start here */ _firmware_crc = _firmware_end; /* We append the CRC32 to the binary file. This is its offset in memory if we don't append embedded files */ + /* check that CRC is within flash memory */ + ASSERT(_firmware_crc + 4 <= ORIGIN(rom) + LENGTH(rom), "region ROM overflowed") + /* .bss section which is used for uninitialized data */ .bss ALIGN(4) (NOLOAD) : { diff --git a/src/Heating/Heater.cpp b/src/Heating/Heater.cpp index 19017fa5..ef340c91 100644 --- a/src/Heating/Heater.cpp +++ b/src/Heating/Heater.cpp @@ -41,26 +41,29 @@ constexpr ObjectModelTableEntry Heater::objectModelTable[] = { // Within each group, these entries must be in alphabetical order // 0. Heater members - { "active", OBJECT_MODEL_FUNC(self->GetActiveTemperature(), 1), ObjectModelEntryFlags::live }, - { "avgPwm", OBJECT_MODEL_FUNC(self->GetAveragePWM(), 3), ObjectModelEntryFlags::live }, - { "current", OBJECT_MODEL_FUNC(self->GetTemperature(), 2), ObjectModelEntryFlags::live }, - { "max", OBJECT_MODEL_FUNC(self->GetHighestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->GetLowestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, - { "model", OBJECT_MODEL_FUNC((const FopDt *)&self->GetModel()), ObjectModelEntryFlags::none }, - { "monitors", OBJECT_MODEL_FUNC_ARRAY(0), ObjectModelEntryFlags::none }, - { "sensor", OBJECT_MODEL_FUNC((int32_t)self->GetSensorNumber()), ObjectModelEntryFlags::none }, - { "standby", OBJECT_MODEL_FUNC(self->GetStandbyTemperature(), 1), ObjectModelEntryFlags::live }, - { "state", OBJECT_MODEL_FUNC(self->GetStatus().ToString()), ObjectModelEntryFlags::live }, + { "active", OBJECT_MODEL_FUNC(self->GetActiveTemperature(), 1), ObjectModelEntryFlags::live }, + { "avgPwm", OBJECT_MODEL_FUNC(self->GetAveragePWM(), 3), ObjectModelEntryFlags::live }, + { "current", OBJECT_MODEL_FUNC(self->GetTemperature(), 2), ObjectModelEntryFlags::live }, + { "max", OBJECT_MODEL_FUNC(self->GetHighestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, + { "maxBadReadings", OBJECT_MODEL_FUNC((int32_t)self->maxBadTemperatureCount), ObjectModelEntryFlags::none }, + { "maxHeatingFaultTime", OBJECT_MODEL_FUNC(self->maxHeatingFaultTime, 1), ObjectModelEntryFlags::none }, + { "maxTempExcursion", OBJECT_MODEL_FUNC(self->maxTempExcursion, 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->GetLowestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, + { "model", OBJECT_MODEL_FUNC((const FopDt *)&self->GetModel()), ObjectModelEntryFlags::none }, + { "monitors", OBJECT_MODEL_FUNC_ARRAY(0), ObjectModelEntryFlags::none }, + { "sensor", OBJECT_MODEL_FUNC((int32_t)self->GetSensorNumber()), ObjectModelEntryFlags::none }, + { "standby", OBJECT_MODEL_FUNC(self->GetStandbyTemperature(), 1), ObjectModelEntryFlags::live }, + { "state", OBJECT_MODEL_FUNC(self->GetStatus().ToString()), ObjectModelEntryFlags::live }, // 1. Heater.monitors[] members - { "action", OBJECT_MODEL_FUNC_IF(self->monitors[context.GetLastIndex()].GetTrigger() != HeaterMonitorTrigger::Disabled, - (int32_t)self->monitors[context.GetLastIndex()].GetAction()), ObjectModelEntryFlags::none }, - { "condition", OBJECT_MODEL_FUNC(self->monitors[context.GetLastIndex()].GetTriggerName()), ObjectModelEntryFlags::none }, - { "limit", OBJECT_MODEL_FUNC_IF(self->monitors[context.GetLastIndex()].GetTrigger() != HeaterMonitorTrigger::Disabled, - self->monitors[context.GetLastIndex()].GetTemperatureLimit(), 1), ObjectModelEntryFlags::none }, + { "action", OBJECT_MODEL_FUNC_IF(self->monitors[context.GetLastIndex()].GetTrigger() != HeaterMonitorTrigger::Disabled, + (int32_t)self->monitors[context.GetLastIndex()].GetAction()), ObjectModelEntryFlags::none }, + { "condition", OBJECT_MODEL_FUNC(self->monitors[context.GetLastIndex()].GetTriggerName()), ObjectModelEntryFlags::none }, + { "limit", OBJECT_MODEL_FUNC_IF(self->monitors[context.GetLastIndex()].GetTrigger() != HeaterMonitorTrigger::Disabled, + self->monitors[context.GetLastIndex()].GetTemperatureLimit(), 1), ObjectModelEntryFlags::none }, }; -constexpr uint8_t Heater::objectModelTableDescriptor[] = { 2, 10, 3 }; +constexpr uint8_t Heater::objectModelTableDescriptor[] = { 2, 13, 3 }; DEFINE_GET_OBJECT_MODEL_TABLE(Heater) @@ -93,6 +96,7 @@ float Heater::lastCoolingRate; FansBitmap Heater::tuningFans; unsigned int Heater::tuningPhase; uint8_t Heater::idleCyclesDone; +bool Heater::tuningQuietMode; Heater::HeaterParameters Heater::fanOffParams, Heater::fanOnParams; @@ -286,7 +290,8 @@ GCodeResult Heater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansB const float ambientTemp = (seenA) ? gb.GetFValue() : currentTemp; if (ambientTemp + 20 >= targetTemp) { - reply.printf("Target temperature must be at least 20C above ambient temperature"); + reply.copy("Target temperature must be at least 20C above ambient temperature"); + return GCodeResult::error; } // Get and store the optional parameters @@ -295,6 +300,7 @@ GCodeResult Heater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansB tuningPwm = (gb.Seen('P')) ? gb.GetLimitedFValue('P', 0.1, 1.0) : GetModel().GetMaxPwm(); tuningHysteresis = (gb.Seen('Y')) ? gb.GetLimitedFValue('Y', 1.0, 20.0) : DefaultTuningHysteresis; tuningFanPwm = (gb.Seen('F')) ? gb.GetLimitedFValue('F', 0.1, 1.0) : DefaultTuningFanPwm; + tuningQuietMode = gb.Seen('Q') && gb.GetUIValue() != 0; const GCodeResult rslt = StartAutoTune(reply, seenA, ambientTemp); if (rslt == GCodeResult::ok) @@ -419,14 +425,23 @@ void Heater::SetAndReportModelAfterTuning(bool usingFans) noexcept if (Succeeded(rslt)) { tuned = true; - str.printf( "Auto tuning heater %u completed after %u idle and %u tuning cycles in %" PRIu32 " seconds. This heater needs the following M307 command:\n ", + str.printf( "Auto tuning heater %u completed after %u idle and %u tuning cycles in %" PRIu32 " seconds", GetHeaterNumber(), idleCyclesDone, (usingFans) ? fanOffParams.numCycles + fanOnParams.numCycles : fanOffParams.numCycles, (millis() - tuningBeginTime)/(uint32_t)SecondsToMillis ); - GetModel().AppendM307Command(GetHeaterNumber(), str.GetRef(), !reprap.GetHeat().IsBedOrChamberHeater(GetHeaterNumber())); + if (tuningQuietMode) + { + str.cat('\n'); + } + else + { + str.cat( ". This heater needs the following M307 command:\n"); + GetModel().AppendM307Command(GetHeaterNumber(), str.GetRef(), !reprap.GetHeat().IsBedOrChamberHeater(GetHeaterNumber())); + } reprap.GetPlatform().Message(LoggedGenericMessage, str.c_str()); + if (reprap.Debug(moduleHeat)) { str.printf("Long term gain %.1f/%.1f", (double)fanOffParams.GetNormalGain(), (double)fanOffParams.gain); @@ -438,13 +453,16 @@ void Heater::SetAndReportModelAfterTuning(bool usingFans) noexcept reprap.GetPlatform().Message(GenericMessage, str.c_str()); } - if (reprap.GetGCodes().SawM501InConfigFile()) + if (!tuningQuietMode) { - reprap.GetPlatform().Message(GenericMessage, "Send M500 to save this command in config-override.g\n"); - } - else - { - reprap.GetPlatform().MessageF(GenericMessage, "Edit the M307 H%u command in config.g to match this. Omit the V parameter if the heater is not powered from VIN.\n", GetHeaterNumber()); + if (reprap.GetGCodes().SawM501InConfigFile()) + { + reprap.GetPlatform().Message(GenericMessage, "Send M500 to save this command in config-override.g\n"); + } + else + { + reprap.GetPlatform().MessageF(GenericMessage, "Edit the M307 H%u command in config.g to match this. Omit the V parameter if the heater is not powered from VIN.\n", GetHeaterNumber()); + } } } else @@ -461,6 +479,7 @@ GCodeResult Heater::ConfigureFaultDetectionParameters(GCodeBuffer& gb, const Str bool seenValue = false; gb.TryGetNonNegativeFValue('P', maxHeatingFaultTime, seenValue); gb.TryGetNonNegativeFValue('T', maxTempExcursion, seenValue); + gb.TryGetLimitedUIValue('R', maxBadTemperatureCount, seenValue, 51); if (seenValue) { const GCodeResult rslt = UpdateFaultDetectionParameters(reply); @@ -468,7 +487,8 @@ GCodeResult Heater::ConfigureFaultDetectionParameters(GCodeBuffer& gb, const Str return rslt; } - reply.printf("Heater %u allowed excursion %.1f" DEGREE_SYMBOL "C, fault trigger time %.1f seconds", heaterNumber, (double)maxTempExcursion, (double)maxHeatingFaultTime); + reply.printf("Heater %u allowed excursion %.1f" DEGREE_SYMBOL "C, fault trigger time %.1f seconds, max %" PRIu32 " consecutive bad readings", + heaterNumber, (double)maxTempExcursion, (double)maxHeatingFaultTime, maxBadTemperatureCount); return GCodeResult::ok; } @@ -674,6 +694,10 @@ GCodeResult Heater::SetFaultDetectionParameters(const CanMessageSetHeaterFaultDe { maxTempExcursion = msg.maxTempExcursion; maxHeatingFaultTime = msg.maxFaultTime; + if (msg.version35) + { + maxBadTemperatureCount = msg.maxBadTemperatureCount; + } return GCodeResult::ok; } diff --git a/src/Heating/Heater.h b/src/Heating/Heater.h index 9da5c919..008b9b54 100644 --- a/src/Heating/Heater.h +++ b/src/Heating/Heater.h @@ -20,7 +20,6 @@ # include "CanId.h" #endif - #define TUNE_WITH_HALF_FAN 0 class HeaterMonitor; @@ -135,7 +134,7 @@ protected: void SetSensorNumber(int sn) noexcept; float GetMaxTemperatureExcursion() const noexcept { return maxTempExcursion; } float GetMaxHeatingFaultTime() const noexcept { return maxHeatingFaultTime; } - unsigned int GetMaxBadTemperatureCount() const noexcept { return maxBadTemperatureCount; } + uint32_t GetMaxBadTemperatureCount() const noexcept { return maxBadTemperatureCount; } float GetTargetTemperature() const noexcept { return (active) ? activeTemperature : standbyTemperature; } bool IsBedOrChamber() const noexcept { return isBedOrChamber; } @@ -185,6 +184,7 @@ protected: static FansBitmap tuningFans; static unsigned int tuningPhase; static uint8_t idleCyclesDone; + static bool tuningQuietMode; static HeaterParameters fanOffParams, fanOnParams; @@ -200,7 +200,7 @@ private: float standbyTemperature; // the required standby temperature float maxTempExcursion; // the maximum temperature excursion permitted while maintaining the setpoint float maxHeatingFaultTime; // how long a heater fault is permitted to persist before a heater fault is raised - unsigned int maxBadTemperatureCount; // the number of consecutive bad sensor readings we allow before raising a fault + uint32_t maxBadTemperatureCount; // the number of consecutive bad sensor readings we allow before raising a fault bool isBedOrChamber; // true if this was a bed or chamber heater when we were switched on bool active; // are we active or standby? diff --git a/src/Heating/HeaterMonitor.cpp b/src/Heating/HeaterMonitor.cpp index 7b1ef9fb..a593b072 100644 --- a/src/Heating/HeaterMonitor.cpp +++ b/src/Heating/HeaterMonitor.cpp @@ -17,7 +17,7 @@ HeaterMonitor::HeaterMonitor() noexcept } // Check if any action needs to be taken. Returns true if everything is OK -bool HeaterMonitor::Check(unsigned int maxBadTemperatureCount) noexcept +bool HeaterMonitor::Check(uint32_t maxBadTemperatureCount) noexcept { if (sensorNumber >= 0 && trigger != HeaterMonitorTrigger::Disabled) { diff --git a/src/Heating/HeaterMonitor.h b/src/Heating/HeaterMonitor.h index f10a27a4..206ea51a 100644 --- a/src/Heating/HeaterMonitor.h +++ b/src/Heating/HeaterMonitor.h @@ -48,7 +48,7 @@ public: void Set(int sn, float lim, HeaterMonitorAction act, HeaterMonitorTrigger trig) noexcept; void Disable() noexcept; - bool Check(unsigned int maxBadTemperatureCount) noexcept; // Check if any action needs to be taken + bool Check(uint32_t) noexcept; // Check if any action needs to be taken int GetSensorNumber() const noexcept { return sensorNumber; } // Get the supervisory sensor number float GetTemperatureLimit() const noexcept { return limit; } // Get the temperature limit diff --git a/src/Heating/RemoteHeater.cpp b/src/Heating/RemoteHeater.cpp index 931fbcf2..6d6e081a 100644 --- a/src/Heating/RemoteHeater.cpp +++ b/src/Heating/RemoteHeater.cpp @@ -426,6 +426,8 @@ GCodeResult RemoteHeater::UpdateFaultDetectionParameters(const StringRef& reply) msg->heater = GetHeaterNumber(); msg->maxFaultTime = GetMaxHeatingFaultTime(); msg->maxTempExcursion = GetMaxTemperatureExcursion(); + msg->maxBadTemperatureCount = GetMaxBadTemperatureCount(); + msg->version35 = true; return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply); } diff --git a/src/Movement/AxisShaper.cpp b/src/Movement/AxisShaper.cpp index d5ea5eee..5c9e94df 100644 --- a/src/Movement/AxisShaper.cpp +++ b/src/Movement/AxisShaper.cpp @@ -77,7 +77,7 @@ GCodeResult AxisShaper::Configure(GCodeBuffer& gb, const StringRef& reply) THROW // Changing just the minimum acceleration is OK because no other variables depend on it. if (gb.SeenAny("FSPHT")) { - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index 9b99f0bb..2621020e 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -2374,6 +2374,16 @@ void DDA::UpdateMovementAccumulators(volatile int32_t *accumulators) const noexc #endif } +float DDA::GetTotalExtrusionRate() const noexcept +{ + float fraction = 0.0; + for (size_t i = MaxAxesPlusExtruders - reprap.GetGCodes().GetNumExtruders(); i < MaxAxesPlusExtruders; ++i) + { + fraction += directionVector[i]; + } + return fraction * InverseConvertSpeedToMmPerSec(topSpeed); +} + #if SUPPORT_LASER // Manage the laser power. Return the number of ticks until we should be called again, or 0 to be called at the start of the next move. diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h index fe37aee3..d9d2143e 100644 --- a/src/Movement/DDA.h +++ b/src/Movement/DDA.h @@ -147,6 +147,8 @@ public: float GetAccelerationMmPerSecSquared() const noexcept { return InverseConvertAcceleration(acceleration); } float GetDecelerationMmPerSecSquared() const noexcept { return InverseConvertAcceleration(deceleration); } float GetVirtualExtruderPosition() const noexcept { return virtualExtruderPosition; } + float GetTotalExtrusionRate() const noexcept; + float AdvanceBabyStepping(DDARing& ring, size_t axis, float amount) noexcept; // Try to push babystepping earlier in the move queue const Tool *GetTool() const noexcept { return tool; } float GetTotalDistance() const noexcept { return totalDistance; } diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp index 66d8d759..5b375636 100644 --- a/src/Movement/DDARing.cpp +++ b/src/Movement/DDARing.cpp @@ -121,7 +121,7 @@ GCodeResult DDARing::ConfigureMovementQueue(GCodeBuffer& gb, const StringRef& re gb.TryGetUIValue('R', gracePeriod, seen); if (seen) { - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } @@ -780,6 +780,12 @@ float DDARing::GetDecelerationMmPerSecSquared() const noexcept return (cdda != nullptr) ? cdda->GetDecelerationMmPerSecSquared() : 0.0; } +float DDARing::GetTotalExtrusionRate() const noexcept +{ + const DDA* const cdda = currentDda; // capture volatile variable + return (cdda != nullptr) ? cdda->GetTotalExtrusionRate() : 0.0; +} + // Pause the print as soon as we can, returning true if we are able to skip any moves and updating 'rp' to the first move we skipped. // Called from GCodes by the Main task bool DDARing::PauseMoves(RestorePoint& rp) noexcept diff --git a/src/Movement/DDARing.h b/src/Movement/DDARing.h index 3cf6b641..ea15bf34 100644 --- a/src/Movement/DDARing.h +++ b/src/Movement/DDARing.h @@ -60,6 +60,7 @@ public: float GetTopSpeedMmPerSec() const noexcept; float GetAccelerationMmPerSecSquared() const noexcept; float GetDecelerationMmPerSecSquared() const noexcept; + float GetTotalExtrusionRate() const noexcept; int32_t GetEndPoint(size_t drive) const noexcept { return liveEndPoints[drive]; } // Get the current position of a motor void GetCurrentMachinePosition(float m[MaxAxes], bool disableMotorMapping) const noexcept; // Get the current position in untransformed coords diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index f73987a6..26277d12 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -127,6 +127,7 @@ constexpr ObjectModelTableEntry Move::objectModelTable[] = // 2. move.currentMove members { "acceleration", OBJECT_MODEL_FUNC(self->GetAccelerationMmPerSecSquared(), 1), ObjectModelEntryFlags::live }, { "deceleration", OBJECT_MODEL_FUNC(self->GetDecelerationMmPerSecSquared(), 1), ObjectModelEntryFlags::live }, + { "extrusionRate", OBJECT_MODEL_FUNC(self->GetTotalExtrusionRate(), 2), ObjectModelEntryFlags::live }, # if SUPPORT_LASER { "laserPwm", OBJECT_MODEL_FUNC_IF_NOSELF(reprap.GetGCodes().GetMachineType() == MachineType::laser, reprap.GetPlatform().GetLaserPwm(), 2), ObjectModelEntryFlags::live }, @@ -180,7 +181,7 @@ constexpr uint8_t Move::objectModelTableDescriptor[] = 9 + SUPPORT_COORDINATE_ROTATION, 17 + SUPPORT_WORKPLACE_COORDINATES, 2, - 4 + SUPPORT_LASER, + 5 + SUPPORT_LASER, 3, 2, 2, @@ -1042,7 +1043,7 @@ GCodeResult Move::ConfigurePressureAdvance(GCodeBuffer& gb, const StringRef& rep if (gb.Seen('S')) { const float advance = gb.GetNonNegativeFValue(); - if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) + if (!reprap.GetGCodes().LockCurrentMovementSystemAndWaitForStandstill(gb)) { return GCodeResult::notFinished; } diff --git a/src/Movement/Move.h b/src/Movement/Move.h index 554b0977..27726ea5 100644 --- a/src/Movement/Move.h +++ b/src/Movement/Move.h @@ -166,6 +166,7 @@ public: float GetRequestedSpeedMmPerSec() const noexcept { return rings[0].GetRequestedSpeedMmPerSec(); } float GetAccelerationMmPerSecSquared() const noexcept { return rings[0].GetAccelerationMmPerSecSquared(); } float GetDecelerationMmPerSecSquared() const noexcept { return rings[0].GetDecelerationMmPerSecSquared(); } + float GetTotalExtrusionRate() const noexcept { return rings[0].GetTotalExtrusionRate(); } void AdjustLeadscrews(const floatc_t corrections[]) noexcept; // Called by some Kinematics classes to adjust the leadscrews diff --git a/src/Movement/RawMove.h b/src/Movement/RawMove.h index adec7b08..99b11d1b 100644 --- a/src/Movement/RawMove.h +++ b/src/Movement/RawMove.h @@ -80,6 +80,7 @@ struct MovementState : public RawMove { Tool *currentTool; // the current tool of this movement system AxesBitmap axesAndExtrudersOwned; // axes and extruders that this movement system has moved since the last sync + ParameterLettersBitmap ownedAxisLetters; // letters denoting axes that this movement system owns // The current user position now holds the requested user position after applying workplace coordinate offsets. // So we must subtract the workplace coordinate offsets when we want to display them. diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.cpp b/src/Networking/ESP8266WiFi/WiFiInterface.cpp index d6554ec4..e5f4b2b4 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.cpp +++ b/src/Networking/ESP8266WiFi/WiFiInterface.cpp @@ -88,7 +88,7 @@ constexpr IRQn ESP_SPI_IRQn = WiFiSpiSercomIRQn; #endif const uint32_t WiFiSlowResponseTimeoutMillis = 500; // SPI timeout when when the ESP has to access the SPIFFS filesytem; highest measured is 234ms. -const uint32_t WiFiFastResponseTimeoutMillis = 20; // SPI timeout when when the ESP does not have to access SPIFFS filesystem. +const uint32_t WiFiFastResponseTimeoutMillis = 100; // SPI timeout when when the ESP does not have to access SPIFFS filesystem. 20ms is too short on Duet 2 with both FTP and Telnet enabled. const uint32_t WiFiWaitReadyMillis = 100; const uint32_t WiFiStartupMillis = 15000; // Formatting the SPIFFS partition can take up to 10s. const uint32_t WiFiStableMillis = 100; diff --git a/src/Networking/MulticastDiscovery/MulticastResponder.cpp b/src/Networking/MulticastDiscovery/MulticastResponder.cpp index c2227c33..2d0b2ee7 100644 --- a/src/Networking/MulticastDiscovery/MulticastResponder.cpp +++ b/src/Networking/MulticastDiscovery/MulticastResponder.cpp @@ -19,10 +19,12 @@ extern "C" { #include "LwipEthernet/Lwip/src/include/lwip/udp.h" #include "LwipEthernet/Lwip/src/include/lwip/igmp.h" -extern struct netif gs_net_if; +extern netif gs_net_if; } -static constexpr ip_addr_t ourGroup = IPADDR4_INIT_BYTES(239, 255, 2, 3); +extern Mutex lwipMutex; + +static constexpr ip_addr_t ourGroupIpAddr = IPADDR4_INIT_BYTES(239, 255, 2, 3); static udp_pcb *ourPcb = nullptr; static pbuf * volatile receivedPbuf = nullptr; @@ -84,9 +86,12 @@ void MulticastResponder::Spin() noexcept debugPrintf("\n"); #endif receivedPbuf = nullptr; + fgmcHandler->handleStream(0, (uint8_t *)rxPbuf->payload, rxPbuf->len); - pbuf_free(rxPbuf); ++messagesProcessed; + + MutexLocker lock(lwipMutex); + pbuf_free(rxPbuf); } } } @@ -106,6 +111,7 @@ void MulticastResponder::Start(TcpPort port) noexcept if (ourPcb == nullptr) { + MutexLocker lock(lwipMutex); ourPcb = udp_new_ip_type(IPADDR_TYPE_ANY); if (ourPcb == nullptr) { @@ -114,12 +120,14 @@ void MulticastResponder::Start(TcpPort port) noexcept else { udp_set_multicast_ttl(ourPcb, 255); - if (igmp_joingroup_netif(&gs_net_if, ip_2_ip4(&ourGroup)) != ERR_OK) // without this call, multicast packets to this IP address get discarded + if (igmp_joingroup_netif(&gs_net_if, ip_2_ip4(&ourGroupIpAddr)) != ERR_OK) // without this call, multicast packets to this IP address get discarded { + lock.Release(); reprap.GetPlatform().Message(ErrorMessage, "igmp_joingroup failed\n"); } - else if (udp_bind(ourPcb, &ourGroup, port) != ERR_OK) + else if (udp_bind(ourPcb, &ourGroupIpAddr, port) != ERR_OK) { + lock.Release(); reprap.GetPlatform().Message(ErrorMessage, "udp_bind call failed\n"); } else @@ -136,6 +144,7 @@ void MulticastResponder::Stop() noexcept { if (ourPcb != nullptr) { + MutexLocker lock(lwipMutex); udp_remove(ourPcb); ourPcb = nullptr; } @@ -153,20 +162,30 @@ void MulticastResponder::SendResponse(uint8_t *data, size_t length) noexcept debugPrintf("\n"); #endif + MutexLocker lock(lwipMutex); pbuf * const pb = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_RAM); -#if 0 - if (pbuf_take(pb, data, length) != ERR_OK) + if (pb != nullptr) { - debugPrintf("pbuf_take returned error\n"); + if (pbuf_take(pb, data, length) == ERR_OK) + { + if (udp_sendto(ourPcb, pb, &ourGroupIpAddr, lastMessageReceivedPort) != ERR_OK && reprap.Debug(moduleNetwork)) + { + debugPrintf("UDP send failed\n"); + } + } + else + { + if (reprap.Debug(moduleNetwork)) + { + debugPrintf("pbuf_take returned error, length %u\n", length); + } + pbuf_free(pb); + } } - if (udp_sendto_if(ourPcb, pb, &ourGroup, lastMessageReceivedPort, &gs_net_if) != ERR_OK) + else if (reprap.Debug(moduleNetwork)) { - debugPrintf("UDP send failed\n"); + debugPrintf("pbug_alloc failed,length=%u\n", length); } -#else - (void)pbuf_take(pb, data, length); - (void)udp_sendto_if(ourPcb, pb, &ourGroup, lastMessageReceivedPort, &gs_net_if); -#endif } // Schedule a reboot. We delay a little while to allow the response to be transmitted first. diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp index 516f91d9..6105b0fb 100644 --- a/src/Networking/Network.cpp +++ b/src/Networking/Network.cpp @@ -97,6 +97,9 @@ Network::Network(Platform& p) noexcept : platform(p) # else # error Unknown board # endif +# if defined(DUET3_MB6HC) + interfaces[1] = nullptr; // no WiFi interface yet +# endif #endif // HAS_NETWORKING } @@ -350,7 +353,7 @@ WiFiInterface *Network::FindWiFiInterface() const noexcept #if HAS_WIFI_NETWORKING for (NetworkInterface *iface : interfaces) { - if (iface->IsWiFiInterface()) + if (iface != nullptr && iface->IsWiFiInterface()) { return static_cast<WiFiInterface *>(iface); } @@ -533,7 +536,10 @@ void Network::Spin() noexcept // Keep the network modules running for (NetworkInterface *iface : interfaces) { - iface->Spin(); + if (iface != nullptr) + { + iface->Spin(); + } } #if HAS_RESPONDERS @@ -603,7 +609,10 @@ void Network::Diagnostics(MessageType mtype) noexcept for (NetworkInterface *iface : interfaces) { - iface->Diagnostics(mtype); + if (iface != nullptr) + { + iface->Diagnostics(mtype); + } } #endif @@ -628,7 +637,7 @@ void Network::SetEthernetIPAddress(IPAddress p_ipAddress, IPAddress p_netmask, I #if HAS_NETWORKING for (NetworkInterface *iface : interfaces) { - if (!iface->IsWiFiInterface()) + if (iface != nullptr && !iface->IsWiFiInterface()) { iface->SetIPAddress(p_ipAddress, p_netmask, p_gateway); } @@ -699,9 +708,12 @@ void Network::SetHostname(const char *name) noexcept strcpy(hostname, DEFAULT_HOSTNAME); } - for (unsigned int i = 0; i < GetNumNetworkInterfaces(); ++i) + for (NetworkInterface *iface : interfaces) { - interfaces[i]->UpdateHostname(hostname); + if (iface != nullptr) + { + iface->UpdateHostname(hostname); + } } #endif } diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp index 7e003bf6..5dc74632 100644 --- a/src/Platform/Platform.cpp +++ b/src/Platform/Platform.cpp @@ -2677,12 +2677,30 @@ void Platform::SetDriversIdle() noexcept // Configure the brake port for a driver GCodeResult Platform::ConfigureDriverBrakePort(GCodeBuffer& gb, const StringRef& reply, size_t driver) noexcept { + bool seen = false; if (gb.Seen('C')) { - return GetGCodeResultFromSuccess(brakePorts[driver].AssignPort(gb, reply, PinUsedBy::gpout, PinAccess::write0)); + seen = true; + if (!brakePorts[driver].AssignPort(gb, reply, PinUsedBy::gpout, PinAccess::write0)) + { + return GCodeResult::error; + } + delayAfterBrakeOn[driver] = DefaultDelayAfterBrakeOn; + } + uint32_t val; + if (gb.TryGetLimitedUIValue('S', val, seen, 100)) + { + delayAfterBrakeOn[driver] = val; + } + + if (!seen) + { + reply.printf("Driver %u uses brake port ", driver); + brakePorts[driver].AppendPinName(reply); +#if 0 // don't print this bit until we have implemented it! + reply.catf(" and %ums delay after turning the brake on", delayAfterBrakeOn[driver]); +#endif } - reply.printf("Driver %u uses brake port ", driver); - brakePorts[driver].AppendPinName(reply); return GCodeResult::ok; } diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h index f33c633a..d2d9ab6e 100644 --- a/src/Platform/Platform.h +++ b/src/Platform/Platform.h @@ -761,7 +761,8 @@ private: bool driverErrPinsActiveLow; #endif - IoPort brakePorts[NumDirectDrivers]; + IoPort brakePorts[NumDirectDrivers]; // the brake ports for each driver + uint16_t delayAfterBrakeOn[NumDirectDrivers]; // how many milliseconds we wait between turning the brake on and de-energising the driver float motorCurrents[MaxAxesPlusExtruders]; // the normal motor current for each stepper driver float motorCurrentFraction[MaxAxesPlusExtruders]; // the percentages of normal motor current that each driver is set to diff --git a/src/PrintMonitor/PrintMonitor.cpp b/src/PrintMonitor/PrintMonitor.cpp index 6b6fc1d9..af10959e 100644 --- a/src/PrintMonitor/PrintMonitor.cpp +++ b/src/PrintMonitor/PrintMonitor.cpp @@ -74,7 +74,6 @@ constexpr ObjectModelTableEntry PrintMonitor::objectModelTable[] = { "duration", OBJECT_MODEL_FUNC_IF(self->IsPrinting(), self->GetPrintOrSimulatedDuration()), ObjectModelEntryFlags::live }, { "file", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none }, { "filePosition", OBJECT_MODEL_FUNC(self->gCodes.GetPrintingFilePosition()), ObjectModelEntryFlags::live }, - { "firstLayerDuration", OBJECT_MODEL_FUNC_NOSELF(nullptr), ObjectModelEntryFlags::obsolete }, { "lastDuration", OBJECT_MODEL_FUNC_IF(!self->IsPrinting(), (int32_t)self->gCodes.GetLastDuration()), ObjectModelEntryFlags::none }, { "lastFileName", OBJECT_MODEL_FUNC_IF(!self->filenameBeingPrinted.IsEmpty() && !self->IsPrinting(), self->filenameBeingPrinted.c_str()), ObjectModelEntryFlags::none }, // TODO Add enum about the last file print here (to replace lastFileAborted, lastFileCancelled, lastFileSimulated) @@ -108,11 +107,10 @@ constexpr ObjectModelTableEntry PrintMonitor::objectModelTable[] = // 3. TimesLeft members { "filament", OBJECT_MODEL_FUNC(self->EstimateTimeLeftAsExpression(filamentBased)), ObjectModelEntryFlags::live }, { "file", OBJECT_MODEL_FUNC(self->EstimateTimeLeftAsExpression(fileBased)), ObjectModelEntryFlags::live }, - { "layer", OBJECT_MODEL_FUNC_NOSELF(nullptr), ObjectModelEntryFlags::obsolete }, { "slicer", OBJECT_MODEL_FUNC(self->EstimateTimeLeftAsExpression(slicerBased)), ObjectModelEntryFlags::live }, }; -constexpr uint8_t PrintMonitor::objectModelTableDescriptor[] = { 4, 13, 11, 5, 4 }; +constexpr uint8_t PrintMonitor::objectModelTableDescriptor[] = { 4, 12, 11, 5, 3 }; DEFINE_GET_OBJECT_MODEL_TABLE(PrintMonitor) diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index c2845247..a994f734 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -318,25 +318,26 @@ class ExpansionManager; // Define floating point type to use for calculations where we would like high precision in matrix calculations #if SAME70 -typedef double floatc_t; // type of matrix element used for calibration +typedef double floatc_t; // type of matrix element used for calibration #else -// We are more memory-constrained on the other processors and they don't support double precision -typedef float floatc_t; // type of matrix element used for calibration +// We are more memory-constrained on the other processors and they don't support double precision in hardware +typedef float floatc_t; // type of matrix element used for calibration #endif #if defined(DUET3) || defined(DUET3MINI) -typedef Bitmap<uint32_t> AxesBitmap; // Type of a bitmap representing a set of axes, and sometimes extruders too +typedef Bitmap<uint32_t> AxesBitmap; // Type of a bitmap representing a set of axes, and sometimes extruders too #else -typedef Bitmap<uint16_t> AxesBitmap; // Type of a bitmap representing a set of axes, and sometimes extruders too +typedef Bitmap<uint16_t> AxesBitmap; // Type of a bitmap representing a set of axes, and sometimes extruders too #endif -typedef Bitmap<uint32_t> ExtrudersBitmap; // Type of a bitmap representing a set of extruder drive numbers -typedef Bitmap<uint32_t> DriversBitmap; // Type of a bitmap representing a set of local driver numbers -typedef Bitmap<uint32_t> FansBitmap; // Type of a bitmap representing a set of fan numbers -typedef Bitmap<uint32_t> HeatersBitmap; // Type of a bitmap representing a set of heater numbers -typedef Bitmap<uint16_t> DriverChannelsBitmap; // Type of a bitmap representing a set of drivers that typically have a common cooling fan -typedef Bitmap<uint32_t> InputPortsBitmap; // Type of a bitmap representing a set of input ports -typedef Bitmap<uint32_t> TriggerNumbersBitmap; // Type of a bitmap representing a set of trigger numbers -typedef Bitmap<uint64_t> ToolNumbersBitmap; // Type of a bitmap representing a set of tool numbers +typedef Bitmap<uint32_t> ExtrudersBitmap; // Type of a bitmap representing a set of extruder drive numbers +typedef Bitmap<uint32_t> DriversBitmap; // Type of a bitmap representing a set of local driver numbers +typedef Bitmap<uint32_t> FansBitmap; // Type of a bitmap representing a set of fan numbers +typedef Bitmap<uint32_t> HeatersBitmap; // Type of a bitmap representing a set of heater numbers +typedef Bitmap<uint16_t> DriverChannelsBitmap; // Type of a bitmap representing a set of drivers that typically have a common cooling fan +typedef Bitmap<uint32_t> InputPortsBitmap; // Type of a bitmap representing a set of input ports +typedef Bitmap<uint32_t> TriggerNumbersBitmap; // Type of a bitmap representing a set of trigger numbers +typedef Bitmap<uint64_t> ToolNumbersBitmap; // Type of a bitmap representing a set of tool numbers +typedef Bitmap<uint32_t> ParameterLettersBitmap; // Type of a bitmap representing a set of parameter letters in A..Z and a..f #if defined(DUET3) || defined(DUET3MINI) typedef Bitmap<uint64_t> SensorsBitmap; diff --git a/src/SBC/SbcInterface.cpp b/src/SBC/SbcInterface.cpp index 0a203999..592cb16b 100644 --- a/src/SBC/SbcInterface.cpp +++ b/src/SBC/SbcInterface.cpp @@ -443,7 +443,7 @@ void SbcInterface::ExchangeData() noexcept break; } - // Lock movement and wait for standstill + // Lock movement and wait for standstill. Currently this is used only by M505, so we lock all movement systems. case SbcRequest::LockMovementAndWaitForStandstill: { const GCodeChannel channel = transfer.ReadCodeChannel(); @@ -451,7 +451,7 @@ void SbcInterface::ExchangeData() noexcept { GCodeBuffer * const gb = reprap.GetGCodes().GetGCodeBuffer(channel); MutexLocker locker(gb->mutex, SbcYieldTimeout); - if (locker.IsAcquired() && reprap.GetGCodes().LockMovementAndWaitForStandstill(*gb)) + if (locker.IsAcquired() && reprap.GetGCodes().LockAllMovementSystemsAndWaitForStandstill(*gb)) { transfer.WriteLocked(channel); } diff --git a/src/Storage/FileInfoParser.cpp b/src/Storage/FileInfoParser.cpp index 1ecc187c..a41d52f1 100644 --- a/src/Storage/FileInfoParser.cpp +++ b/src/Storage/FileInfoParser.cpp @@ -487,7 +487,7 @@ bool FileInfoParser::FindHeight(const char* bufp, size_t len) noexcept return foundHeight; } -// Scan the buffer for th total number of layers. The buffer is null-terminated. +// Scan the buffer for the total number of layers. The buffer is null-terminated. bool FileInfoParser::FindNumLayers(const char* bufp, size_t len) noexcept { static const char* const numLayerStrings[] = diff --git a/src/bossa/BossaFlash.cpp b/src/bossa/BossaFlash.cpp index c1fbc0b0..f83d78a7 100644 --- a/src/bossa/BossaFlash.cpp +++ b/src/bossa/BossaFlash.cpp @@ -34,11 +34,11 @@ BossaFlash::BossaFlash(Samba& samba, uint32_t pages, uint32_t size, uint32_t planes, - uint32_t lockRegions, + uint32_t numLockRegions, uint32_t user, uint32_t stack) THROWS(GCodeException) : _samba(samba), _name(name), _addr(addr), _pages(pages), _size(size), - _planes(planes), _lockRegions(lockRegions), _user(user), _wordCopy(samba, user) + _planes(planes), _numLockRegions(numLockRegions), _user(user), _wordCopy(samba, user) { _wordCopy.setWords(size / sizeof(uint32_t)); @@ -51,44 +51,39 @@ BossaFlash::BossaFlash(Samba& samba, _pageBufferB = _pageBufferA + size; } -void -BossaFlash::setLockRegions(const Vector<bool, 16>& regions) THROWS(GCodeException) +void BossaFlash::setLockRegions(Bitmap<uint32_t>regions) THROWS(GCodeException) { - if (regions.Size() > _lockRegions) - throw FlashRegionError("Flash::setLockRegions: regions.Size() > _lockRegions"); - _regions.set(regions); } -void -BossaFlash::setSecurity() noexcept +#if ORIGINAL_BOSSA_CODE + +void BossaFlash::setSecurity() noexcept { _security.set(true); } -void -BossaFlash::setBor(bool enable) noexcept +void BossaFlash::setBor(bool enable) noexcept { if (canBor()) _bor.set(enable); } -void -BossaFlash::setBod(bool enable) noexcept +void BossaFlash::setBod(bool enable) noexcept { if (canBod()) _bod.set(enable); } -void -BossaFlash::setBootFlash(bool enable) noexcept +#endif + +void BossaFlash::setBootFlash(bool enable) noexcept { if (canBootFlash()) _bootFlash.set(enable); } -void -BossaFlash::loadBuffer(const uint8_t* data, uint16_t bufferSize) THROWS(GCodeException) +void BossaFlash::loadBuffer(const uint8_t* data, uint16_t bufferSize) THROWS(GCodeException) { _samba.write(_onBufferA ? _pageBufferA : _pageBufferB, data, bufferSize); } diff --git a/src/bossa/BossaFlash.h b/src/bossa/BossaFlash.h index 99b66a4e..b647bd93 100644 --- a/src/bossa/BossaFlash.h +++ b/src/bossa/BossaFlash.h @@ -69,53 +69,47 @@ public: uint32_t pages, // Number of pages uint32_t size, // Page size in bytes uint32_t planes, // Number of flash planes - uint32_t p_lockRegions, // Number of flash lock regions + uint32_t numLockRegions, // Number of flash lock regions uint32_t user, // Address in SRAM where the applet and buffers will be placed uint32_t stack) THROWS(GCodeException); // Address in SRAM where the applet stack will be placed virtual ~BossaFlash() {} - const char *_ecv_array name() noexcept { return _name; } + const char *_ecv_array name() const noexcept { return _name; } - virtual uint32_t address() noexcept { return _addr; } - virtual uint32_t pageSize() noexcept { return _size; } - virtual uint32_t numPages() noexcept { return _pages; } - virtual uint32_t numPlanes() noexcept { return _planes; } - virtual uint32_t totalSize() noexcept { return _size * _pages; } - virtual uint32_t lockRegions() noexcept { return _lockRegions; } + uint32_t address() const noexcept { return _addr; } + uint32_t pageSize() const noexcept { return _size; } + uint32_t numPages() const noexcept { return _pages; } + uint32_t numPlanes() const noexcept { return _planes; } + uint32_t totalSize() const noexcept { return _size * _pages; } + uint32_t getNumLockRegions() const noexcept { return _numLockRegions; } virtual void eraseAll(uint32_t offset) THROWS(GCodeException) = 0; virtual void eraseAuto(bool enable) noexcept = 0; - virtual Vector<bool, 16> getLockRegions() THROWS(GCodeException) = 0; - virtual void setLockRegions(const Vector<bool, 16>& regions) THROWS(GCodeException); + virtual Bitmap<uint32_t> getLockRegions() THROWS(GCodeException) = 0; + virtual void setLockRegions(Bitmap<uint32_t> regions) THROWS(GCodeException); #if ORIGINAL_BOSSA_CODE virtual bool getSecurity() = 0; -#endif - virtual void setSecurity() noexcept; - -#if ORIGINAL_BOSSA_CODE + void setSecurity() noexcept; virtual bool getBod() = 0; -#endif - virtual void setBod(bool enable) noexcept; - virtual bool canBod() noexcept = 0; - -#if ORIGINAL_BOSSA_CODE + void setBod(bool enable) noexcept; virtual bool getBor() = 0; + void setBor(bool enable) noexcept; + virtual bool canBor() const noexcept = 0; #endif - virtual void setBor(bool enable) noexcept; - virtual bool canBor() noexcept = 0; + virtual bool canBod() const noexcept = 0; virtual bool getBootFlash() THROWS(GCodeException) = 0; - virtual void setBootFlash(bool enable) noexcept; - virtual bool canBootFlash() noexcept = 0; + void setBootFlash(bool enable) noexcept; + virtual bool canBootFlash() const noexcept = 0; virtual void writeOptions() THROWS(GCodeException) = 0; virtual void writePage(uint32_t page) THROWS(GCodeException) = 0; virtual void readPage(uint32_t page, uint8_t* data) THROWS(GCodeException) = 0; - virtual void loadBuffer(const uint8_t* data, uint16_t size) THROWS(GCodeException); + void loadBuffer(const uint8_t* data, uint16_t size) THROWS(GCodeException); protected: Samba& _samba; @@ -124,15 +118,18 @@ protected: uint32_t _pages; uint32_t _size; uint32_t _planes; - uint32_t _lockRegions; + uint32_t _numLockRegions; uint32_t _user; WordCopyApplet _wordCopy; FlashOption<bool> _bootFlash; - FlashOption<Vector<bool, 16>> _regions; + FlashOption<Bitmap<uint32_t>> _regions; + +#if ORIGINAL_BOSSA_CODE FlashOption<bool> _bod; FlashOption<bool> _bor; FlashOption<bool> _security; +#endif bool _onBufferA; uint32_t _pageBufferA; diff --git a/src/bossa/Device.cpp b/src/bossa/Device.cpp index d3abc9e8..ab51285f 100644 --- a/src/bossa/Device.cpp +++ b/src/bossa/Device.cpp @@ -26,12 +26,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /////////////////////////////////////////////////////////////////////////////// + #include "Device.h" #include "EefcFlash.h" #if ORIGINAL_BOSSA_CODE -void -Device::readChipId(uint32_t& chipId, uint32_t& extChipId) +void Device::readChipId(uint32_t& chipId, uint32_t& extChipId) { if ((chipId = _samba.readWord(0x400e0740)) != 0) { @@ -44,8 +44,7 @@ Device::readChipId(uint32_t& chipId, uint32_t& extChipId) } #endif -void -Device::create() THROWS(GCodeException) +void Device::create() THROWS(GCodeException) { BossaFlash* flashPtr; #if ORIGINAL_BOSSA_CODE @@ -635,8 +634,7 @@ Device::create() THROWS(GCodeException) _flash = flashPtr; } -void -Device::reset() THROWS(GCodeException) +void Device::reset() noexcept { try { @@ -696,4 +694,4 @@ Device::reset() THROWS(GCodeException) } } - +// End diff --git a/src/bossa/Device.h b/src/bossa/Device.h index 06054576..914ed7d2 100644 --- a/src/bossa/Device.h +++ b/src/bossa/Device.h @@ -85,7 +85,7 @@ public: BossaFlash *_ecv_from null getFlash() const noexcept { return _flash; } - void reset() THROWS(GCodeException); + void reset() noexcept; private: Samba& _samba; diff --git a/src/bossa/EefcFlash.cpp b/src/bossa/EefcFlash.cpp index 153e38b7..65ba291b 100644 --- a/src/bossa/EefcFlash.cpp +++ b/src/bossa/EefcFlash.cpp @@ -63,19 +63,21 @@ EefcFlash::EefcFlash(Samba& samba, uint32_t pages, uint32_t size, uint32_t planes, - uint32_t lockRegions, + uint32_t numLockRegions, uint32_t user, uint32_t stack, uint32_t regs, bool canBrownout) THROWS(GCodeException) - : BossaFlash(samba, name, addr, pages, size, planes, lockRegions, user, stack), + : BossaFlash(samba, name, addr, pages, size, planes, numLockRegions, user, stack), _regs(regs), _canBrownout(canBrownout), _eraseAuto(true) { // SAM3 Errata (FWS must be 6) _samba.writeWord(EEFC0_FMR, 0x6 << 8); if (planes == 2) + { _samba.writeWord(EEFC1_FMR, 0x6 << 8); + } } EefcFlash::~EefcFlash() @@ -96,8 +98,7 @@ EefcFlash::eraseAll(uint32_t offset) THROWS(GCodeException) writeFCR1(EEFC_FCMD_EA, 0); } - // Erase all can take an exceptionally long time on some devices - // so wait on FSR for up to 30 seconds + // Erase all can take an exceptionally long time on some devices so wait on FSR for up to 30 seconds waitFSR(30); } // Else we must do it by pages @@ -124,47 +125,49 @@ EefcFlash::eraseAll(uint32_t offset) THROWS(GCodeException) } } -void -EefcFlash::eraseAuto(bool enable) noexcept +void EefcFlash::eraseAuto(bool enable) noexcept { _eraseAuto = enable; } -Vector<bool, 16> -EefcFlash::getLockRegions() THROWS(GCodeException) +Bitmap<uint32_t> EefcFlash::getLockRegions() THROWS(GCodeException) { - Vector<bool, 16> regions(_lockRegions, false); - uint32_t frr; - uint32_t bit; + Bitmap<uint32_t> regions; waitFSR(); - for (uint32_t region = 0; region < _lockRegions; region++) + for (uint32_t region = 0; region < _numLockRegions; region++) { - if (_planes == 2 && region >= _lockRegions / 2) + if (_planes == 2 && region >= _numLockRegions / 2) { - bit = region - _lockRegions / 2; + uint32_t bit = region - _numLockRegions / 2; writeFCR1(EEFC_FCMD_GLB, 0); waitFSR(); - frr = readFRR1(); + uint32_t frr = readFRR1(); while (bit >= 32) { frr = readFRR1(); bit -= 32; } - regions[region] = (frr & (1 << bit)) != 0; + if ((frr & (1 << bit)) != 0) + { + regions.SetBit(region); + } } else { - bit = region; + uint32_t bit = region; writeFCR0(EEFC_FCMD_GLB, 0); waitFSR(); - frr = readFRR0(); + uint32_t frr = readFRR0(); while (bit >= 32) { frr = readFRR0(); bit -= 32; } - regions[region] = (frr & (1 << bit)) != 0; + if ((frr & (1 << bit)) != 0) + { + regions.SetBit(region); + } } } @@ -206,8 +209,7 @@ EefcFlash::getBor() } #endif -bool -EefcFlash::getBootFlash() THROWS(GCodeException) +bool EefcFlash::getBootFlash() THROWS(GCodeException) { waitFSR(); writeFCR0(EEFC_FCMD_GGPB, 0); @@ -215,8 +217,7 @@ EefcFlash::getBootFlash() THROWS(GCodeException) return (readFRR0() & (1 << (_canBrownout ? 3 : 1))); } -void -EefcFlash::writeOptions() THROWS(GCodeException) +void EefcFlash::writeOptions() THROWS(GCodeException) { if (canBootFlash() && _bootFlash.isDirty() && _bootFlash.get() != getBootFlash()) { @@ -237,29 +238,23 @@ EefcFlash::writeOptions() THROWS(GCodeException) #endif if (_regions.isDirty()) { - uint32_t page; - Vector<bool, 16> current; - - if (_regions.get().Size() > _lockRegions) - throw FlashRegionError("EefcFlash::writeOptions: FlashRegionError"); + Bitmap<uint32_t> current = getLockRegions(); - current = getLockRegions(); - - for (uint32_t region = 0; region < _lockRegions; region++) + for (uint32_t region = 0; region < _numLockRegions; region++) { - if (_regions.get()[region] != current[region]) + if (_regions.get().IsBitSet(region) != current.IsBitSet(region)) { - if (_planes == 2 && region >= _lockRegions / 2) + if (_planes == 2 && region >= _numLockRegions / 2) { - page = (region - _lockRegions / 2) * _pages / _lockRegions; + const uint32_t page = (region - _numLockRegions / 2) * _pages / _numLockRegions; waitFSR(); - writeFCR1(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page); + writeFCR1(_regions.get().IsBitSet(region) ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page); } else { - page = region * _pages / _lockRegions; + const uint32_t page = region * _pages / _numLockRegions; waitFSR(); - writeFCR0(_regions.get()[region] ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page); + writeFCR0(_regions.get().IsBitSet(region) ? EEFC_FCMD_SLB : EEFC_FCMD_CLB, page); } } } @@ -273,8 +268,7 @@ EefcFlash::writeOptions() THROWS(GCodeException) #endif } -void -EefcFlash::writePage(uint32_t page) THROWS(GCodeException) +void EefcFlash::writePage(uint32_t page) THROWS(GCodeException) { if (page >= _pages) throw FlashPageError("EefcFlash::writePage: FlashPageError"); @@ -285,13 +279,16 @@ EefcFlash::writePage(uint32_t page) THROWS(GCodeException) waitFSR(); _wordCopy.runv(); if (_planes == 2 && page >= _pages / 2) + { writeFCR1(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page - _pages / 2); + } else + { writeFCR0(_eraseAuto ? EEFC_FCMD_EWP : EEFC_FCMD_WP, page); + } } -void -EefcFlash::readPage(uint32_t page, uint8_t* data) THROWS(GCodeException) +void EefcFlash::readPage(uint32_t page, uint8_t* data) THROWS(GCodeException) { if (page >= _pages) throw FlashPageError("EefcFlash::readPage: FlashPageError"); @@ -306,16 +303,14 @@ EefcFlash::readPage(uint32_t page, uint8_t* data) THROWS(GCodeException) _samba.read(_onBufferA ? _pageBufferA : _pageBufferB, data, _size); } -void -EefcFlash::waitFSR(int seconds) THROWS(GCodeException) +void EefcFlash::waitFSR(int seconds) THROWS(GCodeException) { int tries = seconds * 1000; - uint32_t fsr0; uint32_t fsr1 = 0x1; while (tries-- > 0) { - fsr0 = _samba.readWord(EEFC0_FSR); + uint32_t fsr0 = _samba.readWord(EEFC0_FSR); if (fsr0 & 0x2) throw FlashCmdError("EefcFlash::waitFSR: FlashCmdError 1"); if (fsr0 & 0x4) @@ -337,26 +332,22 @@ EefcFlash::waitFSR(int seconds) THROWS(GCodeException) throw FlashTimeoutError("EefcFlash::waitFSR: FlashTimeoutError"); } -void -EefcFlash::writeFCR0(uint8_t cmd, uint32_t arg) THROWS(GCodeException) +void EefcFlash::writeFCR0(uint8_t cmd, uint32_t arg) THROWS(GCodeException) { _samba.writeWord(EEFC0_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd); } -void -EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg) THROWS(GCodeException) +void EefcFlash::writeFCR1(uint8_t cmd, uint32_t arg) THROWS(GCodeException) { _samba.writeWord(EEFC1_FCR, (EEFC_KEY << 24) | (arg << 8) | cmd); } -uint32_t -EefcFlash::readFRR0() THROWS(GCodeException) +uint32_t EefcFlash::readFRR0() THROWS(GCodeException) { return _samba.readWord(EEFC0_FRR); } -uint32_t -EefcFlash::readFRR1() THROWS(GCodeException) +uint32_t EefcFlash::readFRR1() THROWS(GCodeException) { return _samba.readWord(EEFC1_FRR); } diff --git a/src/bossa/EefcFlash.h b/src/bossa/EefcFlash.h index a92241e6..4c277b82 100644 --- a/src/bossa/EefcFlash.h +++ b/src/bossa/EefcFlash.h @@ -42,7 +42,7 @@ public: uint32_t pages, uint32_t size, uint32_t planes, - uint32_t lockRegions, + uint32_t numLockRegions, uint32_t user, uint32_t stack, uint32_t regs, @@ -52,22 +52,18 @@ public: void eraseAll(uint32_t offset) THROWS(GCodeException) override; void eraseAuto(bool enable) noexcept override; - Vector<bool, 16> getLockRegions() THROWS(GCodeException) override; + Bitmap<uint32_t> getLockRegions() THROWS(GCodeException) override; #if ORIGINAL_BOSSA_CODE bool getSecurity(); - - bool getBod(); -#endif - bool canBod() noexcept override { return _canBrownout; } - -#if ORIGINAL_BOSSA_CODE bool getBor(); + bool getBod(); + bool canBor() const noexcept override { return _canBrownout; } #endif - bool canBor() noexcept override { return _canBrownout; } + bool canBod() const noexcept override { return _canBrownout; } bool getBootFlash() THROWS(GCodeException) override; - bool canBootFlash() noexcept override { return true; } + bool canBootFlash() const noexcept override { return true; } void writeOptions() THROWS(GCodeException) override; diff --git a/src/bossa/Flasher.cpp b/src/bossa/Flasher.cpp index 4b611874..f0f6a44b 100644 --- a/src/bossa/Flasher.cpp +++ b/src/bossa/Flasher.cpp @@ -176,7 +176,7 @@ void Flasher::lock(/* string& regionArg, */ bool enable) THROWS(GCodeException) { _observer.onStatus("%s all regions\n", enable ? "Lock" : "Unlock"); #endif - Vector<bool, 16> regions(_flash->lockRegions(), enable); + Bitmap<uint32_t> regions = Bitmap<uint32_t>::MakeLowestNBits((enable) ? _flash->getNumLockRegions() : 0); _flash->setLockRegions(regions); #if ORIGINAL_BOSSA_CODE } diff --git a/src/bossa/SerialPort.h b/src/bossa/SerialPort.h index e4cc5236..f29cb925 100644 --- a/src/bossa/SerialPort.h +++ b/src/bossa/SerialPort.h @@ -57,8 +57,6 @@ public: StopBit stop = StopBitOne) noexcept = 0; virtual void close() noexcept = 0; - virtual bool isUsb() noexcept = 0; - virtual int read(uint8_t* data, int size) noexcept = 0; virtual int write(const uint8_t* data, int size) noexcept = 0; virtual int get() noexcept = 0; @@ -66,8 +64,6 @@ public: virtual bool timeout(int millisecs) noexcept = 0; virtual void flush() noexcept = 0; - virtual void setDTR(bool dtr) noexcept = 0; - virtual void setRTS(bool rts) noexcept = 0; }; #endif // _SERIALPORT_H diff --git a/src/libc/errno.c b/src/libc/errno.c new file mode 100644 index 00000000..0ba05c99 --- /dev/null +++ b/src/libc/errno.c @@ -0,0 +1,17 @@ +/* + * errno.c + * + * Created on: 1 Oct 2022 + * Author: David + * + * This file replaces the one in newlib in order to avoid pulling the reent struct + */ + +static int globalErrno = 0; + +int * __errno () noexcept +{ + return &globalErrno; +} + +// End diff --git a/src/libc/nano-mallocr.c b/src/libc/nano-mallocr.c index 4b69b6d4..b5c3c1c4 100644 --- a/src/libc/nano-mallocr.c +++ b/src/libc/nano-mallocr.c @@ -32,9 +32,13 @@ * Interface documentation refer to malloc.c. */ +#if 0 // DC we don't want to pull in stdio #include <stdio.h> +#endif #include <string.h> +#if 0 // DC we don't want to pull in errno because it pulls in the reent struct #include <errno.h> +#endif #include <malloc.h> #if 1 // DC @@ -57,6 +61,7 @@ #include <assert.h> #else #define assert(x) ((void)0) +#include <stdint.h> extern void vAssertCalled(uint32_t line, const char *file) noexcept; #endif @@ -116,9 +121,9 @@ extern void ReleaseMallocMutex(); #else #define MALLOC_LOCK #define MALLOC_UNLOCK -#endif #define RERRNO errno +#endif #define nano_malloc malloc #define nano_free free @@ -279,7 +284,9 @@ void * nano_malloc(RARG malloc_size_t s) if (alloc_size >= MAX_ALLOC_SIZE || alloc_size < s) { +#if 0 // DC RERRNO = ENOMEM; +#endif return NULL; } @@ -328,7 +335,9 @@ void * nano_malloc(RARG malloc_size_t s) /* sbrk returns -1 if fail to allocate */ if (r == (void *)-1) { +#if 0 // DC RERRNO = ENOMEM; +#endif MALLOC_UNLOCK; return NULL; } |