Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hammacher <bmasterc@gmail.com>2022-10-28 11:49:51 +0300
committerChristian Hammacher <bmasterc@gmail.com>2022-10-28 11:49:51 +0300
commitea1c2d1c15a7fb34dd1e8d4ff18b56d6e481fc06 (patch)
treed6650b8cf3d9667a34cd211f4fd5f47a6b6a3492
parent03edcc635b371c118ea217086142d7bf26f833c4 (diff)
parentd4bea3d3c623da8ae91484ab3a87d006e078cabb (diff)
Merge remote-tracking branch 'origin/3.5-dev' into v3-chrishamm
-rw-r--r--src/CAN/CanInterface.cpp10
-rw-r--r--src/CAN/CommandProcessor.cpp11
-rw-r--r--src/Comms/PanelDueUpdater.cpp4
-rw-r--r--src/Display/ButtonMenuItem.h3
-rw-r--r--src/Display/FilesMenuItem.h3
-rw-r--r--src/Display/ImageMenuItem.h3
-rw-r--r--src/Display/TextMenuItem.h3
-rw-r--r--src/Display/ValueMenuItem.h3
-rw-r--r--src/Endstops/EndstopsManager.cpp2
-rw-r--r--src/Fans/LedStripDriver.cpp2
-rw-r--r--src/GCodes/CollisionAvoider.cpp15
-rw-r--r--src/GCodes/CollisionAvoider.h2
-rw-r--r--src/GCodes/GCodeBuffer/BinaryParser.cpp37
-rw-r--r--src/GCodes/GCodeBuffer/BinaryParser.h3
-rw-r--r--src/GCodes/GCodeBuffer/ExpressionParser.cpp28
-rw-r--r--src/GCodes/GCodeBuffer/GCodeBuffer.cpp7
-rw-r--r--src/GCodes/GCodeBuffer/GCodeBuffer.h8
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.cpp66
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.h20
-rw-r--r--src/GCodes/GCodes.cpp308
-rw-r--r--src/GCodes/GCodes.h92
-rw-r--r--src/GCodes/GCodes2.cpp155
-rw-r--r--src/GCodes/GCodes3.cpp23
-rw-r--r--src/GCodes/GCodes4.cpp80
-rw-r--r--src/GCodes/GCodes5.cpp14
-rw-r--r--src/Hardware/SAM4E/sam4e8e_flash.ld3
-rw-r--r--src/Heating/Heater.cpp76
-rw-r--r--src/Heating/Heater.h6
-rw-r--r--src/Heating/HeaterMonitor.cpp2
-rw-r--r--src/Heating/HeaterMonitor.h2
-rw-r--r--src/Heating/RemoteHeater.cpp2
-rw-r--r--src/Movement/AxisShaper.cpp2
-rw-r--r--src/Movement/DDA.cpp10
-rw-r--r--src/Movement/DDA.h2
-rw-r--r--src/Movement/DDARing.cpp8
-rw-r--r--src/Movement/DDARing.h1
-rw-r--r--src/Movement/Move.cpp5
-rw-r--r--src/Movement/Move.h1
-rw-r--r--src/Movement/RawMove.h1
-rw-r--r--src/Networking/ESP8266WiFi/WiFiInterface.cpp2
-rw-r--r--src/Networking/MulticastDiscovery/MulticastResponder.cpp47
-rw-r--r--src/Networking/Network.cpp24
-rw-r--r--src/Platform/Platform.cpp24
-rw-r--r--src/Platform/Platform.h3
-rw-r--r--src/PrintMonitor/PrintMonitor.cpp4
-rw-r--r--src/RepRapFirmware.h27
-rw-r--r--src/SBC/SbcInterface.cpp4
-rw-r--r--src/Storage/FileInfoParser.cpp2
-rw-r--r--src/bossa/BossaFlash.cpp29
-rw-r--r--src/bossa/BossaFlash.h49
-rw-r--r--src/bossa/Device.cpp12
-rw-r--r--src/bossa/Device.h2
-rw-r--r--src/bossa/EefcFlash.cpp97
-rw-r--r--src/bossa/EefcFlash.h16
-rw-r--r--src/bossa/Flasher.cpp2
-rw-r--r--src/bossa/SerialPort.h4
-rw-r--r--src/libc/errno.c17
-rw-r--r--src/libc/nano-mallocr.c11
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;
}