diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Endstops/Endstop.cpp | 23 | ||||
-rw-r--r-- | src/Endstops/Endstop.h | 8 | ||||
-rw-r--r-- | src/Endstops/EndstopDefs.h | 20 | ||||
-rw-r--r-- | src/Endstops/EndstopsManager.cpp | 101 | ||||
-rw-r--r-- | src/Endstops/EndstopsManager.h | 28 | ||||
-rw-r--r-- | src/Endstops/ZProbe.cpp | 68 | ||||
-rw-r--r-- | src/Endstops/ZProbe.h | 6 | ||||
-rw-r--r-- | src/Endstops/ZProbeEndstop.cpp | 4 | ||||
-rw-r--r-- | src/GCodes/GCodeException.cpp | 2 | ||||
-rw-r--r-- | src/GCodes/GCodeException.h | 10 | ||||
-rw-r--r-- | src/GCodes/GCodeInput.cpp | 32 | ||||
-rw-r--r-- | src/GCodes/GCodeInput.h | 48 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 6 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 8 | ||||
-rw-r--r-- | src/GCodes/GCodes3.cpp | 6 | ||||
-rw-r--r-- | src/GCodes/GCodes4.cpp | 231 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 18 | ||||
-rw-r--r-- | src/Platform.cpp | 4 | ||||
-rw-r--r-- | src/Platform.h | 2 | ||||
-rw-r--r-- | src/RepRap.cpp | 27 | ||||
-rw-r--r-- | src/Version.h | 2 |
21 files changed, 416 insertions, 238 deletions
diff --git a/src/Endstops/Endstop.cpp b/src/Endstops/Endstop.cpp index ea4cf5a3..f80cdca9 100644 --- a/src/Endstops/Endstop.cpp +++ b/src/Endstops/Endstop.cpp @@ -10,6 +10,29 @@ // Endstop base class DriversBitmap EndstopOrZProbe::stalledDrivers = 0; // used to track which drivers are reported as stalled, for stall detect endstops and stall detect Z probes +#if SUPPORT_OBJECT_MODEL + +// Object model table and functions +// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17. +// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM. + +// Macro to build a standard lambda function that includes the necessary type conversions +#define OBJECT_MODEL_FUNC(...) OBJECT_MODEL_FUNC_BODY(Endstop, __VA_ARGS__) + +constexpr ObjectModelTableEntry Endstop::objectModelTable[] = +{ + // Within each group, these entries must be in alphabetical order + // 0. Endstop members + { "triggered", OBJECT_MODEL_FUNC(self->Stopped() == EndStopHit::atStop), ObjectModelEntryFlags::live }, + { "type", OBJECT_MODEL_FUNC(self->GetEndstopType().ToString()), ObjectModelEntryFlags::none }, +}; + +constexpr uint8_t Endstop::objectModelTableDescriptor[] = { 1, 2 }; + +DEFINE_GET_OBJECT_MODEL_TABLE(Endstop) + +#endif + Endstop::Endstop(uint8_t p_axis, EndStopPosition pos) noexcept : axis(p_axis), atHighEnd(pos == EndStopPosition::highEndStop) { } diff --git a/src/Endstops/Endstop.h b/src/Endstops/Endstop.h index fc84de1c..d4c8ee17 100644 --- a/src/Endstops/Endstop.h +++ b/src/Endstops/Endstop.h @@ -8,16 +8,17 @@ #ifndef SRC_ENDSTOPS_ENDSTOP_H_ #define SRC_ENDSTOPS_ENDSTOP_H_ -#include "RepRapFirmware.h" +#include <RepRapFirmware.h> +#include <ObjectModel/ObjectModel.h> #include "EndstopDefs.h" -#include "Hardware/IoPorts.h" +#include <Hardware/IoPorts.h> #include <General/FreelistManager.h> class AxisDriversConfig; class CanMessageBuffer; // This is the base class for all types of endstops and for ZProbe. -class EndstopOrZProbe +class EndstopOrZProbe INHERIT_OBJECT_MODEL { public: EndstopOrZProbe() noexcept : next(nullptr) {} @@ -72,6 +73,7 @@ public: protected: Endstop(uint8_t axis, EndStopPosition pos) noexcept; + DECLARE_OBJECT_MODEL private: uint8_t axis; // which axis this endstop is on diff --git a/src/Endstops/EndstopDefs.h b/src/Endstops/EndstopDefs.h index 394f47b5..97eb1dc6 100644 --- a/src/Endstops/EndstopDefs.h +++ b/src/Endstops/EndstopDefs.h @@ -8,6 +8,8 @@ #ifndef SRC_ENDSTOPS_ENDSTOPDEFS_H_ #define SRC_ENDSTOPS_ENDSTOPDEFS_H_ +#include <NamedEnum.h> + // Forward declarations class EndstopOrZProbe; class Endstop; @@ -53,15 +55,15 @@ enum class EndStopPosition : unsigned int }; // Type of an endstop input - values must tally with the M574 command S parameter -enum class EndStopType : unsigned int -{ - unused_wasActiveLow = 0, - inputPin = 1, - zProbeAsEndstop = 2, - motorStallAny = 3, - motorStallIndividual = 4, - numInputTypes = 5 -}; +NamedEnum +( EndStopType, unsigned int, + unused_wasActiveLow, + inputPin, + zProbeAsEndstop, + motorStallAny, + motorStallIndividual, + numInputTypes +); // This is used as the return type of function Stopped. // Note the ordering: we need more-stopped-value > less-stopped-value diff --git a/src/Endstops/EndstopsManager.cpp b/src/Endstops/EndstopsManager.cpp index a6a8460e..a890012e 100644 --- a/src/Endstops/EndstopsManager.cpp +++ b/src/Endstops/EndstopsManager.cpp @@ -26,7 +26,47 @@ # include "CanMessageBuffer.h" #endif -ReadWriteLock EndstopsManager::endstopsLock; // used to lock both endstops and Z probes +ReadWriteLock EndstopsManager::endstopsLock; +ReadWriteLock EndstopsManager::zProbesLock; + +#if SUPPORT_OBJECT_MODEL + +// Object model table and functions +// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17. +// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM. + +// Macro to build a standard lambda function that includes the necessary type conversions +#define OBJECT_MODEL_FUNC(...) OBJECT_MODEL_FUNC_BODY(EndstopsManager, __VA_ARGS__) + +constexpr ObjectModelArrayDescriptor EndstopsManager::endstopsArrayDescriptor = +{ + &endstopsLock, + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return reprap.GetGCodes().GetVisibleAxes(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue(((const EndstopsManager*)self)->FindEndstop(context.GetLastIndex()).Ptr()); } +}; + +constexpr ObjectModelArrayDescriptor EndstopsManager::probesArrayDescriptor = +{ + &zProbesLock, + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const EndstopsManager*)self)->GetNumProbesToReport(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue(((const EndstopsManager*)self)->GetZProbe(context.GetLastIndex()).Ptr()); } +}; + +constexpr ObjectModelTableEntry EndstopsManager::objectModelTable[] = +{ + // Within each group, these entries must be in alphabetical order + // 0. sensors members + { "endstops", OBJECT_MODEL_FUNC_NOSELF(&endstopsArrayDescriptor), ObjectModelEntryFlags::live }, + { "probes", OBJECT_MODEL_FUNC_NOSELF(&probesArrayDescriptor), ObjectModelEntryFlags::live }, +}; + +constexpr uint8_t EndstopsManager::objectModelTableDescriptor[] = { 1, 2 }; + +DEFINE_GET_OBJECT_MODEL_TABLE(EndstopsManager) + +#endif EndstopsManager::EndstopsManager() noexcept : activeEndstops(nullptr), extrudersEndstop(nullptr), isHomingMove(false) { @@ -68,6 +108,35 @@ void EndstopsManager::Init() noexcept currentZProbeNumber = 0; } +ReadLockedPointer<Endstop> EndstopsManager::FindEndstop(size_t axis) const noexcept +{ + ReadLocker lock(endstopsLock); + return ReadLockedPointer<Endstop>(lock, (axis < MaxAxes) ? axisEndstops[axis] : nullptr); +} + +ReadLockedPointer<ZProbe> EndstopsManager::GetZProbe(size_t index) const noexcept +{ + ReadLocker lock(zProbesLock); + return ReadLockedPointer<ZProbe>(lock, (index < ARRAY_SIZE(zProbes)) ? zProbes[index] : nullptr); +} + +// Return the current Z probe if there is one, else a default Z probe +ReadLockedPointer<ZProbe> EndstopsManager::GetCurrentOrDefaultZProbe() const noexcept +{ + ReadLocker lock(zProbesLock); + return ReadLockedPointer<ZProbe>(lock, + (currentZProbeNumber < ARRAY_SIZE(zProbes) && zProbes[currentZProbeNumber] != nullptr) + ? zProbes[currentZProbeNumber] + : defaultZProbe); +} + +ZProbe& EndstopsManager::GetCurrentOrDefaultZProbeFromISR() const noexcept +{ + return (currentZProbeNumber < ARRAY_SIZE(zProbes) && zProbes[currentZProbeNumber] != nullptr) + ? *zProbes[currentZProbeNumber] + : *defaultZProbe; +} + // Add an endstop to the active list void EndstopsManager::AddToActive(EndstopOrZProbe& e) noexcept { @@ -320,7 +389,7 @@ GCodeResult EndstopsManager::HandleM574(GCodeBuffer& gb, const StringRef& reply, } else { - switch (inputType) + switch (inputType.ToBaseType()) { case EndStopType::motorStallAny: // Asking for stall detection endstop, so we can delete any existing endstop(s) and create new ones @@ -393,7 +462,7 @@ void EndstopsManager::GetM119report(const StringRef& reply) noexcept : TranslateEndStopResult(axisEndstops[axis]->Stopped(), axisEndstops[axis]->GetAtHighEnd()); reply.catf("%c: %s, ", reprap.GetGCodes().GetAxisLetters()[axis], status); } - reply.catf("Z probe: %s", TranslateEndStopResult(GetCurrentZProbe().Stopped(), false)); + reply.catf("Z probe: %s", TranslateEndStopResult(GetCurrentOrDefaultZProbe()->Stopped(), false)); } const char *EndstopsManager::TranslateEndStopResult(EndStopHit es, bool atHighEnd) noexcept @@ -412,17 +481,6 @@ const char *EndstopsManager::TranslateEndStopResult(EndStopHit es, bool atHighEn } } -ZProbe& EndstopsManager::GetCurrentZProbe() const noexcept -{ - ZProbe * const zp = (currentZProbeNumber < MaxZProbes) ? zProbes[currentZProbeNumber] : nullptr; - return (zp == nullptr) ? *defaultZProbe : *zp; -} - -ZProbe *EndstopsManager::GetZProbe(size_t num) const noexcept -{ - return (num < ARRAY_SIZE(zProbes)) ? zProbes[num] : nullptr; -} - void EndstopsManager::SetZProbeDefaults() noexcept { zProbes[0]->SetDefaults(); @@ -625,6 +683,21 @@ GCodeResult EndstopsManager::HandleG31(GCodeBuffer& gb, const StringRef& reply) return zProbes[probeNumber]->HandleG31(gb, reply); } +#if SUPPORT_OBJECT_MODEL + +size_t EndstopsManager::GetNumProbesToReport() const noexcept +{ + size_t ret = MaxZProbes; + while (ret != 0 && zProbes[ret - 1] == nullptr) + { + --ret; + } + return ret; +} + +#endif + + #if SUPPORT_CAN_EXPANSION // Handle signalling of a remote switch change, when the handle indicates that it is being used as an endstop. diff --git a/src/Endstops/EndstopsManager.h b/src/Endstops/EndstopsManager.h index 0c8d0313..0ee184af 100644 --- a/src/Endstops/EndstopsManager.h +++ b/src/Endstops/EndstopsManager.h @@ -8,9 +8,10 @@ #ifndef SRC_ENDSTOPS_ENDSTOPMANAGER_H_ #define SRC_ENDSTOPS_ENDSTOPMANAGER_H_ -#include "RepRapFirmware.h" +#include <RepRapFirmware.h> #include "EndstopDefs.h" -#include "GCodes/GCodeResult.h" +#include <GCodes/GCodeResult.h> +#include <ObjectModel/ObjectModel.h> #include <RTOSIface/RTOSIface.h> #if SUPPORT_CAN_EXPANSION @@ -21,7 +22,7 @@ class CanMessageBuffer; class StallDetectionEndstop; // Endstop manager class -class EndstopsManager +class EndstopsManager INHERIT_OBJECT_MODEL { public: EndstopsManager() noexcept; @@ -57,9 +58,11 @@ public: GCodeResult HandleM558(GCodeBuffer& gb, const StringRef &reply) THROWS_GCODE_EXCEPTION; // M558 GCodeResult HandleG31(GCodeBuffer& gb, const StringRef& reply) THROWS_GCODE_EXCEPTION; // G31 - ZProbe& GetCurrentZProbe() const noexcept; - const size_t GetCurrentZProbeNumber() const noexcept { return currentZProbeNumber; } - ZProbe *GetZProbe(size_t num) const noexcept; + ReadLockedPointer<ZProbe> GetZProbe(size_t index) const noexcept; + size_t GetCurrentZProbeNumber() const noexcept { return currentZProbeNumber; } + ReadLockedPointer<ZProbe> GetCurrentOrDefaultZProbe() const noexcept; + ZProbe& GetCurrentOrDefaultZProbeFromISR() const noexcept; + void SetZProbeDefaults() noexcept; GCodeResult ProgramZProbe(GCodeBuffer& gb, const StringRef& reply) THROWS_GCODE_EXCEPTION; @@ -73,17 +76,26 @@ public: bool WriteZProbeParameters(FileStore *f, bool includingG31) const noexcept; #endif +protected: + DECLARE_OBJECT_MODEL + OBJECT_MODEL_ARRAY(endstops) + OBJECT_MODEL_ARRAY(probes) + private: // Add an endstop to the active list void AddToActive(EndstopOrZProbe& e) noexcept; +#if SUPPORT_OBJECT_MODEL + size_t GetNumProbesToReport() const noexcept; +#endif + // Translate end stop result to text static const char *TranslateEndStopResult(EndStopHit es, bool atHighEnd) noexcept; - ReadLockedPointer<ZProbe> FindZProbe(size_t index) const noexcept; ReadLockedPointer<Endstop> FindEndstop(size_t axis) const noexcept; - static ReadWriteLock endstopsLock; // used to lock both endstops and Z probes + static ReadWriteLock endstopsLock; + static ReadWriteLock zProbesLock; EndstopOrZProbe * volatile activeEndstops; // linked list of endstops and Z probes that are active for the current move size_t currentZProbeNumber; // which Z probe we are using diff --git a/src/Endstops/ZProbe.cpp b/src/Endstops/ZProbe.cpp index 672f470c..d148cc5b 100644 --- a/src/Endstops/ZProbe.cpp +++ b/src/Endstops/ZProbe.cpp @@ -13,6 +13,63 @@ #include "Storage/FileStore.h" #include "Heating/Heat.h" +#if SUPPORT_OBJECT_MODEL + +// Object model table and functions +// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17. +// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM. + +// Macro to build a standard lambda function that includes the necessary type conversions +#define OBJECT_MODEL_FUNC(...) OBJECT_MODEL_FUNC_BODY(ZProbe, __VA_ARGS__) + +constexpr ObjectModelArrayDescriptor ZProbe::offsetsArrayDescriptor = +{ + nullptr, + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return 2; }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue((context.GetLastIndex() == 0) ? ((const ZProbe*)self)->xOffset : ((const ZProbe*)self)->yOffset); } +}; + +constexpr ObjectModelArrayDescriptor ZProbe::valueArrayDescriptor = +{ + nullptr, + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return (((const ZProbe*)self)->type == ZProbeType::dumbModulated) ? 2 : 1; }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { int v1 = 0; + return ExpressionValue + ( (context.GetLastIndex() == 0) + ? (int32_t)((const ZProbe*)self)->GetRawReading() + : (((const ZProbe*)self)->GetSecondaryValues(v1), v1) + ); + } +}; + +constexpr ObjectModelTableEntry ZProbe::objectModelTable[] = +{ + // Within each group, these entries must be in alphabetical order + // 0. Probe members + { "calibrationTemperature", OBJECT_MODEL_FUNC(self->calibTemperature), ObjectModelEntryFlags::none }, + { "disablesHeaters", OBJECT_MODEL_FUNC((bool)self->misc.parts.turnHeatersOff), ObjectModelEntryFlags::none }, + { "diveHeight", OBJECT_MODEL_FUNC(self->diveHeight), ObjectModelEntryFlags::none }, + { "maxProbeCount", OBJECT_MODEL_FUNC((int32_t)self->misc.parts.maxTaps), ObjectModelEntryFlags::none }, + { "offsets", OBJECT_MODEL_FUNC_NOSELF(&offsetsArrayDescriptor), ObjectModelEntryFlags::none }, + { "recoveryTime", OBJECT_MODEL_FUNC(self->recoveryTime), ObjectModelEntryFlags::none }, + { "speed", OBJECT_MODEL_FUNC(self->probeSpeed), ObjectModelEntryFlags::none }, + { "temperatureCoefficient", OBJECT_MODEL_FUNC(self->temperatureCoefficient), ObjectModelEntryFlags::none }, + { "threshold", OBJECT_MODEL_FUNC((int32_t)self->adcValue), ObjectModelEntryFlags::none }, + { "tolerance", OBJECT_MODEL_FUNC(self->tolerance), ObjectModelEntryFlags::none }, + { "travelSpeed", OBJECT_MODEL_FUNC(self->travelSpeed), ObjectModelEntryFlags::none }, + { "triggerHeight", OBJECT_MODEL_FUNC(self->triggerHeight), ObjectModelEntryFlags::none }, + { "type", OBJECT_MODEL_FUNC((int32_t)self->type), ObjectModelEntryFlags::none }, + { "value", OBJECT_MODEL_FUNC_NOSELF(&valueArrayDescriptor), ObjectModelEntryFlags::live }, +}; + +constexpr uint8_t ZProbe::objectModelTableDescriptor[] = { 1, 14 }; + +DEFINE_GET_OBJECT_MODEL_TABLE(ZProbe) + +#endif + ZProbe::ZProbe(unsigned int num, ZProbeType p_type) noexcept : EndstopOrZProbe(), number(num) { SetDefaults(); @@ -106,7 +163,7 @@ int ZProbe::GetReading() const noexcept return (misc.parts.invertReading) ? 1000 - zProbeVal : zProbeVal; } -int ZProbe::GetSecondaryValues(int& v1, int& v2) noexcept +int ZProbe::GetSecondaryValues(int& v1) const noexcept { const Platform& p = reprap.GetPlatform(); if (p.GetZProbeOnFilter().IsValid() && p.GetZProbeOffFilter().IsValid()) @@ -114,7 +171,7 @@ int ZProbe::GetSecondaryValues(int& v1, int& v2) noexcept switch (type) { case ZProbeType::dumbModulated: // modulated IR sensor - v1 = (int) (p.GetZProbeOnFilter().GetSum() / ZProbeAverageReadings); // pass back the reading with IR turned on + v1 = (int)(p.GetZProbeOnFilter().GetSum() / ZProbeAverageReadings); // pass back the reading with IR turned on return 1; default: break; @@ -245,15 +302,12 @@ GCodeResult ZProbe::HandleG31(GCodeBuffer& gb, const StringRef& reply) else { const int v0 = GetReading(); - int v1, v2; - switch (GetSecondaryValues(v1, v2)) + int v1; + switch (GetSecondaryValues(v1)) { case 1: reply.printf("Current reading %d (%d)", v0, v1); break; - case 2: - reply.printf("Current reading %d (%d, %d)", v0, v1, v2); - break; default: reply.printf("Current reading %d", v0); break; diff --git a/src/Endstops/ZProbe.h b/src/Endstops/ZProbe.h index 0e2b6801..364cd6bd 100644 --- a/src/Endstops/ZProbe.h +++ b/src/Endstops/ZProbe.h @@ -47,7 +47,7 @@ public: void SetProbingAway(const bool probingAway) noexcept { misc.parts.probingAway = probingAway; } int GetReading() const noexcept; - int GetSecondaryValues(int& v1, int& v2) noexcept; + int GetSecondaryValues(int& v1) const noexcept; GCodeResult HandleG31(GCodeBuffer& gb, const StringRef& reply) THROWS_GCODE_EXCEPTION; void SetTriggerHeight(float height) noexcept { triggerHeight = height; } @@ -60,6 +60,10 @@ public: static constexpr unsigned int MaxTapsLimit = 31; // must be low enough to fit in the maxTaps field protected: + DECLARE_OBJECT_MODEL + OBJECT_MODEL_ARRAY(offsets) + OBJECT_MODEL_ARRAY(value) + uint8_t number; ZProbeType type; int8_t sensor; // the sensor number used for temperature calibration diff --git a/src/Endstops/ZProbeEndstop.cpp b/src/Endstops/ZProbeEndstop.cpp index dc12dd5f..c4c919a0 100644 --- a/src/Endstops/ZProbeEndstop.cpp +++ b/src/Endstops/ZProbeEndstop.cpp @@ -20,8 +20,8 @@ ZProbeEndstop::ZProbeEndstop(uint8_t axis, EndStopPosition pos) noexcept : Endst // Test whether we are at or near the stop EndStopHit ZProbeEndstop::Stopped() const noexcept { - const ZProbe * const zp = reprap.GetPlatform().GetEndstops().GetZProbe(zProbeNumber); - return (zp != nullptr) ? zp->Stopped() : EndStopHit::atStop; + const auto zp = reprap.GetPlatform().GetEndstops().GetZProbe(zProbeNumber); + return (zp.IsNotNull()) ? zp->Stopped() : EndStopHit::atStop; } // This is called to prime axis endstops diff --git a/src/GCodes/GCodeException.cpp b/src/GCodes/GCodeException.cpp index 80024776..44e74a76 100644 --- a/src/GCodes/GCodeException.cpp +++ b/src/GCodes/GCodeException.cpp @@ -11,7 +11,7 @@ #include <GCodes/GCodeBuffer/GCodeBuffer.h> // Construct the error message. This will be prefixed with "Error: " when it is returned to the user. -void GCodeException::GetMessage(const StringRef &reply, const GCodeBuffer& gb) const +void GCodeException::GetMessage(const StringRef &reply, const GCodeBuffer& gb) const noexcept { reply.copy((gb.IsDoingFileMacro()) ? "in file macro" : (gb.IsDoingFile()) ? "in GCode file" : "while executing command"); if (line >= 0 && column >= 0 && gb.IsDoingFile()) diff --git a/src/GCodes/GCodeException.h b/src/GCodes/GCodeException.h index ad434132..f11d6e1d 100644 --- a/src/GCodes/GCodeException.h +++ b/src/GCodes/GCodeException.h @@ -16,24 +16,24 @@ class GCodeBuffer; class GCodeException { public: - GCodeException(int lin, int col, const char *msg) : line(lin), column(col), message(msg) { } + GCodeException(int lin, int col, const char *msg) noexcept : line(lin), column(col), message(msg) { } - GCodeException(int lin, int col, const char *msg, const char *sparam) : line(lin), column(col), message(msg) + GCodeException(int lin, int col, const char *msg, const char *sparam) noexcept : line(lin), column(col), message(msg) { param.s = sparam; } - GCodeException(int lin, int col, const char *msg, uint32_t uparam) : line(lin), column(col), message(msg) + GCodeException(int lin, int col, const char *msg, uint32_t uparam) noexcept : line(lin), column(col), message(msg) { param.u = uparam; } - GCodeException(int lin, int col, const char *msg, int32_t iparam) : line(lin), column(col), message(msg) + GCodeException(int lin, int col, const char *msg, int32_t iparam) noexcept : line(lin), column(col), message(msg) { param.i = iparam; } - void GetMessage(const StringRef& reply, const GCodeBuffer& gb) const; + void GetMessage(const StringRef& reply, const GCodeBuffer& gb) const noexcept; private: int line; diff --git a/src/GCodes/GCodeInput.cpp b/src/GCodes/GCodeInput.cpp index ea791712..efd079ee 100644 --- a/src/GCodes/GCodeInput.cpp +++ b/src/GCodes/GCodeInput.cpp @@ -12,7 +12,7 @@ #include "GCodeBuffer/GCodeBuffer.h" // Read some input bytes into the GCode buffer. Return true if there is a line of GCode waiting to be processed. -bool StandardGCodeInput::FillBuffer(GCodeBuffer *gb) +bool StandardGCodeInput::FillBuffer(GCodeBuffer *gb) noexcept { const size_t bytesToPass = min<size_t>(BytesCached(), GCODE_LENGTH); for (size_t i = 0; i < bytesToPass; i++) @@ -50,7 +50,7 @@ bool StandardGCodeInput::FillBuffer(GCodeBuffer *gb) // G-code input class for wrapping around Stream-based hardware ports -void StreamGCodeInput::Reset() +void StreamGCodeInput::Reset() noexcept { while (device.available() > 0) { @@ -58,30 +58,30 @@ void StreamGCodeInput::Reset() } } -char StreamGCodeInput::ReadByte() +char StreamGCodeInput::ReadByte() noexcept { return static_cast<char>(device.read()); } -size_t StreamGCodeInput::BytesCached() const +size_t StreamGCodeInput::BytesCached() const noexcept { return device.available(); } // Dynamic G-code input class for caching codes from software-defined sources -RegularGCodeInput::RegularGCodeInput() +RegularGCodeInput::RegularGCodeInput() noexcept : state(GCodeInputState::idle), writingPointer(0), readingPointer(0) { } -void RegularGCodeInput::Reset() +void RegularGCodeInput::Reset() noexcept { state = GCodeInputState::idle; writingPointer = readingPointer = 0; } -char RegularGCodeInput::ReadByte() +char RegularGCodeInput::ReadByte() noexcept { char c = buffer[readingPointer++]; if (readingPointer == GCodeInputBufferSize) @@ -92,7 +92,7 @@ char RegularGCodeInput::ReadByte() } -size_t RegularGCodeInput::BytesCached() const +size_t RegularGCodeInput::BytesCached() const noexcept { if (writingPointer >= readingPointer) { @@ -101,12 +101,12 @@ size_t RegularGCodeInput::BytesCached() const return GCodeInputBufferSize - readingPointer + writingPointer; } -size_t RegularGCodeInput::BufferSpaceLeft() const +size_t RegularGCodeInput::BufferSpaceLeft() const noexcept { return (readingPointer - writingPointer - 1u) % GCodeInputBufferSize; } -void NetworkGCodeInput::Put(MessageType mtype, char c) +void NetworkGCodeInput::Put(MessageType mtype, char c) noexcept { if (BufferSpaceLeft() == 0) { @@ -190,7 +190,7 @@ void NetworkGCodeInput::Put(MessageType mtype, char c) } } -void NetworkGCodeInput::Put(MessageType mtype, const char *buf) +void NetworkGCodeInput::Put(MessageType mtype, const char *buf) noexcept { const size_t len = strlen(buf) + 1; MutexLocker lock(bufMutex, 200); @@ -207,13 +207,13 @@ void NetworkGCodeInput::Put(MessageType mtype, const char *buf) } } -NetworkGCodeInput::NetworkGCodeInput() : RegularGCodeInput() +NetworkGCodeInput::NetworkGCodeInput() noexcept : RegularGCodeInput() { bufMutex.Create("NetworkGCodeInput"); } // Fill a GCodeBuffer with the last available G-code -bool NetworkGCodeInput::FillBuffer(GCodeBuffer *gb) /*override*/ +bool NetworkGCodeInput::FillBuffer(GCodeBuffer *gb) noexcept /*override*/ { MutexLocker lock(bufMutex, 10); return lock && RegularGCodeInput::FillBuffer(gb); @@ -224,14 +224,14 @@ bool NetworkGCodeInput::FillBuffer(GCodeBuffer *gb) /*override*/ // File-based G-code input source // Reset this input. Should be called when the associated file is being closed -void FileGCodeInput::Reset() +void FileGCodeInput::Reset() noexcept { lastFile = nullptr; RegularGCodeInput::Reset(); } // Reset this input. Should be called when a specific G-code or macro file is closed outside of the reading context -void FileGCodeInput::Reset(const FileData &file) +void FileGCodeInput::Reset(const FileData &file) noexcept { if (file.f == lastFile) { @@ -240,7 +240,7 @@ void FileGCodeInput::Reset(const FileData &file) } // Read another chunk of G-codes from the file and return true if more data is available -GCodeInputReadResult FileGCodeInput::ReadFromFile(FileData &file) +GCodeInputReadResult FileGCodeInput::ReadFromFile(FileData &file) noexcept { const size_t bytesCached = BytesCached(); diff --git a/src/GCodes/GCodeInput.h b/src/GCodes/GCodeInput.h index 5b432831..5c605096 100644 --- a/src/GCodes/GCodeInput.h +++ b/src/GCodes/GCodeInput.h @@ -13,39 +13,39 @@ #include "MessageType.h" #include "RTOSIface/RTOSIface.h" -const size_t GCodeInputBufferSize = 256; // How many bytes can we cache per input source? -const size_t GCodeInputFileReadThreshold = 128; // How many free bytes must be available before data is read from the SD card? +const size_t GCodeInputBufferSize = 256; // How many bytes can we cache per input source? +const size_t GCodeInputFileReadThreshold = 128; // How many free bytes must be available before data is read from the SD card? // This base class provides incoming G-codes for the GCodeBuffer class class GCodeInput { public: - virtual void Reset() = 0; // Clean all the cached data from this input - virtual bool FillBuffer(GCodeBuffer *gb) = 0; // Fill a GCodeBuffer with the last available G-code - virtual size_t BytesCached() const = 0; // How many bytes have been cached? + virtual void Reset() noexcept = 0; // Clean all the cached data from this input + virtual bool FillBuffer(GCodeBuffer *gb) noexcept = 0; // Fill a GCodeBuffer with the last available G-code + virtual size_t BytesCached() const noexcept = 0; // How many bytes have been cached? }; // This class provides a standard implementation of FillBuffer that calls ReadByte() to supply individual characters class StandardGCodeInput : public GCodeInput { public: - bool FillBuffer(GCodeBuffer *gb) override; // Fill a GCodeBuffer with the last available G-code + bool FillBuffer(GCodeBuffer *gb) noexcept override; // Fill a GCodeBuffer with the last available G-code protected: - virtual char ReadByte() = 0; // Get the next byte from the source + virtual char ReadByte() noexcept = 0; // Get the next byte from the source }; // This class wraps around an existing Stream device which lets us avoid double buffering. class StreamGCodeInput : public StandardGCodeInput { public: - StreamGCodeInput(Stream &dev) : device(dev) { } + StreamGCodeInput(Stream &dev) noexcept : device(dev) { } - void Reset() override; - size_t BytesCached() const override; // How many bytes have been cached? + void Reset() noexcept override; + size_t BytesCached() const noexcept override; // How many bytes have been cached? protected: - char ReadByte() override; + char ReadByte() noexcept override; private: Stream &device; @@ -73,14 +73,14 @@ enum class GCodeInputState class RegularGCodeInput : public StandardGCodeInput { public: - RegularGCodeInput(); + RegularGCodeInput() noexcept; - void Reset() override; - size_t BytesCached() const override; // How many bytes have been cached? - size_t BufferSpaceLeft() const; // How much space do we have left? + void Reset() noexcept override; + size_t BytesCached() const noexcept override; // How many bytes have been cached? + size_t BufferSpaceLeft() const noexcept; // How much space do we have left? protected: - char ReadByte() override; + char ReadByte() noexcept override; GCodeInputState state; size_t writingPointer, readingPointer; @@ -97,12 +97,12 @@ class FileGCodeInput : public RegularGCodeInput { public: - FileGCodeInput() : RegularGCodeInput(), lastFile(nullptr) { } + FileGCodeInput() noexcept : RegularGCodeInput(), lastFile(nullptr) { } - void Reset() override; // Clears the buffer. Should be called when the associated file is being closed - void Reset(const FileData &file); // Clears the buffer of a specific file. Should be called when it is closed or re-opened outside the reading context + void Reset() noexcept override; // Clears the buffer. Should be called when the associated file is being closed + void Reset(const FileData &file) noexcept; // Clears the buffer of a specific file. Should be called when it is closed or re-opened outside the reading context - GCodeInputReadResult ReadFromFile(FileData &file); // Read another chunk of G-codes from the file and return true if more data is available + GCodeInputReadResult ReadFromFile(FileData &file) noexcept; // Read another chunk of G-codes from the file and return true if more data is available private: FileStore *lastFile; @@ -114,13 +114,13 @@ private: class NetworkGCodeInput : public RegularGCodeInput { public: - NetworkGCodeInput(); + NetworkGCodeInput() noexcept; - bool FillBuffer(GCodeBuffer *gb) override; // Fill a GCodeBuffer with the last available G-code - void Put(MessageType mtype, const char *buf); // Append a null-terminated string to the buffer + bool FillBuffer(GCodeBuffer *gb) noexcept override; // Fill a GCodeBuffer with the last available G-code + void Put(MessageType mtype, const char *buf) noexcept; // Append a null-terminated string to the buffer private: - void Put(MessageType mtype, char c); // Append a single character. This does NOT lock the mutex! + void Put(MessageType mtype, char c) noexcept; // Append a single character. This does NOT lock the mutex! Mutex bufMutex; }; diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index a926657b..1df814ba 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -2583,7 +2583,8 @@ GCodeResult GCodes::ExecuteG30(GCodeBuffer& gb, const StringRef& reply) { // Do a Z probe at the specified point. gb.SetState(GCodeState::probingAtPoint0); - if (platform.GetCurrentZProbeType() != ZProbeType::none && platform.GetCurrentZProbeType() != ZProbeType::blTouch && !probeIsDeployed) + const ZProbeType t = platform.GetCurrentZProbeType(); + if (t != ZProbeType::none && t != ZProbeType::blTouch && !probeIsDeployed) { DoFileMacro(gb, DEPLOYPROBE_G, false, 30); } @@ -2654,7 +2655,8 @@ GCodeResult GCodes::ProbeGrid(GCodeBuffer& gb, const StringRef& reply) gridXindex = gridYindex = 0; gb.SetState(GCodeState::gridProbing1); - if (platform.GetCurrentZProbeType() != ZProbeType::none && platform.GetCurrentZProbeType() != ZProbeType::blTouch && !probeIsDeployed) + const ZProbeType t = platform.GetCurrentZProbeType(); + if (t != ZProbeType::none && t != ZProbeType::blTouch && !probeIsDeployed) { DoFileMacro(gb, DEPLOYPROBE_G, false, 29); } diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 06e3c961..2682321d 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -4086,15 +4086,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) case 851: // Set Z probe offset, only for Marlin compatibility { - ZProbe& zp = platform.GetCurrentZProbe(); + auto zp = platform.GetCurrentZProbe(); if (gb.Seen('Z')) { - zp.SetTriggerHeight(-gb.GetFValue()); - zp.SetSaveToConfigOverride(); + zp->SetTriggerHeight(-gb.GetFValue()); + zp->SetSaveToConfigOverride(); } else { - reply.printf("Z probe offset is %.2fmm", (double)(-zp.GetConfiguredTriggerHeight())); + reply.printf("Z probe offset is %.2fmm", (double)(-zp->GetConfiguredTriggerHeight())); } } break; diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index b45443a2..4b07516a 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -769,7 +769,7 @@ GCodeResult GCodes::StraightProbe(GCodeBuffer& gb, const StringRef& reply) const size_t probeToUse = gb.Seen('P') ? gb.GetUIValue() : platform.GetEndstops().GetCurrentZProbeNumber(); // Check if this probe exists to not run into a nullptr dereference later - if (platform.GetEndstops().GetZProbe(probeToUse) == nullptr) + if (platform.GetEndstops().GetZProbe(probeToUse).IsNull()) { reply.catf("Invalid probe number: %d", probeToUse); return GCodeResult::error; @@ -800,7 +800,7 @@ GCodeResult GCodes::ProbeTool(GCodeBuffer& gb, const StringRef& reply) if (useProbe) { probeNumberToUse = gb.GetUIValue(); - if (platform.GetEndstops().GetZProbe(probeNumberToUse) == nullptr) + if (platform.GetEndstops().GetZProbe(probeNumberToUse).IsNull()) { reply.copy("Invalid probe number"); return GCodeResult::error; @@ -879,7 +879,7 @@ GCodeResult GCodes::FindCenterOfCavity(GCodeBuffer& gb, const StringRef& reply, if (useProbe) { probeNumberToUse = gb.GetUIValue(); - if (platform.GetEndstops().GetZProbe(probeNumberToUse) == nullptr) + if (platform.GetEndstops().GetZProbe(probeNumberToUse).IsNull()) { reply.copy("Invalid probe number"); return GCodeResult::error; diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp index 652d54f9..33761417 100644 --- a/src/GCodes/GCodes4.cpp +++ b/src/GCodes/GCodes4.cpp @@ -475,11 +475,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (move.IsAccessibleProbePoint(x, y)) { SetMoveBufferDefaults(); - const ZProbe& zp = platform.GetCurrentZProbe(); - moveBuffer.coords[X_AXIS] = x - zp.GetXOffset(); - moveBuffer.coords[Y_AXIS] = y - zp.GetYOffset(); - moveBuffer.coords[Z_AXIS] = zp.GetStartingHeight(); - moveBuffer.feedRate = zp.GetTravelSpeed(); + const auto zp = platform.GetCurrentZProbe(); + moveBuffer.coords[X_AXIS] = x - zp->GetXOffset(); + moveBuffer.coords[Y_AXIS] = y - zp->GetYOffset(); + moveBuffer.coords[Z_AXIS] = zp->GetStartingHeight(); + moveBuffer.feedRate = zp->GetTravelSpeed(); NewMoveAvailable(1); tapsDone = 0; @@ -516,8 +516,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(gb)) { lastProbedTime = millis(); - const ZProbe& zp = platform.GetCurrentZProbe(); - if (zp.GetProbeType() != ZProbeType::none && zp.GetTurnHeatersOff()) + const auto zp = platform.GetCurrentZProbe(); + if (zp->GetProbeType() != ZProbeType::none && zp->GetTurnHeatersOff()) { reprap.GetHeat().SuspendHeaters(true); } @@ -527,12 +527,12 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) case GCodeState::gridProbing3: // ready to probe the current grid probe point { - const ZProbe& zp = platform.GetCurrentZProbe(); - if (millis() - lastProbedTime >= (uint32_t)(zp.GetRecoveryTime() * SecondsToMillis)) + const auto zp = platform.GetCurrentZProbe(); + if (millis() - lastProbedTime >= (uint32_t)(zp->GetRecoveryTime() * SecondsToMillis)) { // Probe the bed at the current XY coordinates // Check for probe already triggered at start - if (zp.GetProbeType() == ZProbeType::none) + if (zp->GetProbeType() == ZProbeType::none) { // No Z probe, so do manual mesh levelling instead UnlockAll(gb); // release the movement lock to allow manual Z moves @@ -540,12 +540,12 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) doingManualBedProbe = true; // suspend the Z movement limit DoManualBedProbe(gb); } - else if (platform.GetCurrentZProbe().Stopped() == EndStopHit::atStop) + else if (zp->Stopped() == EndStopHit::atStop) { reprap.GetHeat().SuspendHeaters(false); platform.Message(ErrorMessage, "Z probe already triggered before probing move started\n"); gb.SetState(GCodeState::normal); - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 29); } @@ -562,11 +562,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) gb.SetState(GCodeState::normal); break; } - platform.GetCurrentZProbe().SetProbing(true); + zp->SetProbing(true); moveBuffer.checkEndstops = true; moveBuffer.reduceAcceleration = true; - moveBuffer.coords[Z_AXIS] = -zp.GetDiveHeight() + zp.GetActualTriggerHeight(); - moveBuffer.feedRate = zp.GetProbingSpeed(); + moveBuffer.coords[Z_AXIS] = -zp->GetDiveHeight() + zp->GetActualTriggerHeight(); + moveBuffer.feedRate = zp->GetProbingSpeed(); NewMoveAvailable(1); gb.AdvanceState(); } @@ -580,32 +580,32 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) doingManualBedProbe = false; ++tapsDone; reprap.GetHeat().SuspendHeaters(false); - const ZProbe& zp = platform.GetCurrentZProbe(); - if (zp.GetProbeType() == ZProbeType::none) + const auto zp = platform.GetCurrentZProbe(); + if (zp->GetProbeType() == ZProbeType::none) { // No Z probe, so we are doing manual mesh levelling. Take the current Z height as the height error. g30zHeightError = moveBuffer.coords[Z_AXIS]; } else { - platform.GetCurrentZProbe().SetProbing(false); + zp->SetProbing(false); if (!zProbeTriggered) { platform.Message(ErrorMessage, "Z probe was not triggered during probing move\n"); gb.SetState(GCodeState::normal); - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 29); } break; } - g30zHeightError = moveBuffer.coords[Z_AXIS] - zp.GetActualTriggerHeight(); + g30zHeightError = moveBuffer.coords[Z_AXIS] - zp->GetActualTriggerHeight(); g30zHeightErrorSum += g30zHeightError; } gb.AdvanceState(); - if (platform.GetCurrentZProbeType() == ZProbeType::blTouch) + if (zp->GetProbeType() == ZProbeType::blTouch) { DoFileMacro(gb, RETRACTPROBE_G, false, 29); // bltouch needs to be retracted when it triggers } @@ -616,9 +616,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Move back up to the dive height SetMoveBufferDefaults(); { - const ZProbe& zp = platform.GetCurrentZProbe(); - moveBuffer.coords[Z_AXIS] = zp.GetStartingHeight(); - moveBuffer.feedRate = zp.GetTravelSpeed(); + const auto zp = platform.GetCurrentZProbe(); + moveBuffer.coords[Z_AXIS] = zp->GetStartingHeight(); + moveBuffer.feedRate = zp->GetTravelSpeed(); } NewMoveAvailable(1); gb.AdvanceState(); @@ -628,24 +628,24 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(gb)) { // See whether we need to do any more taps - const ZProbe& params = platform.GetCurrentZProbe(); + const auto zp = platform.GetCurrentZProbe(); bool acceptReading = false; - if (params.GetMaxTaps() < 2) + if (zp->GetMaxTaps() < 2) { acceptReading = true; } else if (tapsDone >= 2) { g30zHeightErrorLowestDiff = min<float>(g30zHeightErrorLowestDiff, fabsf(g30zHeightError - g30PrevHeightError)); - if (params.GetTolerance() > 0.0) + if (zp->GetTolerance() > 0.0) { - if (g30zHeightErrorLowestDiff <= params.GetTolerance()) + if (g30zHeightErrorLowestDiff <= zp->GetTolerance()) { g30zHeightError = (g30zHeightError + g30PrevHeightError)/2; acceptReading = true; } } - else if (tapsDone == params.GetMaxTaps()) + else if (tapsDone == zp->GetMaxTaps()) { g30zHeightError = g30zHeightErrorSum/tapsDone; acceptReading = true; @@ -657,7 +657,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) reprap.GetMove().AccessHeightMap().SetGridHeight(gridXindex, gridYindex, g30zHeightError); gb.AdvanceState(); } - else if (tapsDone < params.GetMaxTaps()) + else if (tapsDone < zp->GetMaxTaps()) { // Tap again lastProbedTime = millis(); @@ -668,7 +668,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) { platform.Message(ErrorMessage, "Z probe readings not consistent\n"); gb.SetState(GCodeState::normal); - if (params.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 29); } @@ -765,9 +765,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Initial state when executing G30 with a P parameter. Start by moving to the dive height at the current position. SetMoveBufferDefaults(); { - const ZProbe& zp = platform.GetCurrentZProbe(); - moveBuffer.coords[Z_AXIS] = zp.GetStartingHeight(); - moveBuffer.feedRate = zp.GetTravelSpeed(); + const auto zp = platform.GetCurrentZProbe(); + moveBuffer.coords[Z_AXIS] = zp->GetStartingHeight(); + moveBuffer.feedRate = zp->GetTravelSpeed(); } NewMoveAvailable(1); gb.AdvanceState(); @@ -780,9 +780,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Head is at the dive height but needs to be moved to the correct XY position. The XY coordinates have already been stored. SetMoveBufferDefaults(); (void)reprap.GetMove().GetProbeCoordinates(g30ProbePointIndex, moveBuffer.coords[X_AXIS], moveBuffer.coords[Y_AXIS], true); - const ZProbe& zp = platform.GetCurrentZProbe(); - moveBuffer.coords[Z_AXIS] = zp.GetStartingHeight(); - moveBuffer.feedRate = zp.GetTravelSpeed(); + const auto zp = platform.GetCurrentZProbe(); + moveBuffer.coords[Z_AXIS] = zp->GetStartingHeight(); + moveBuffer.feedRate = zp->GetTravelSpeed(); NewMoveAvailable(1); InitialiseTaps(); @@ -808,7 +808,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) { // Head has finished moving to the correct XY position lastProbedTime = millis(); // start the probe recovery timer - if (platform.GetCurrentZProbe().GetTurnHeatersOff()) + if (platform.GetCurrentZProbe()->GetTurnHeatersOff()) { reprap.GetHeat().SuspendHeaters(true); } @@ -819,54 +819,56 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) case GCodeState::probingAtPoint3: // Executing G30 with a P parameter. The move to put the head at the specified XY coordinates has been completed and the recovery timer started. // OR executing G30 without a P parameter, and the recovery timer has been started. - if (millis() - lastProbedTime >= (uint32_t)(platform.GetCurrentZProbe().GetRecoveryTime() * SecondsToMillis)) { - // The probe recovery time has elapsed, so we can start the probing move - const ZProbe& zp = platform.GetCurrentZProbe(); - if (zp.GetProbeType() == ZProbeType::none) - { - // No Z probe, so we are doing manual 'probing' - UnlockAll(gb); // release the movement lock to allow manual Z moves - gb.AdvanceState(); // resume at the next state when the user has finished - doingManualBedProbe = true; // suspend the Z movement limit - DoManualBedProbe(gb); - } - else if (platform.GetCurrentZProbe().Stopped() == EndStopHit::atStop) // check for probe already triggered at start + const auto zp = platform.GetCurrentZProbe(); + if (millis() - lastProbedTime >= (uint32_t)(zp->GetRecoveryTime() * SecondsToMillis)) { - // Z probe is already triggered at the start of the move, so abandon the probe and record an error - reprap.GetHeat().SuspendHeaters(false); - platform.Message(ErrorMessage, "Z probe already triggered at start of probing move\n"); - if (g30ProbePointIndex >= 0) + // The probe recovery time has elapsed, so we can start the probing move + if (zp->GetProbeType() == ZProbeType::none) { - reprap.GetMove().SetZBedProbePoint(g30ProbePointIndex, zp.GetDiveHeight(), true, true); + // No Z probe, so we are doing manual 'probing' + UnlockAll(gb); // release the movement lock to allow manual Z moves + gb.AdvanceState(); // resume at the next state when the user has finished + doingManualBedProbe = true; // suspend the Z movement limit + DoManualBedProbe(gb); } - gb.SetState(GCodeState::normal); // no point in doing anything else - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + else if (zp->Stopped() == EndStopHit::atStop) // check for probe already triggered at start { - DoFileMacro(gb, RETRACTPROBE_G, false, 30); + // Z probe is already triggered at the start of the move, so abandon the probe and record an error + reprap.GetHeat().SuspendHeaters(false); + platform.Message(ErrorMessage, "Z probe already triggered at start of probing move\n"); + if (g30ProbePointIndex >= 0) + { + reprap.GetMove().SetZBedProbePoint(g30ProbePointIndex, zp->GetDiveHeight(), true, true); + } + gb.SetState(GCodeState::normal); // no point in doing anything else + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) + { + DoFileMacro(gb, RETRACTPROBE_G, false, 30); + } } - } - else - { - zProbeTriggered = false; - SetMoveBufferDefaults(); - if (!platform.GetEndstops().EnableCurrentZProbe()) + else { - error = true; - reply.copy("Failed to enable Z probe"); - gb.SetState(GCodeState::normal); - break; - } + zProbeTriggered = false; + SetMoveBufferDefaults(); + if (!platform.GetEndstops().EnableCurrentZProbe()) + { + error = true; + reply.copy("Failed to enable Z probe"); + gb.SetState(GCodeState::normal); + break; + } - platform.GetCurrentZProbe().SetProbing(true); - moveBuffer.checkEndstops = true; - moveBuffer.reduceAcceleration = true; - moveBuffer.coords[Z_AXIS] = (IsAxisHomed(Z_AXIS)) - ? 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 - moveBuffer.feedRate = zp.GetProbingSpeed(); - NewMoveAvailable(1); - gb.AdvanceState(); + zp->SetProbing(true); + moveBuffer.checkEndstops = true; + moveBuffer.reduceAcceleration = true; + moveBuffer.coords[Z_AXIS] = (IsAxisHomed(Z_AXIS)) + ? 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 + moveBuffer.feedRate = zp->GetProbingSpeed(); + NewMoveAvailable(1); + gb.AdvanceState(); + } } } break; @@ -880,15 +882,15 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) doingManualBedProbe = false; hadProbingError = false; ++tapsDone; - const ZProbe& zp = platform.GetCurrentZProbe(); - if (zp.GetProbeType() == ZProbeType::none) + const auto zp = platform.GetCurrentZProbe(); + if (zp->GetProbeType() == ZProbeType::none) { // No Z probe, so we are doing manual mesh levelling. Take the current Z height as the height error. g30zStoppedHeight = g30zHeightError = moveBuffer.coords[Z_AXIS]; } else { - platform.GetCurrentZProbe().SetProbing(false); + zp->SetProbing(false); if (!zProbeTriggered) { platform.Message(ErrorMessage, "Z probe was not triggered during probing move\n"); @@ -901,7 +903,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) float m[MaxAxes]; reprap.GetMove().GetCurrentMachinePosition(m, false); // get height without bed compensation g30zStoppedHeight = m[Z_AXIS] - g30HValue; // save for later - g30zHeightError = g30zStoppedHeight - zp.GetActualTriggerHeight(); + g30zHeightError = g30zStoppedHeight - zp->GetActualTriggerHeight(); g30zHeightErrorSum += g30zHeightError; } } @@ -913,7 +915,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) { // G30 S-1 command taps once and reports the height, S-2 sets the tool offset to the negative of the current height, S-3 sets the Z probe trigger height gb.SetState(GCodeState::probingAtPoint7); // special state for reporting the stopped height at the end - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 30); // retract the probe before moving to the new state } @@ -923,14 +925,14 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (tapsDone == 1 && !hadProbingError) { // Reset the Z axis origin according to the height error so that we can move back up to the dive height - moveBuffer.coords[Z_AXIS] = zp.GetActualTriggerHeight(); + moveBuffer.coords[Z_AXIS] = zp->GetActualTriggerHeight(); reprap.GetMove().SetNewPosition(moveBuffer.coords, false); // Find the coordinates of the Z probe to pass to SetZeroHeightError float tempCoords[MaxAxes]; memcpy(tempCoords, moveBuffer.coords, sizeof(tempCoords)); - tempCoords[X_AXIS] += zp.GetXOffset(); - tempCoords[Y_AXIS] += zp.GetYOffset(); + tempCoords[X_AXIS] += zp->GetXOffset(); + tempCoords[Y_AXIS] += zp->GetYOffset(); reprap.GetMove().SetZeroHeightError(tempCoords); ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); @@ -941,7 +943,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) } gb.AdvanceState(); - if (zp.GetProbeType() == ZProbeType::blTouch) + if (zp->GetProbeType() == ZProbeType::blTouch) { DoFileMacro(gb, RETRACTPROBE_G, false, 30); // bltouch needs to be retracted when it triggers } @@ -952,9 +954,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Move back up to the dive height before we change anything, in particular before we adjust leadscrews SetMoveBufferDefaults(); { - const ZProbe& zp = platform.GetCurrentZProbe(); - moveBuffer.coords[Z_AXIS] = zp.GetStartingHeight(); - moveBuffer.feedRate = zp.GetTravelSpeed(); + const auto zp = platform.GetCurrentZProbe(); + moveBuffer.coords[Z_AXIS] = zp->GetStartingHeight(); + moveBuffer.feedRate = zp->GetTravelSpeed(); } NewMoveAvailable(1); gb.AdvanceState(); @@ -965,16 +967,16 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(gb)) { // See whether we need to do any more taps - const ZProbe& params = platform.GetCurrentZProbe(); + const auto zp = platform.GetCurrentZProbe(); bool acceptReading = false; - if (params.GetMaxTaps() < 2) + if (zp->GetMaxTaps() < 2) { acceptReading = true; } else if (tapsDone >= 2) { g30zHeightErrorLowestDiff = min<float>(g30zHeightErrorLowestDiff, fabsf(g30zHeightError - g30PrevHeightError)); - if (params.GetTolerance() > 0.0 && g30zHeightErrorLowestDiff <= params.GetTolerance()) + if (zp->GetTolerance() > 0.0 && g30zHeightErrorLowestDiff <= zp->GetTolerance()) { g30zHeightError = (g30zHeightError + g30PrevHeightError)/2; acceptReading = true; @@ -983,7 +985,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (!acceptReading) { - if (tapsDone < params.GetMaxTaps()) + if (tapsDone < zp->GetMaxTaps()) { // Tap again g30PrevHeightError = g30zHeightError; @@ -994,7 +996,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // We no longer flag this as a probing error, instead we take the average and issue a warning g30zHeightError = g30zHeightErrorSum/tapsDone; - if (params.GetTolerance() > 0.0) // zero or negative tolerance means always average all readings, so no warning message + if (zp->GetTolerance() > 0.0) // zero or negative tolerance means always average all readings, so no warning message { platform.Message(WarningMessage, "Z probe readings not consistent\n"); } @@ -1013,13 +1015,13 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Find the coordinates of the Z probe to pass to SetZeroHeightError float tempCoords[MaxAxes]; memcpy(tempCoords, moveBuffer.coords, sizeof(tempCoords)); - tempCoords[X_AXIS] += params.GetXOffset(); - tempCoords[Y_AXIS] += params.GetYOffset(); + tempCoords[X_AXIS] += zp->GetXOffset(); + tempCoords[Y_AXIS] += zp->GetYOffset(); reprap.GetMove().SetZeroHeightError(tempCoords); ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); } gb.AdvanceState(); - if (platform.GetCurrentZProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 30); } @@ -1055,8 +1057,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (g30SValue == -3) { // Adjust the Z probe trigger height to the stop height - ZProbe& zp = platform.GetCurrentZProbe(); - zp.SetTriggerHeight(g30zStoppedHeight); + platform.GetCurrentZProbe()->SetTriggerHeight(g30zStoppedHeight); reply.printf("Z probe trigger height set to %.3f mm", (double)g30zStoppedHeight); } else if (g30SValue == -2) @@ -1087,9 +1088,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(gb)) { const StraightProbeSettings& sps = reprap.GetMove().GetStraightProbeSettings(); - const ZProbe& zp = *(platform.GetEndstops().GetZProbe(sps.GetZProbeToUse())); + const auto zp = platform.GetEndstops().GetZProbe(sps.GetZProbeToUse()); gb.AdvanceState(); - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp.IsNotNull() && zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, DEPLOYPROBE_G, false, 38); } @@ -1100,9 +1101,9 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(gb)) { const StraightProbeSettings& sps = reprap.GetMove().GetStraightProbeSettings(); - const ZProbe& zp = *(platform.GetEndstops().GetZProbe(sps.GetZProbeToUse())); + const auto zp = platform.GetEndstops().GetZProbe(sps.GetZProbeToUse()); lastProbedTime = millis(); // start the probe recovery timer - if (zp.GetTurnHeatersOff()) + if (zp.IsNotNull() && zp->GetTurnHeatersOff()) { reprap.GetHeat().SuspendHeaters(true); } @@ -1112,12 +1113,12 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) case GCodeState::straightProbe2: // Executing G38. The probe has been deployed and the recovery timer has been started. - if (millis() - lastProbedTime >= (uint32_t)(platform.GetCurrentZProbe().GetRecoveryTime() * SecondsToMillis)) + if (millis() - lastProbedTime >= (uint32_t)(platform.GetCurrentZProbe()->GetRecoveryTime() * SecondsToMillis)) { // The probe recovery time has elapsed, so we can start the probing move const StraightProbeSettings& sps = reprap.GetMove().GetStraightProbeSettings(); - const ZProbe& zp = *(platform.GetEndstops().GetZProbe(sps.GetZProbeToUse())); - if (zp.GetProbeType() == ZProbeType::none) + const auto zp = platform.GetEndstops().GetZProbe(sps.GetZProbeToUse()); + if (zp.IsNull() || zp->GetProbeType() == ZProbeType::none) { // No Z probe, so we are doing manual 'probing' UnlockAll(gb); // release the movement lock to allow manual Z moves @@ -1127,7 +1128,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) else { const bool probingAway = sps.ProbingAway(); - const bool atStop = (zp.Stopped() == EndStopHit::atStop); + const bool atStop = (zp->Stopped() == EndStopHit::atStop); if (probingAway != atStop) { // Z probe is already in target state at the start of the move, so abandon the probe and signal an error if the type demands so @@ -1138,7 +1139,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) error = true; } gb.SetState(GCodeState::normal); // no point in doing anything else - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 38); } @@ -1155,11 +1156,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) break; } - zp.SetProbing(true); + zp->SetProbing(true); moveBuffer.checkEndstops = true; moveBuffer.reduceAcceleration = true; sps.SetCoordsToTarget(moveBuffer.coords); - moveBuffer.feedRate = zp.GetProbingSpeed(); + moveBuffer.feedRate = zp->GetProbingSpeed(); NewMoveAvailable(1); gb.AdvanceState(); } @@ -1175,10 +1176,10 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) reprap.GetHeat().SuspendHeaters(false); const StraightProbeSettings& sps = reprap.GetMove().GetStraightProbeSettings(); const bool probingAway = sps.ProbingAway(); - const ZProbe& zp = *(platform.GetEndstops().GetZProbe(sps.GetZProbeToUse())); - if (zp.GetProbeType() != ZProbeType::none) + const auto zp = platform.GetEndstops().GetZProbe(sps.GetZProbeToUse()); + if (zp.IsNotNull() && zp->GetProbeType() != ZProbeType::none) { - zp.SetProbing(false); + zp->SetProbing(false); if (!zProbeTriggered && sps.SignalError()) { platform.MessageF(ErrorMessage, "Z probe %s during probing move\n", probingAway ? "did not loose contact" : "was not triggered"); @@ -1187,7 +1188,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) } gb.SetState(GCodeState::normal); - if (zp.GetProbeType() != ZProbeType::none && !probeIsDeployed) + if (zp->GetProbeType() != ZProbeType::none && !probeIsDeployed) { DoFileMacro(gb, RETRACTPROBE_G, false, 38); // retract the probe before moving to the new state } diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index 13060a17..56ccd6aa 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -345,8 +345,13 @@ bool Move::IsRawMotorMove(uint8_t moveType) const noexcept // Return true if the specified point is accessible to the Z probe bool Move::IsAccessibleProbePoint(float x, float y) const noexcept { - const ZProbe& params = reprap.GetPlatform().GetCurrentZProbe(); - return kinematics->IsReachable(x - params.GetXOffset(), y - params.GetYOffset(), false); + const auto zp = reprap.GetPlatform().GetCurrentZProbe(); + if (zp.IsNotNull()) + { + x -= zp->GetXOffset(); + y -= zp->GetYOffset(); + } + return kinematics->IsReachable(x, y, false); } // 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. @@ -865,9 +870,12 @@ float Move::GetProbeCoordinates(int count, float& x, float& y, bool wantNozzlePo y = probePoints.GetYCoord(count); if (wantNozzlePosition) { - const ZProbe& rp = reprap.GetPlatform().GetCurrentZProbe(); - x -= rp.GetXOffset(); - y -= rp.GetYOffset(); + const auto zp = reprap.GetPlatform().GetCurrentZProbe(); + if (zp.IsNotNull()) + { + x -= zp->GetXOffset(); + y -= zp->GetYOffset(); + } } return probePoints.GetZHeight(count); } diff --git a/src/Platform.cpp b/src/Platform.cpp index c22bdb41..bf71ce3b 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -3812,7 +3812,7 @@ void Platform::SetAxisMinimum(size_t axis, float value, bool byProbing) noexcept ZProbeType Platform::GetCurrentZProbeType() const noexcept { - return endstops.GetCurrentZProbe().GetProbeType(); + return endstops.GetCurrentOrDefaultZProbe()->GetProbeType(); } void Platform::InitZProbeFilters() noexcept @@ -4405,7 +4405,7 @@ void Platform::Tick() noexcept } #endif - const ZProbe& currentZProbe = GetCurrentZProbe(); + const ZProbe& currentZProbe = endstops.GetCurrentOrDefaultZProbeFromISR(); switch (tickState) { case 1: diff --git a/src/Platform.h b/src/Platform.h index 59d2f37f..001758db 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -451,7 +451,7 @@ public: // Endstops and Z probe EndstopsManager& GetEndstops() noexcept { return endstops; } - ZProbe& GetCurrentZProbe() noexcept { return endstops.GetCurrentZProbe(); } + ReadLockedPointer<ZProbe> GetCurrentZProbe() noexcept { return endstops.GetCurrentOrDefaultZProbe(); } ZProbeType GetCurrentZProbeType() const noexcept; void InitZProbeFilters() noexcept; const volatile ZProbeAveragingFilter& GetZProbeOnFilter() const noexcept { return zProbeOnFilter; } diff --git a/src/RepRap.cpp b/src/RepRap.cpp index b57d291b..8b78e4bf 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -156,6 +156,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = { "job", OBJECT_MODEL_FUNC(self->printMonitor), ObjectModelEntryFlags::live }, { "move", OBJECT_MODEL_FUNC(self->move), ObjectModelEntryFlags::live }, { "network", OBJECT_MODEL_FUNC(self->network), ObjectModelEntryFlags::none }, + { "sensors", OBJECT_MODEL_FUNC(&self->platform->GetEndstops()), ObjectModelEntryFlags::none }, { "state", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::live }, { "tools", OBJECT_MODEL_FUNC_NOSELF(&toolsArrayDescriptor), ObjectModelEntryFlags::live }, @@ -166,7 +167,7 @@ constexpr ObjectModelTableEntry RepRap::objectModelTable[] = { "upTime", OBJECT_MODEL_FUNC_NOSELF((int32_t)((millis64()/1000u) & 0x7FFFFFFF)), ObjectModelEntryFlags::live }, }; -constexpr uint8_t RepRap::objectModelTableDescriptor[] = { 2, 8, 4 }; +constexpr uint8_t RepRap::objectModelTableDescriptor[] = { 2, 9, 4 }; DEFINE_GET_OBJECT_MODEL_TABLE(RepRap) @@ -1188,16 +1189,14 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) noe response->cat(",\"sensors\":{"); // Probe - const int v0 = platform->GetCurrentZProbe().GetReading(); - int v1, v2; - switch (platform->GetCurrentZProbe().GetSecondaryValues(v1, v2)) + const auto zp = platform->GetCurrentZProbe(); + const int v0 = zp->GetReading(); + int v1; + switch (zp->GetSecondaryValues(v1)) { case 1: response->catf("\"probeValue\":%d,\"probeSecondary\":[%d]", v0, v1); break; - case 2: - response->catf("\"probeValue\":%d,\"probeSecondary\":[%d,%d]", v0, v1, v2); - break; default: response->catf("\"probeValue\":%d", v0); break; @@ -1484,11 +1483,11 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) noe /* Probe */ { - const ZProbe& zp = platform->GetCurrentZProbe(); + const auto zp = platform->GetCurrentZProbe(); // Trigger threshold, trigger height, type response->catf(",\"probe\":{\"threshold\":%d,\"height\":%.2f,\"type\":%u}", - zp.GetAdcValue(), (double)zp.GetConfiguredTriggerHeight(), (unsigned int)zp.GetProbeType()); + zp->GetAdcValue(), (double)zp->GetConfiguredTriggerHeight(), (unsigned int)zp->GetProbeType()); } /* Tool Mapping */ @@ -1916,16 +1915,14 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq) noexcept response->catf(",\"tool\":%d", GetCurrentToolNumber()); // Send the Z probe value - const int v0 = platform->GetCurrentZProbe().GetReading(); - int v1, v2; - switch (platform->GetCurrentZProbe().GetSecondaryValues(v1, v2)) + const auto zp = platform->GetCurrentZProbe(); + const int v0 = zp->GetReading(); + int v1; + switch (zp->GetSecondaryValues(v1)) { case 1: response->catf(",\"probe\":\"%d (%d)\"", v0, v1); break; - case 2: - response->catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2); - break; default: response->catf(",\"probe\":\"%d\"", v0); break; diff --git a/src/Version.h b/src/Version.h index 2b0fcf5f..988ea29f 100644 --- a/src/Version.h +++ b/src/Version.h @@ -20,7 +20,7 @@ #endif #ifndef DATE -# define DATE "2020-01-17b3" +# define DATE "2020-01-18b1" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d" |