From c812ce5e14cf476526d955edbce2effa9d922902 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Sat, 18 Jan 2020 23:03:39 +0000 Subject: Major refactoring, bug fixes in function evaluation Changed all bitmaps to use the bitmap class from RRFLibraries Fixed bugs in functoin evaluation --- src/CAN/CanInterface.cpp | 24 +- src/CAN/CanInterface.h | 6 +- src/CAN/CanMotion.cpp | 4 +- src/Display/Menu.cpp | 6 +- src/Endstops/Endstop.cpp | 2 +- src/Endstops/Endstop.h | 8 +- src/Endstops/EndstopsManager.cpp | 22 +- src/Endstops/StallDetectionEndstop.cpp | 14 +- src/Endstops/SwitchEndstop.cpp | 10 +- src/Endstops/SwitchEndstop.h | 2 +- src/Endstops/ZProbe.cpp | 20 +- src/Endstops/ZProbeEndstop.cpp | 2 +- src/Fans/Fan.cpp | 73 ++---- src/Fans/Fan.h | 5 +- src/Fans/FansManager.cpp | 2 +- src/Fans/LocalFan.cpp | 73 +++--- src/Fans/RemoteFan.cpp | 2 +- src/GCodes/GCodeBuffer/StringParser.cpp | 22 +- src/GCodes/GCodeMachineState.cpp | 2 +- src/GCodes/GCodeMachineState.h | 2 +- src/GCodes/GCodes.cpp | 145 +++++------ src/GCodes/GCodes.h | 4 +- src/GCodes/GCodes2.cpp | 6 +- src/GCodes/GCodes3.cpp | 26 +- src/GCodes/GCodes4.cpp | 12 +- src/GCodes/Trigger.cpp | 6 +- src/GCodes/Trigger.h | 8 +- src/Heating/Heat.cpp | 8 +- src/Heating/Heater.cpp | 6 +- src/Heating/Sensors/TemperatureSensor.cpp | 2 +- src/Movement/DDA.cpp | 54 ++-- src/Movement/DDA.h | 2 +- src/Movement/Kinematics/CoreKinematics.cpp | 10 +- src/Movement/Kinematics/FiveBarScaraKinematics.cpp | 16 +- src/Movement/Kinematics/HangprinterKinematics.cpp | 19 +- src/Movement/Kinematics/Kinematics.cpp | 14 +- src/Movement/Kinematics/Kinematics.h | 4 +- src/Movement/Kinematics/LinearDeltaKinematics.cpp | 19 +- src/Movement/Kinematics/LinearDeltaKinematics.h | 2 +- src/Movement/Kinematics/PolarKinematics.cpp | 16 +- src/Movement/Kinematics/RotaryDeltaKinematics.cpp | 19 +- src/Movement/Kinematics/RotaryDeltaKinematics.h | 2 +- src/Movement/Kinematics/ScaraKinematics.cpp | 16 +- src/Movement/Move.cpp | 42 +-- src/Movement/StepperDrivers/TMC2660.cpp | 12 +- src/Movement/StepperDrivers/TMC51xx.cpp | 4 +- src/Movement/StraightProbeSettings.cpp | 2 +- src/Movement/StraightProbeSettings.h | 2 +- src/ObjectModel/ObjectModel.cpp | 94 ++++++- src/ObjectModel/ObjectModel.h | 50 ++-- src/OutputMemory.cpp | 26 ++ src/OutputMemory.h | 3 + src/Platform.cpp | 281 ++++++++++----------- src/Platform.h | 17 +- src/PrintMonitor.cpp | 10 +- src/RepRap.cpp | 67 +++-- src/RepRapFirmware.cpp | 9 +- src/RepRapFirmware.h | 43 ++-- src/Tools/Tool.cpp | 77 ++++-- src/Tools/Tool.h | 22 +- src/Version.h | 2 +- 61 files changed, 781 insertions(+), 699 deletions(-) (limited to 'src') diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index c05feee5..db737693 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -431,9 +431,9 @@ void CanDriversData::AddEntry(DriverId driver, uint16_t val) noexcept } // Get the details of the drivers on the next board and advance startFrom beyond the entries for this board -CanAddress CanDriversData::GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& driversBitmap) const noexcept +CanAddress CanDriversData::GetNextBoardDriverBitmap(size_t& startFrom, CanDriversBitmap& driversBitmap) const noexcept { - driversBitmap = 0; + driversBitmap.Clear(); if (startFrom >= numEntries) { return CanId::NoAddress; @@ -441,7 +441,7 @@ CanAddress CanDriversData::GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& const CanAddress boardAddress = data[startFrom].driver.boardAddress; do { - SetBit(driversBitmap, data[startFrom].driver.localDriver); + driversBitmap.SetBit(data[startFrom].driver.localDriver); ++startFrom; } while (startFrom < numEntries && data[startFrom].driver.boardAddress == boardAddress); return boardAddress; @@ -474,9 +474,9 @@ void CanDriversList::AddEntry(DriverId driver) noexcept } // Get the details of the drivers on the next board and advance startFrom beyond the entries for this board -CanAddress CanDriversList::GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& driversBitmap) const noexcept +CanAddress CanDriversList::GetNextBoardDriverBitmap(size_t& startFrom, CanDriversBitmap& driversBitmap) const noexcept { - driversBitmap = 0; + driversBitmap.Clear(); if (startFrom >= numEntries) { return CanId::NoAddress; @@ -484,7 +484,7 @@ CanAddress CanDriversList::GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& const CanAddress boardAddress = drivers[startFrom].boardAddress; do { - SetBit(driversBitmap, drivers[startFrom].localDriver); + driversBitmap.SetBit(drivers[startFrom].localDriver); ++startFrom; } while (startFrom < numEntries && drivers[startFrom].boardAddress == boardAddress); return boardAddress; @@ -498,7 +498,7 @@ static bool SetRemoteDriverValues(const CanDriversData& data, const StringRef& r size_t start = 0; for (;;) { - uint16_t driverBits; + CanDriversBitmap driverBits; size_t savedStart = start; const CanAddress boardAddress = data.GetNextBoardDriverBitmap(start, driverBits); if (boardAddress == CanId::NoAddress) @@ -513,7 +513,7 @@ static bool SetRemoteDriverValues(const CanDriversData& data, const StringRef& r } const CanRequestId rid = CanInterface::AllocateRequestId(boardAddress); CanMessageMultipleDrivesRequest * const msg = buf->SetupRequestMessage(rid, CanId::MasterAddress, boardAddress, mt); - msg->driversToUpdate = driverBits; + msg->driversToUpdate = driverBits.GetRaw(); size_t numDrivers = 0; while (savedStart < start && numDrivers < ARRAY_SIZE(msg->values)) { @@ -536,7 +536,7 @@ static bool SetRemoteDriverStates(const CanDriversList& drivers, const StringRef size_t start = 0; for (;;) { - uint16_t driverBits; + CanDriversBitmap driverBits; size_t savedStart = start; const CanAddress boardAddress = drivers.GetNextBoardDriverBitmap(start, driverBits); if (boardAddress == CanId::NoAddress) @@ -551,7 +551,7 @@ static bool SetRemoteDriverStates(const CanDriversList& drivers, const StringRef } const CanRequestId rid = CanInterface::AllocateRequestId(boardAddress); CanMessageMultipleDrivesRequest * const msg = buf->SetupRequestMessage(rid, CanId::MasterAddress, boardAddress, CanMessageType::setDriverStates); - msg->driversToUpdate = driverBits; + msg->driversToUpdate = driverBits.GetRaw(); size_t numDrivers = 0; while (savedStart < start && numDrivers < ARRAY_SIZE(msg->values)) { @@ -776,7 +776,7 @@ GCodeResult CanInterface::SetRemoteDriverStallParameters(const CanDriversList& d size_t start = 0; for (;;) { - uint16_t driverBits; + CanDriversBitmap driverBits; const CanAddress boardAddress = drivers.GetNextBoardDriverBitmap(start, driverBits); if (boardAddress == CanId::NoAddress) { @@ -784,7 +784,7 @@ GCodeResult CanInterface::SetRemoteDriverStallParameters(const CanDriversList& d } CanMessageGenericConstructor cons(M915Params); - cons.AddUParam('d', driverBits); + cons.AddUParam('d', driverBits.GetRaw()); cons.PopulateFromCommand(gb); const GCodeResult rslt = cons.SendAndGetResponse(CanMessageType::m915, boardAddress, reply); if (rslt != GCodeResult::ok) diff --git a/src/CAN/CanInterface.h b/src/CAN/CanInterface.h index 1230993f..7eade76d 100644 --- a/src/CAN/CanInterface.h +++ b/src/CAN/CanInterface.h @@ -22,6 +22,8 @@ class DDA; class DriveMovement; struct PrepParams; +typedef Bitmap CanDriversBitmap; + // Class to accumulate a set of values relating to CAN-connected drivers class CanDriversData { @@ -29,7 +31,7 @@ public: CanDriversData() noexcept; void AddEntry(DriverId id, uint16_t val) noexcept; size_t GetNumEntries() const noexcept { return numEntries; } - CanAddress GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& driversBitmap) const noexcept; + CanAddress GetNextBoardDriverBitmap(size_t& startFrom, CanDriversBitmap& driversBitmap) const noexcept; uint16_t GetElement(size_t n) const pre(n < GetnumEntries()) noexcept { return data[n].val; } private: @@ -50,7 +52,7 @@ public: void Clear() noexcept { numEntries = 0; } void AddEntry(DriverId id) noexcept; size_t GetNumEntries() const noexcept { return numEntries; } - CanAddress GetNextBoardDriverBitmap(size_t& startFrom, uint16_t& driversBitmap) const noexcept; + CanAddress GetNextBoardDriverBitmap(size_t& startFrom, CanDriversBitmap& driversBitmap) const noexcept; private: size_t numEntries; diff --git a/src/CAN/CanMotion.cpp b/src/CAN/CanMotion.cpp index e4d66cf5..521eb8eb 100644 --- a/src/CAN/CanMotion.cpp +++ b/src/CAN/CanMotion.cpp @@ -160,12 +160,12 @@ CanMessageBuffer *CanMotion::GetUrgentMessage() noexcept if (driversToStop[driversToStopIndexBeingFilled ^ 1].GetNumEntries() != 0) { - uint16_t drivers; + CanDriversBitmap drivers; const CanAddress board = driversToStop[driversToStopIndexBeingFilled ^ 1].GetNextBoardDriverBitmap(indexOfNextDriverToStop, drivers); if (board != CanId::NoAddress) { auto msg = urgentMessageBuffer->SetupRequestMessage(0, CanInterface::GetCanAddress(), board); - msg->whichDrives = drivers; + msg->whichDrives = drivers.GetRaw(); return urgentMessageBuffer; } driversToStop[driversToStopIndexBeingFilled ^ 1].Clear(); diff --git a/src/Display/Menu.cpp b/src/Display/Menu.cpp index 5c890e80..07870011 100644 --- a/src/Display/Menu.cpp +++ b/src/Display/Menu.cpp @@ -170,15 +170,15 @@ void Menu::DisplayMessageBox(const MessageBox& mbox) noexcept // Add whichever XYZ jog buttons we have been asked to display - assume only XYZ for now const PixelNumber axisButtonWidth = availableWidth/4; const PixelNumber axisButtonStep = (availableWidth - 3 *axisButtonWidth)/2 + axisButtonWidth; - if (IsBitSet(mbox.controls, X_AXIS)) + if (mbox.controls.IsBitSet(X_AXIS)) { AddItem(new ValueMenuItem(top + 2 * rowHeight, left, axisButtonWidth, MenuItem::CentreAlign, fontToUse, MenuItem::AlwaysVisible, true, 510, 1), true); } - if (IsBitSet(mbox.controls, Y_AXIS)) + if (mbox.controls.IsBitSet(Y_AXIS)) { AddItem(new ValueMenuItem(top + 2 * rowHeight, left + axisButtonStep, axisButtonWidth, MenuItem::CentreAlign, fontToUse, MenuItem::AlwaysVisible, true, 511, 1), true); } - if (IsBitSet(mbox.controls, Z_AXIS)) + if (mbox.controls.IsBitSet(Z_AXIS)) { AddItem(new ValueMenuItem(top + 2 * rowHeight, left + 2 * axisButtonStep, axisButtonWidth, MenuItem::CentreAlign, fontToUse, MenuItem::AlwaysVisible, true, 512, 2), true); } diff --git a/src/Endstops/Endstop.cpp b/src/Endstops/Endstop.cpp index f80cdca9..98119c7d 100644 --- a/src/Endstops/Endstop.cpp +++ b/src/Endstops/Endstop.cpp @@ -8,7 +8,7 @@ #include "Endstop.h" // 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 +DriversBitmap EndstopOrZProbe::stalledDrivers; // used to track which drivers are reported as stalled, for stall detect endstops and stall detect Z probes #if SUPPORT_OBJECT_MODEL diff --git a/src/Endstops/Endstop.h b/src/Endstops/Endstop.h index d4c8ee17..e0eb3a9e 100644 --- a/src/Endstops/Endstop.h +++ b/src/Endstops/Endstop.h @@ -31,7 +31,7 @@ public: EndstopOrZProbe *GetNext() const noexcept { return next; } void SetNext(EndstopOrZProbe *e) noexcept { next = e; } - static void UpdateStalledDrivers(uint32_t driverMask, bool isStalled) noexcept; + static void UpdateStalledDrivers(DriversBitmap drivers, bool isStalled) noexcept; protected: static DriversBitmap GetStalledDrivers() noexcept { return stalledDrivers; } @@ -42,15 +42,15 @@ private: static DriversBitmap stalledDrivers; // used to track which drivers are reported as stalled, for stall detect endstops and stall detect Z probes }; -inline void EndstopOrZProbe::UpdateStalledDrivers(uint32_t driverMask, bool isStalled) noexcept +inline void EndstopOrZProbe::UpdateStalledDrivers(DriversBitmap drivers, bool isStalled) noexcept { if (isStalled) { - stalledDrivers |= driverMask; + stalledDrivers |= drivers; } else { - stalledDrivers &= ~driverMask; + stalledDrivers &= ~drivers; } } diff --git a/src/Endstops/EndstopsManager.cpp b/src/Endstops/EndstopsManager.cpp index a890012e..e1224bc9 100644 --- a/src/Endstops/EndstopsManager.cpp +++ b/src/Endstops/EndstopsManager.cpp @@ -148,12 +148,12 @@ void EndstopsManager::AddToActive(EndstopOrZProbe& e) noexcept bool EndstopsManager::EnableAxisEndstops(AxesBitmap axes, bool forHoming) noexcept { activeEndstops = nullptr; - isHomingMove = forHoming && axes != 0; + isHomingMove = forHoming && axes.IsNonEmpty(); const Kinematics& kin = reprap.GetMove().GetKinematics(); - while (axes != 0) + while (axes.IsNonEmpty()) { - const unsigned int axis = LowestSetBit(axes); - ClearBit(axes, axis); + const unsigned int axis = axes.LowestSetBit(); + axes.ClearBit(axis); if (axisEndstops[axis] != nullptr && axisEndstops[axis]->Prime(kin, reprap.GetPlatform().GetAxisDriversConfig(axis))) { AddToActive(*axisEndstops[axis]); @@ -183,22 +183,22 @@ bool EndstopsManager::EnableZProbe(size_t probeNumber, bool probingAway) noexcep // Enable extruder endstops. This adds to any existing axis endstops, so you must call EnableAxisEndstops before calling this. bool EndstopsManager::EnableExtruderEndstops(ExtrudersBitmap extruders) noexcept { - if (extruders != 0) + if (extruders.IsNonEmpty()) { if (extrudersEndstop == nullptr) { extrudersEndstop = new StallDetectionEndstop; } - DriversBitmap drivers = 0; - while (extruders != 0) + DriversBitmap drivers; + while (extruders.IsNonEmpty()) { - const unsigned int extruder = LowestSetBit(extruders); - ClearBit(extruders, extruder); + const unsigned int extruder = extruders.LowestSetBit(); + extruders.ClearBit(extruder); const DriverId driver = reprap.GetPlatform().GetExtruderDriver(extruder); #if SUPPORT_CAN_EXPANSION if (driver.IsLocal()) { - SetBit(drivers, driver.localDriver); + drivers.SetBit(driver.localDriver); } else { @@ -206,7 +206,7 @@ bool EndstopsManager::EnableExtruderEndstops(ExtrudersBitmap extruders) noexcept return false; } #else - SetBit(drivers, driver.localDriver); + drivers.SetBit(driver.localDriver); #endif } diff --git a/src/Endstops/StallDetectionEndstop.cpp b/src/Endstops/StallDetectionEndstop.cpp index 47a065ce..bc127a5c 100644 --- a/src/Endstops/StallDetectionEndstop.cpp +++ b/src/Endstops/StallDetectionEndstop.cpp @@ -12,26 +12,26 @@ // Stall detection endstop StallDetectionEndstop::StallDetectionEndstop(uint8_t axis, EndStopPosition pos, bool p_individualMotors) noexcept - : Endstop(axis, pos), driversMonitored(0), individualMotors(p_individualMotors) + : Endstop(axis, pos), individualMotors(p_individualMotors) { } StallDetectionEndstop::StallDetectionEndstop() noexcept - : Endstop(NO_AXIS, EndStopPosition::noEndStop), driversMonitored(0), individualMotors(false), stopAll(true) + : Endstop(NO_AXIS, EndStopPosition::noEndStop), individualMotors(false), stopAll(true) { } // Test whether we are at or near the stop EndStopHit StallDetectionEndstop::Stopped() const noexcept { - return ((GetStalledDrivers() & driversMonitored) != 0) ? EndStopHit::atStop : EndStopHit::noStop; + return (GetStalledDrivers().Intersects(driversMonitored)) ? EndStopHit::atStop : EndStopHit::noStop; } // This is called to prime axis endstops bool StallDetectionEndstop::Prime(const Kinematics& kin, const AxisDriversConfig& axisDrivers) noexcept { // Find which drivers are relevant, and decide whether we stop just the driver, just the axis, or everything - stopAll = (kin.GetConnectedAxes(GetAxis()) & ~MakeBitmap(GetAxis())) != 0; + stopAll = kin.GetConnectedAxes(GetAxis()).Intersects(~AxesBitmap::MakeFromBits(GetAxis())); numDriversLeft = axisDrivers.numDrivers; driversMonitored = axisDrivers.GetDriversBitmap(); @@ -48,7 +48,7 @@ EndstopHitDetails StallDetectionEndstop::CheckTriggered(bool goingSlow) noexcept { EndstopHitDetails rslt; // initialised by default constructor const DriversBitmap relevantStalledDrivers = driversMonitored & GetStalledDrivers(); - if (relevantStalledDrivers != 0) + if (relevantStalledDrivers.IsNonEmpty()) { rslt.axis = GetAxis(); if (rslt.axis == NO_AXIS) @@ -73,7 +73,7 @@ EndstopHitDetails StallDetectionEndstop::CheckTriggered(bool goingSlow) noexcept #if SUPPORT_CAN_EXPANSION rslt.driver.boardAddress = 0; #else - rslt.driver.localDriver = LowestSetBitNumber(relevantStalledDrivers); + rslt.driver.localDriver = relevantStalledDrivers.LowestSetBit(); #endif } else @@ -104,7 +104,7 @@ bool StallDetectionEndstop::Acknowledge(EndstopHitDetails what) noexcept return true; case EndstopHitAction::stopDriver: - ClearBit(driversMonitored, what.driver.localDriver); + driversMonitored.ClearBit(what.driver.localDriver); --numDriversLeft; return false; diff --git a/src/Endstops/SwitchEndstop.cpp b/src/Endstops/SwitchEndstop.cpp index d8c5eca9..fa4a903a 100644 --- a/src/Endstops/SwitchEndstop.cpp +++ b/src/Endstops/SwitchEndstop.cpp @@ -133,9 +133,9 @@ EndStopHit SwitchEndstop::Stopped() const noexcept bool SwitchEndstop::Prime(const Kinematics& kin, const AxisDriversConfig& axisDrivers) noexcept { // Decide whether we stop just the driver, just the axis, or everything - stopAll = ((kin.GetConnectedAxes(GetAxis()) & ~MakeBitmap(GetAxis())) != 0); + stopAll = kin.GetConnectedAxes(GetAxis()).Intersects(~AxesBitmap::MakeFromBits(GetAxis())); numPortsLeftToTrigger = (numPortsUsed != axisDrivers.numDrivers) ? 1 : numPortsUsed; - portsLeftToTrigger = LowestNBits(numPortsUsed); + portsLeftToTrigger = PortsBitmap::MakeLowestNBits(numPortsUsed); #if SUPPORT_CAN_EXPANSION // For each remote switch, check that the expansion board knows about it, and make sure we have an up-to-date state @@ -163,11 +163,11 @@ bool SwitchEndstop::Prime(const Kinematics& kin, const AxisDriversConfig& axisDr EndstopHitDetails SwitchEndstop::CheckTriggered(bool goingSlow) noexcept { EndstopHitDetails rslt; // initialised by default constructor - if (portsLeftToTrigger != 0) + if (portsLeftToTrigger.IsNonEmpty()) { for (size_t i = 0; i < numPortsUsed; ++i) { - if (IsBitSet(portsLeftToTrigger, i) && IsTriggered(i)) + if (portsLeftToTrigger.IsBitSet(i) && IsTriggered(i)) { rslt.axis = GetAxis(); if (stopAll) @@ -219,7 +219,7 @@ bool SwitchEndstop::Acknowledge(EndstopHitDetails what) noexcept return true; case EndstopHitAction::stopDriver: - ClearBit(portsLeftToTrigger, what.internalUse); + portsLeftToTrigger.ClearBit(what.internalUse); --numPortsLeftToTrigger; return false; diff --git a/src/Endstops/SwitchEndstop.h b/src/Endstops/SwitchEndstop.h index bbfb7874..ea4be47d 100644 --- a/src/Endstops/SwitchEndstop.h +++ b/src/Endstops/SwitchEndstop.h @@ -38,7 +38,7 @@ public: GCodeResult Configure(const char *pinNames, const StringRef& reply) noexcept; private: - typedef uint16_t PortsBitmap; + typedef Bitmap PortsBitmap; void ReleasePorts() noexcept; diff --git a/src/Endstops/ZProbe.cpp b/src/Endstops/ZProbe.cpp index d148cc5b..055e076f 100644 --- a/src/Endstops/ZProbe.cpp +++ b/src/Endstops/ZProbe.cpp @@ -27,7 +27,7 @@ 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); } + { return ExpressionValue((context.GetLastIndex() == 0) ? ((const ZProbe*)self)->xOffset : ((const ZProbe*)self)->yOffset, 1); } }; constexpr ObjectModelArrayDescriptor ZProbe::valueArrayDescriptor = @@ -48,18 +48,18 @@ 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 }, + { "calibrationTemperature", OBJECT_MODEL_FUNC(self->calibTemperature, 1), ObjectModelEntryFlags::none }, { "disablesHeaters", OBJECT_MODEL_FUNC((bool)self->misc.parts.turnHeatersOff), ObjectModelEntryFlags::none }, - { "diveHeight", OBJECT_MODEL_FUNC(self->diveHeight), ObjectModelEntryFlags::none }, + { "diveHeight", OBJECT_MODEL_FUNC(self->diveHeight, 1), 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 }, + { "recoveryTime", OBJECT_MODEL_FUNC(self->recoveryTime, 1), ObjectModelEntryFlags::none }, + { "speed", OBJECT_MODEL_FUNC(self->probeSpeed, 1), ObjectModelEntryFlags::none }, + { "temperatureCoefficient", OBJECT_MODEL_FUNC(self->temperatureCoefficient, 3), 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 }, + { "tolerance", OBJECT_MODEL_FUNC(self->tolerance, 3), ObjectModelEntryFlags::none }, + { "travelSpeed", OBJECT_MODEL_FUNC(self->travelSpeed, 1), ObjectModelEntryFlags::none }, + { "triggerHeight", OBJECT_MODEL_FUNC(self->triggerHeight, 3), ObjectModelEntryFlags::none }, { "type", OBJECT_MODEL_FUNC((int32_t)self->type), ObjectModelEntryFlags::none }, { "value", OBJECT_MODEL_FUNC_NOSELF(&valueArrayDescriptor), ObjectModelEntryFlags::live }, }; @@ -148,7 +148,7 @@ int ZProbe::GetReading() const noexcept #if HAS_STALL_DETECT { const DriversBitmap zDrivers = reprap.GetPlatform().GetAxisDriversConfig(Z_AXIS).GetDriversBitmap(); - zProbeVal = ((zDrivers & GetStalledDrivers()) != 0) ? 1000 : 0; + zProbeVal = (zDrivers.Intersects(GetStalledDrivers())) ? 1000 : 0; } #else return 1000; diff --git a/src/Endstops/ZProbeEndstop.cpp b/src/Endstops/ZProbeEndstop.cpp index c4c919a0..3ded0c6a 100644 --- a/src/Endstops/ZProbeEndstop.cpp +++ b/src/Endstops/ZProbeEndstop.cpp @@ -28,7 +28,7 @@ EndStopHit ZProbeEndstop::Stopped() const noexcept bool ZProbeEndstop::Prime(const Kinematics& kin, const AxisDriversConfig& axisDrivers) noexcept { // Decide whether we stop just the driver, just the axis, or everything - stopAll = (kin.GetConnectedAxes(GetAxis()) & ~MakeBitmap(GetAxis())) != 0; + stopAll = kin.GetConnectedAxes(GetAxis()).Intersects(~AxesBitmap::MakeFromBits(GetAxis())); #if SUPPORT_CAN_EXPANSION //TODO if the Z probe is remote, check that the expansion board knows about it diff --git a/src/Fans/Fan.cpp b/src/Fans/Fan.cpp index 01ad62a6..98b5c1f5 100644 --- a/src/Fans/Fan.cpp +++ b/src/Fans/Fan.cpp @@ -21,28 +21,30 @@ constexpr ObjectModelArrayDescriptor Fan::monitoredSensorsArrayDescriptor = { nullptr, - [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const Fan*)self)->GetNumMonitoredSensors(); }, - [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue((int32_t)((const Fan*)self)->GetMonitoredSensorNumber(context.GetLastIndex())); } + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t + { return ((const Fan*)self)->sensorsMonitored.CountSetBits(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue((int32_t)((const Fan*)self)->sensorsMonitored.GetSetBitNumber(context.GetLastIndex())); } }; constexpr ObjectModelTableEntry Fan::objectModelTable[] = { // Within each group, these entries must be in alphabetical order // 0. Fan members - { "actualValue", OBJECT_MODEL_FUNC(self->lastVal), ObjectModelEntryFlags::live }, - { "blip", OBJECT_MODEL_FUNC(0.001f * (float)self->blipTime), ObjectModelEntryFlags::none }, - { "max", OBJECT_MODEL_FUNC(self->maxVal), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->minVal), ObjectModelEntryFlags::none }, + { "actualValue", OBJECT_MODEL_FUNC(self->lastVal, 1), ObjectModelEntryFlags::live }, + { "blip", OBJECT_MODEL_FUNC(0.001f * (float)self->blipTime, 2), ObjectModelEntryFlags::none }, + { "max", OBJECT_MODEL_FUNC(self->maxVal, 2), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->minVal, 2), ObjectModelEntryFlags::none }, { "name", OBJECT_MODEL_FUNC(self->name.c_str()), ObjectModelEntryFlags::none }, - { "requestedValue", OBJECT_MODEL_FUNC(self->val), ObjectModelEntryFlags::live }, + { "requestedValue", OBJECT_MODEL_FUNC(self->val, 2), ObjectModelEntryFlags::live }, { "rpm", OBJECT_MODEL_FUNC(self->GetRPM()), ObjectModelEntryFlags::live }, { "thermostatic", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none }, // 1. Fan.thermostatic members - { "control", OBJECT_MODEL_FUNC(self->sensorsMonitored != 0), ObjectModelEntryFlags::none }, - { "heaters", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored != 0, &monitoredSensorsArrayDescriptor), ObjectModelEntryFlags::none }, - { "highTemperature", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored != 0, self->triggerTemperatures[1]), ObjectModelEntryFlags::none }, - { "lowTemperature", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored != 0, self->triggerTemperatures[0]), ObjectModelEntryFlags::none }, + { "control", OBJECT_MODEL_FUNC(self->sensorsMonitored.IsNonEmpty()), ObjectModelEntryFlags::none }, + { "heaters", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored.IsNonEmpty(), &monitoredSensorsArrayDescriptor), ObjectModelEntryFlags::none }, + { "highTemperature", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored.IsNonEmpty(), self->triggerTemperatures[1], 1), ObjectModelEntryFlags::none }, + { "lowTemperature", OBJECT_MODEL_FUNC_IF(self->sensorsMonitored.IsNonEmpty(), self->triggerTemperatures[0], 1), ObjectModelEntryFlags::none }, }; constexpr uint8_t Fan::objectModelTableDescriptor[] = { 2, 8, 4 }; @@ -58,7 +60,6 @@ Fan::Fan(unsigned int fanNum) noexcept maxVal(1.0), // 100% maximum fan speed lastRpm(-1), whenLastRpmSet(0), blipTime(DefaultFanBlipTime), - sensorsMonitored(0), isConfigured(false) { triggerTemperatures[0] = triggerTemperatures[1] = DefaultHotEndFanTemperature; @@ -128,7 +129,7 @@ bool Fan::Configure(unsigned int mcode, size_t fanNum, GCodeBuffer& gb, const St gb.GetIntArray(sensors, numH, false); // Note that M106 H-1 disables thermostatic mode. The following code implements that automatically. - sensorsMonitored = 0; + sensorsMonitored.Clear(); for (size_t h = 0; h < numH; ++h) { const int hnum = sensors[h]; @@ -136,7 +137,7 @@ bool Fan::Configure(unsigned int mcode, size_t fanNum, GCodeBuffer& gb, const St { if (hnum < (int)MaxSensors) { - SetBit(sensorsMonitored, (unsigned int)hnum); + sensorsMonitored.SetBit((unsigned int)hnum); } else { @@ -145,7 +146,7 @@ bool Fan::Configure(unsigned int mcode, size_t fanNum, GCodeBuffer& gb, const St } } } - if (sensorsMonitored != 0) + if (sensorsMonitored.IsNonEmpty()) { val = 1.0; // default the fan speed to full for safety } @@ -186,16 +187,10 @@ bool Fan::Configure(unsigned int mcode, size_t fanNum, GCodeBuffer& gb, const St (int)(maxVal * 100.0), (double)(blipTime * MillisToSeconds) ); - if (sensorsMonitored != 0) + if (sensorsMonitored.IsNonEmpty()) { reply.catf(", temperature: %.1f:%.1fC, sensors:", (double)triggerTemperatures[0], (double)triggerTemperatures[1]); - SensorsBitmap copySensorsMonitored = sensorsMonitored; - while (copySensorsMonitored != 0) - { - const unsigned int sensorNum = LowestSetBit(copySensorsMonitored); - ClearBit(copySensorsMonitored, sensorNum); - reply.catf(" %u", sensorNum); - } + sensorsMonitored.Iterate([&reply](unsigned int sensorNum) { reply.catf(" %u", sensorNum); }); reply.catf(", current speed: %d%%:", (int)(lastVal * 100.0)); } } @@ -220,42 +215,12 @@ int32_t Fan::GetRPM() const noexcept return lastRpm; } -// Object model support functions -size_t Fan::GetNumMonitoredSensors() const noexcept -{ - static constexpr uint8_t bitCount[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; - SensorsBitmap copySensorsMonitored = sensorsMonitored; - size_t count = 0; - while (copySensorsMonitored != 0) - { - count += bitCount[copySensorsMonitored & 0x0F]; - copySensorsMonitored >>= 4; - } - return count; -} - -int32_t Fan::GetMonitoredSensorNumber(size_t index) const noexcept -{ - SensorsBitmap copySensorsMonitored = sensorsMonitored; - while (copySensorsMonitored != 0) - { - const unsigned int lowestBit = LowestSetBit(copySensorsMonitored); - if (index == 0) - { - return (int32_t)lowestBit; - } - ClearBit(copySensorsMonitored, lowestBit); - --index; - } - return -1; -} - #if HAS_MASS_STORAGE // Save the settings of this fan if it isn't thermostatic bool Fan::WriteSettings(FileStore *f, size_t fanNum) const noexcept { - if (sensorsMonitored == 0) + if (sensorsMonitored.IsNonEmpty()) { String fanCommand; fanCommand.printf("M106 P%u S%.2f\n", fanNum, (double)val); diff --git a/src/Fans/Fan.h b/src/Fans/Fan.h index f6552b9d..2e8e9bd2 100644 --- a/src/Fans/Fan.h +++ b/src/Fans/Fan.h @@ -45,7 +45,7 @@ public: int32_t GetRPM() const noexcept; GCodeResult SetPwm(float speed, const StringRef& reply) noexcept; - bool HasMonitoredSensors() const noexcept { return sensorsMonitored != 0; } + bool HasMonitoredSensors() const noexcept { return sensorsMonitored.IsNonEmpty(); } const char *GetName() const noexcept { return name.c_str(); } #if HAS_MASS_STORAGE @@ -63,9 +63,6 @@ protected: void SetLastRpm(float rpm) noexcept { lastRpm = rpm; whenLastRpmSet = millis(); } - size_t GetNumMonitoredSensors() const noexcept; - int32_t GetMonitoredSensorNumber(size_t index) const noexcept; - unsigned int fanNumber; // Variables that control the fan diff --git a/src/Fans/FansManager.cpp b/src/Fans/FansManager.cpp index 8558225b..a1f5337a 100644 --- a/src/Fans/FansManager.cpp +++ b/src/Fans/FansManager.cpp @@ -103,7 +103,7 @@ GCodeResult FansManager::ConfigureFanPort(uint32_t fanNum, GCodeBuffer& gb, cons WriteLocker lock(fansLock); Fan *oldFan = nullptr; - std::swap(oldFan, fans[fanNum]); + std::swap(oldFan, fans[fanNum]); delete oldFan; const PwmFrequency freq = (gb.Seen('Q')) ? gb.GetPwmFrequency() : DefaultFanPwmFreq; diff --git a/src/Fans/LocalFan.cpp b/src/Fans/LocalFan.cpp index 4d3daf21..9980d91d 100644 --- a/src/Fans/LocalFan.cpp +++ b/src/Fans/LocalFan.cpp @@ -70,10 +70,10 @@ void LocalFan::InternalRefresh() noexcept { float reqVal; #if HAS_SMART_DRIVERS - uint32_t driverChannelsMonitored = 0; + DriverChannelsBitmap driverChannelsMonitored; #endif - if (sensorsMonitored == 0) + if (sensorsMonitored.IsEmpty()) { reqVal = val; } @@ -81,40 +81,43 @@ void LocalFan::InternalRefresh() noexcept { reqVal = 0.0; const bool bangBangMode = (triggerTemperatures[1] <= triggerTemperatures[0]); - SensorsBitmap copySensorsMonitored = sensorsMonitored; - while (copySensorsMonitored != 0) - { - const unsigned int sensorNum = LowestSetBit(copySensorsMonitored); - ClearBit(copySensorsMonitored, sensorNum); - const auto sensor = reprap.GetHeat().FindSensor(sensorNum); - if (sensor.IsNotNull()) + sensorsMonitored.Iterate + ([&reqVal, bangBangMode, this +#if HAS_SMART_DRIVERS + , &driverChannelsMonitored +#endif + ](unsigned int sensorNum) { - //TODO we used to turn the fan on if the associated heater was being tuned - float ht; - const TemperatureError err = sensor->GetLatestTemperature(ht); - if (err != TemperatureError::success || ht < BadLowTemperature || ht >= triggerTemperatures[1]) - { - reqVal = max(reqVal, (bangBangMode) ? max(0.5, val) : 1.0); - } - else if (!bangBangMode && ht > triggerTemperatures[0]) - { - // We already know that ht < triggerTemperatures[1], therefore unless we have NaNs it is safe to divide by (triggerTemperatures[1] - triggerTemperatures[0]) - reqVal = max(reqVal, (ht - triggerTemperatures[0])/(triggerTemperatures[1] - triggerTemperatures[0])); - } - else if (lastVal != 0.0 && ht + ThermostatHysteresis > triggerTemperatures[0]) // if the fan is on, add a hysteresis before turning it off + const auto sensor = reprap.GetHeat().FindSensor(sensorNum); + if (sensor.IsNotNull()) { - const float minFanSpeed = (bangBangMode) ? max(0.5, val) : minVal; - reqVal = constrain(reqVal, minFanSpeed, maxVal); - } + //TODO we used to turn the fan on if the associated heater was being tuned + float ht; + const TemperatureError err = sensor->GetLatestTemperature(ht); + if (err != TemperatureError::success || ht < BadLowTemperature || ht >= triggerTemperatures[1]) + { + reqVal = max(reqVal, (bangBangMode) ? max(0.5, val) : 1.0); + } + else if (!bangBangMode && ht > triggerTemperatures[0]) + { + // We already know that ht < triggerTemperatures[1], therefore unless we have NaNs it is safe to divide by (triggerTemperatures[1] - triggerTemperatures[0]) + reqVal = max(reqVal, (ht - triggerTemperatures[0])/(triggerTemperatures[1] - triggerTemperatures[0])); + } + else if (lastVal != 0.0 && ht + ThermostatHysteresis > triggerTemperatures[0]) // if the fan is on, add a hysteresis before turning it off + { + const float minFanSpeed = (bangBangMode) ? max(0.5, val) : minVal; + reqVal = constrain(reqVal, minFanSpeed, maxVal); + } #if HAS_SMART_DRIVERS - const int channel = sensor->GetSmartDriversChannel(); - if (channel >= 0) - { - driverChannelsMonitored |= 1 << (unsigned int)channel; - } + const int channel = sensor->GetSmartDriversChannel(); + if (channel >= 0) + { + driverChannelsMonitored.SetBit((unsigned int)channel); + } #endif + } } - } + ); } if (reqVal > 0.0) @@ -124,7 +127,7 @@ void LocalFan::InternalRefresh() noexcept { // We are turning this fan on #if HAS_SMART_DRIVERS - if (driverChannelsMonitored != 0) + if (driverChannelsMonitored.IsNonEmpty()) { reprap.GetPlatform().DriverCoolingFansOnOff(driverChannelsMonitored, true); // tell Platform that we have started a fan that cools drivers } @@ -150,7 +153,7 @@ void LocalFan::InternalRefresh() noexcept } } #if HAS_SMART_DRIVERS - else if (driverChannelsMonitored != 0 && lastVal != 0.0) + else if (driverChannelsMonitored.IsNonEmpty() && lastVal != 0.0) { reprap.GetPlatform().DriverCoolingFansOnOff(driverChannelsMonitored, false); // tell Platform that we have stopped a fan that cools drivers } @@ -185,11 +188,11 @@ bool LocalFan::UpdateFanConfiguration(const StringRef& reply) noexcept bool LocalFan::Check() noexcept { - if (sensorsMonitored != 0 || blipping) + if (sensorsMonitored.IsNonEmpty() || blipping) { InternalRefresh(); } - return sensorsMonitored != 0 && lastVal != 0.0; + return sensorsMonitored.IsNonEmpty() && lastVal != 0.0; } bool LocalFan::AssignPorts(const char *pinNames, const StringRef& reply) noexcept diff --git a/src/Fans/RemoteFan.cpp b/src/Fans/RemoteFan.cpp index 178608d4..79216346 100644 --- a/src/Fans/RemoteFan.cpp +++ b/src/Fans/RemoteFan.cpp @@ -85,7 +85,7 @@ bool RemoteFan::UpdateFanConfiguration(const StringRef& reply) noexcept msg->maxVal = maxVal; msg->triggerTemperatures[0] = triggerTemperatures[0]; msg->triggerTemperatures[1] = triggerTemperatures[1]; - msg->sensorsMonitored = sensorsMonitored; + msg->sensorsMonitored = sensorsMonitored.GetRaw(); return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply) == GCodeResult::ok; } diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index 782bab0e..4036b4be 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -1646,7 +1646,7 @@ void StringParser::AppendAsString(ExpressionValue val, const StringRef& str) break; case TYPE_OF(float): - str.catf((val.param == 3) ? "%.3f" : (val.param == 2) ? "%.2f" : "%.1f", (double)val.fVal); + str.catf(val.GetFloatFormatString(), (double)val.fVal); break; case TYPE_OF(uint32_t): @@ -1667,7 +1667,7 @@ void StringParser::AppendAsString(ExpressionValue val, const StringRef& str) case TYPE_OF(DateTime): { - const time_t time = val.Get40BitValue(); + const time_t time = val.Get56BitValue(); tm timeInfo; gmtime_r(&time, &timeInfo); str.catf("%04u-%02u-%02u %02u:%02u:%02u", @@ -1918,6 +1918,7 @@ ExpressionValue StringParser::ParseExpression(StringBuffer& stringBuffer, uint8_ if (val.type == TYPE_OF(float)) { val.fVal += val2.fVal; + val.param = max(val.param, val2.param); } else { @@ -1930,6 +1931,7 @@ ExpressionValue StringParser::ParseExpression(StringBuffer& stringBuffer, uint8_ if (val.type == TYPE_OF(float)) { val.fVal -= val2.fVal; + val.param = max(val.param, val2.param); } else { @@ -1942,6 +1944,7 @@ ExpressionValue StringParser::ParseExpression(StringBuffer& stringBuffer, uint8_ if (val.type == TYPE_OF(float)) { val.fVal *= val2.fVal; + val.param = max(val.param, val2.param); } else { @@ -1953,6 +1956,7 @@ ExpressionValue StringParser::ParseExpression(StringBuffer& stringBuffer, uint8_ ConvertToFloat(val, evaluate); ConvertToFloat(val2, evaluate); val.fVal /= val2.fVal; + val.param = 0; break; case '>': @@ -2128,6 +2132,7 @@ void StringParser::ConvertToFloat(ExpressionValue& val, bool evaluate) case TYPE_OF(int32_t): val.fVal = (float)val.iVal; val.type = TYPE_OF(float); + val.param = 1; break; case TYPE_OF(float): @@ -2263,6 +2268,7 @@ ExpressionValue StringParser::ParseNumber() if (isFloat) { retvalue.type = TYPE_OF(float); + retvalue.param = constrain(digitsAfterPoint, 1, MaxFloatDigitsDisplayedAfterPoint); if (valueAfterPoint != 0) { if (valueBeforePoint == 0) @@ -2385,6 +2391,7 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff if (gb.buffer[readPointer] == '(') { // It's a function call + ++readPointer; ExpressionValue rslt = ParseExpression(stringBuffer, 0, evaluate); if (id.Equals("abs")) { @@ -2410,31 +2417,37 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff { ConvertToFloat(rslt, evaluate); rslt.fVal = sinf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("cos")) { ConvertToFloat(rslt, evaluate); rslt.fVal = cosf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("tan")) { ConvertToFloat(rslt, evaluate); rslt.fVal = tanf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("asin")) { ConvertToFloat(rslt, evaluate); rslt.fVal = asinf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("acos")) { ConvertToFloat(rslt, evaluate); rslt.fVal = acosf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("atan")) { ConvertToFloat(rslt, evaluate); rslt.fVal = atanf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("atan2")) { @@ -2449,11 +2462,13 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff ExpressionValue nextOperand = ParseExpression(stringBuffer, 0, evaluate); ConvertToFloat(nextOperand, evaluate); rslt.fVal = atan2f(rslt.fVal, nextOperand.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("sqrt")) { ConvertToFloat(rslt, evaluate); rslt.fVal = sqrtf(rslt.fVal); + rslt.param = MaxFloatDigitsDisplayedAfterPoint; } else if (id.Equals("isnan")) { @@ -2477,6 +2492,7 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff if (rslt.type == TYPE_OF(float)) { rslt.fVal = max(rslt.fVal, nextOperand.fVal); + rslt.param = max(rslt.param, nextOperand.param); } else { @@ -2500,6 +2516,7 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff if (rslt.type == TYPE_OF(float)) { rslt.fVal = min(rslt.fVal, nextOperand.fVal); + rslt.param = max(rslt.param, nextOperand.param); } else { @@ -2516,6 +2533,7 @@ ExpressionValue StringParser::ParseIdentifierExpression(StringBuffer& stringBuff { throw ConstructParseException("expected ')'"); } + ++readPointer; return rslt; } diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp index 8412b4c3..e2bef1cf 100644 --- a/src/GCodes/GCodeMachineState.cpp +++ b/src/GCodes/GCodeMachineState.cpp @@ -20,7 +20,7 @@ GCodeMachineState::GCodeMachineState() noexcept #if HAS_LINUX_INTERFACE fileId(0), #endif - lockedResources(0), errorMessage(nullptr), + errorMessage(nullptr), lineNumber(0), compatibility(Compatibility::reprapFirmware), drivesRelative(false), axesRelative(false), #if HAS_LINUX_INTERFACE diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h index 303a3aa8..c348e63a 100644 --- a/src/GCodes/GCodeMachineState.h +++ b/src/GCodes/GCodeMachineState.h @@ -132,7 +132,7 @@ enum class BlockType : uint8_t class GCodeMachineState { public: - typedef uint32_t ResourceBitmap; + typedef Bitmap ResourceBitmap; // Class to record the state of blocks when using conditional GCode class BlockState diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 1df814ba..db69dc0c 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -265,7 +265,7 @@ void GCodes::Reset() noexcept { tr.Init(); } - triggersPending = 0; + triggersPending.Clear(); simulationMode = 0; exitSimulationWhenFileComplete = updateFileWhenSimulationComplete = false; @@ -737,19 +737,19 @@ void GCodes::CheckTriggers() noexcept { for (unsigned int i = 0; i < MaxTriggers; ++i) { - if (!IsBitSet(triggersPending, i) && triggers[i].Check()) + if (!triggersPending.IsBitSet(i) && triggers[i].Check()) { - SetBit(triggersPending, i); + triggersPending.SetBit(i); } } // If any triggers are pending, activate the one with the lowest number - if (triggersPending != 0) + if (triggersPending.IsNonEmpty()) { - const unsigned int lowestTriggerPending = LowestSetBitNumber(triggersPending); + const unsigned int lowestTriggerPending = triggersPending.LowestSetBit(); if (lowestTriggerPending == 0) { - ClearBit(triggersPending, lowestTriggerPending); // clear the trigger + triggersPending.ClearBit(lowestTriggerPending); // clear the trigger DoEmergencyStop(); } else if (!IsDaemonBusy() && daemonGCode->GetState() == GCodeState::normal) // if we are not already executing a trigger or config.g @@ -758,17 +758,17 @@ void GCodes::CheckTriggers() noexcept { if (!IsReallyPrinting()) { - ClearBit(triggersPending, lowestTriggerPending); // ignore a pause trigger if we are already paused or not printing + triggersPending.ClearBit(lowestTriggerPending); // ignore a pause trigger if we are already paused or not printing } else if (LockMovement(*daemonGCode)) // need to lock movement before executing the pause macro { - ClearBit(triggersPending, lowestTriggerPending); // clear the trigger + triggersPending.ClearBit(lowestTriggerPending); // clear the trigger DoPause(*daemonGCode, PauseReason::trigger, "Print paused by external trigger"); } } else { - ClearBit(triggersPending, lowestTriggerPending); // clear the trigger + triggersPending.ClearBit(lowestTriggerPending); // clear the trigger String filename; filename.printf("trigger%u.g", lowestTriggerPending); DoFileMacro(*daemonGCode, filename.c_str(), true); @@ -954,7 +954,7 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg) noexc if (msg != nullptr) { - platform.SendAlert(GenericMessage, msg, "Printing paused", 1, 0.0, 0); + platform.SendAlert(GenericMessage, msg, "Printing paused", 1, 0.0, AxesBitmap()); } } @@ -1528,7 +1528,7 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, bool isPrintingM } moveBuffer.hasExtrusion = false; moveBuffer.virtualExtruderPosition = virtualExtruderPosition; // save this before we update it - ExtrudersBitmap extrudersMoving = 0; + ExtrudersBitmap extrudersMoving; // Check if we are extruding if (gb.Seen(extrudeLetter)) // DC 2018-08-07: at E3D's request, extrusion is now recognised even on uncoordinated moves @@ -1591,7 +1591,7 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, bool isPrintingM } moveBuffer.coords[ExtruderToLogicalDrive(extruder)] = extrusionAmount * extrusionFactors[extruder]; - SetBit(extrudersMoving, extruder); + extrudersMoving.SetBit(extruder); } } if (!isPrintingMove && moveBuffer.usingStandardFeedrate) @@ -1623,7 +1623,7 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, bool isPrintingM rawExtruderTotal += extrusionAmount; } moveBuffer.coords[ExtruderToLogicalDrive(extruder)] = extrusionAmount * extrusionFactors[extruder] * volumetricExtrusionFactors[extruder]; - SetBit(extrudersMoving, extruder); + extrudersMoving.SetBit(extruder); } } } @@ -1651,7 +1651,7 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, bool isPrintingM // Check that enough axes have been homed, returning true if insufficient axes homed bool GCodes::CheckEnoughAxesHomed(AxesBitmap axesMoved) noexcept { - return (reprap.GetMove().GetKinematics().MustBeHomedAxes(axesMoved, noMovesBeforeHoming) & ~axesHomed) != 0; + return (reprap.GetMove().GetKinematics().MustBeHomedAxes(axesMoved, noMovesBeforeHoming) & ~axesHomed).IsNonEmpty(); } // Execute a straight move returning an error message if the command was rejected, else nullptr @@ -1676,7 +1676,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) moveBuffer.moveType = 0; moveBuffer.tool = reprap.GetCurrentTool(); moveBuffer.usePressureAdvance = false; - axesToSenseLength = 0; + axesToSenseLength.Clear(); // Check to see if the move is a 'homing' move that endstops are checked on. // We handle H1 parameters affecting extrusion elsewhere. @@ -1767,7 +1767,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) // Deal with axis movement const float initialX = currentUserPosition[X_AXIS]; const float initialY = currentUserPosition[Y_AXIS]; - AxesBitmap axesMentioned = 0; + AxesBitmap axesMentioned; for (size_t axis = 0; axis < numVisibleAxes; axis++) { if (gb.Seen(axisLetters[axis])) @@ -1778,7 +1778,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) return "G0/G1: attempt to move individual motors of a delta machine to absolute positions"; } - SetBit(axesMentioned, axis); + axesMentioned.SetBit(axis); const float moveArg = gb.GetDistance(); if (moveBuffer.moveType != 0) { @@ -1829,7 +1829,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) break; case 1: - if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & LowestNBits(numTotalAxes), true)) + if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & AxesBitmap::MakeLowestNBits(numTotalAxes), true)) { return "Failed to enable endstops"; } @@ -1837,8 +1837,8 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) break; case 3: - axesToSenseLength = axesMentioned & LowestNBits(numTotalAxes); - if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & LowestNBits(numTotalAxes), false)) + axesToSenseLength = axesMentioned & AxesBitmap::MakeLowestNBits(numTotalAxes); + if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & AxesBitmap::MakeLowestNBits(numTotalAxes), false)) { return "Failed to enable endstops"; } @@ -1850,7 +1850,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) break; } - LoadExtrusionAndFeedrateFromGCode(gb, axesMentioned != 0); // for type 1 moves, this must be called after calling EnableAxisEndstops, because EnableExtruderEndstop assumes that + LoadExtrusionAndFeedrateFromGCode(gb, axesMentioned.IsNonEmpty()); // for type 1 moves, this must be called after calling EnableAxisEndstops, because EnableExtruderEndstop assumes that // Set up the move. We must assign segmentsLeft last, so that when Move runs as a separate task the move won't be picked up by the Move process before it is complete. // Note that if this is an extruder-only move, we don't do axis movements to allow for tool offset changes, we defer those until an axis moves. @@ -1860,13 +1860,13 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) totalSegments = 1; gb.SetState(GCodeState::waitingForSpecialMoveToComplete); } - else if (axesMentioned == 0) + else if (axesMentioned.IsEmpty()) { totalSegments = 1; } else { - if (&gb == fileGCode && !gb.IsDoingFileMacro() && moveBuffer.hasExtrusion && (axesMentioned & ((1 << X_AXIS) | (1 << Y_AXIS))) != 0) + if (&gb == fileGCode && !gb.IsDoingFileMacro() && moveBuffer.hasExtrusion && axesMentioned.Intersects(XyAxes)) { lastPrintingMoveHeight = currentUserPosition[Z_AXIS]; } @@ -1876,7 +1876,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) AxesBitmap effectiveAxesHomed = axesHomed; if (doingManualBedProbe) { - ClearBit(effectiveAxesHomed, Z_AXIS); // if doing a manual Z probe, don't limit the Z movement + effectiveAxesHomed.ClearBit(Z_AXIS); // if doing a manual Z probe, don't limit the Z movement } if (moveBuffer.moveType == 0) @@ -1933,8 +1933,8 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated) // The movement code will only apply pressure advance if there is forward extrusion, so we only need to check for XYU.. movement here. { AxesBitmap axesMentionedExceptZ = axesMentioned; - ClearBit(axesMentionedExceptZ, Z_AXIS); - moveBuffer.usePressureAdvance = moveBuffer.hasExtrusion && (axesMentionedExceptZ != 0); + axesMentionedExceptZ.ClearBit(Z_AXIS); + moveBuffer.usePressureAdvance = moveBuffer.hasExtrusion && axesMentionedExceptZ.IsNonEmpty(); } // Apply segmentation if necessary. To speed up simulation on SCARA printers, we don't apply kinematics segmentation when simulating. @@ -2093,7 +2093,7 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise) const bool wholeCircle = (moveBuffer.initialUserX == currentUserPosition[X_AXIS] && moveBuffer.initialUserY == currentUserPosition[Y_AXIS]); // Get any additional axes - AxesBitmap axesMentioned = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); + AxesBitmap axesMentioned = XyAxes; for (size_t axis = Z_AXIS; axis < numVisibleAxes; axis++) { if (gb.Seen(axisLetters[axis])) @@ -2115,7 +2115,7 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise) { currentUserPosition[axis] = moveArg + GetWorkplaceOffset(axis); } - SetBit(axesMentioned, axis); + axesMentioned.SetBit(axis); } } @@ -2150,11 +2150,11 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise) const AxesBitmap yAxes = reprap.GetCurrentYAxes(); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - if (IsBitSet(xAxes, axis)) + if (xAxes.IsBitSet(axis)) { arcCentre[axis] = (userArcCentreX * axisScaleFactors[axis]) + currentBabyStepOffsets[axis] - Tool::GetOffset(reprap.GetCurrentTool(), X_AXIS); } - else if (IsBitSet(yAxes, axis)) + else if (yAxes.IsBitSet(axis)) { arcCentre[axis] = (userArcCentreY * axisScaleFactors[axis]) + currentBabyStepOffsets[axis] - Tool::GetOffset(reprap.GetCurrentTool(), Y_AXIS); } @@ -2315,12 +2315,12 @@ bool GCodes::ReadMove(RawMove& m) noexcept for (size_t drive = 0; drive < numVisibleAxes; ++drive) { - if (doingArcMove && drive != Z_AXIS && IsBitSet(Tool::GetYAxes(moveBuffer.tool), drive)) + if (doingArcMove && drive != Z_AXIS && Tool::GetYAxes(moveBuffer.tool).IsBitSet(drive)) { // Y axis or a substitute Y axis moveBuffer.initialCoords[drive] = arcCentre[drive] + arcRadius * axisScaleFactors[drive] * sinf(arcCurrentAngle); } - else if (doingArcMove && drive != Z_AXIS && IsBitSet(Tool::GetXAxes(moveBuffer.tool), drive)) + else if (doingArcMove && drive != Z_AXIS && Tool::GetXAxes(moveBuffer.tool).IsBitSet(drive)) { // X axis or a substitute X axis moveBuffer.initialCoords[drive] = arcCentre[drive] + arcRadius * axisScaleFactors[drive] * cosf(arcCurrentAngle); @@ -2516,20 +2516,20 @@ GCodeResult GCodes::DoHome(GCodeBuffer& gb, const StringRef& reply) #endif // Find out which axes we have been asked to home - toBeHomed = 0; + toBeHomed.Clear(); for (size_t axis = 0; axis < numTotalAxes; ++axis) { if (gb.Seen(axisLetters[axis])) { - SetBit(toBeHomed, axis); + toBeHomed.SetBit(axis); SetAxisNotHomed(axis); } } - if (toBeHomed == 0) + if (toBeHomed.IsEmpty()) { SetAllAxesNotHomed(); // homing everything - toBeHomed = LowestNBits(numVisibleAxes); + toBeHomed = AxesBitmap::MakeLowestNBits(numVisibleAxes); } gb.SetState(GCodeState::homing1); @@ -2631,7 +2631,7 @@ void GCodes::DoManualProbe(GCodeBuffer& gb, const char *message, const char *tit // Do a manual bed probe. On entry the state variable is the state we want to return to when the user has finished adjusting the height. void GCodes::DoManualBedProbe(GCodeBuffer& gb) { - DoManualProbe(gb, "Adjust height until the nozzle just touches the bed, then press OK", "Manual bed probing", MakeBitmap(Z_AXIS)); + DoManualProbe(gb, "Adjust height until the nozzle just touches the bed, then press OK", "Manual bed probing", AxesBitmap::MakeFromBits(Z_AXIS)); } // Start probing the grid, returning true if we didn't because of an error. @@ -3082,7 +3082,7 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) uint32_t xMapping[MaxAxes]; size_t xCount = numVisibleAxes; gb.GetUnsignedArray(xMapping, xCount, false); - xMap = UnsignedArrayToBitMap(xMapping, xCount) & LowestNBits(numVisibleAxes); + xMap = AxesBitmap::MakeFromArray(xMapping, xCount) & AxesBitmap::MakeLowestNBits(numVisibleAxes); seen = true; } else @@ -3097,7 +3097,7 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) uint32_t yMapping[MaxAxes]; size_t yCount = numVisibleAxes; gb.GetUnsignedArray(yMapping, yCount, false); - yMap = UnsignedArrayToBitMap(yMapping, yCount) & LowestNBits(numVisibleAxes); + yMap = AxesBitmap::MakeFromArray(yMapping, yCount) & AxesBitmap::MakeLowestNBits(numVisibleAxes); seen = true; } else @@ -3105,7 +3105,7 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) yMap = DefaultYAxisMapping; // by default map X axis straight through } - if ((xMap & yMap) != 0) + if (xMap.Intersects(yMap)) { reply.copy("Cannot map both X and Y to the same axis"); return GCodeResult::error; @@ -3118,12 +3118,12 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) uint32_t fanMapping[MaxFans]; size_t fanCount = MaxFans; gb.GetUnsignedArray(fanMapping, fanCount, false); - fanMap = UnsignedArrayToBitMap(fanMapping, fanCount) & LowestNBits(MaxFans); + fanMap = FansBitmap::MakeFromArray(fanMapping, fanCount) & FansBitmap::MakeLowestNBits(MaxFans); seen = true; } else { - fanMap = 1; // by default map fan 0 to fan 0 + fanMap.SetBit(0); // by default map fan 0 to fan 0 } if (seen) @@ -3194,14 +3194,8 @@ void GCodes::SetMappedFanSpeed(float f) noexcept } else { - const uint32_t fanMap = ct->GetFanMapping(); - for (size_t i = 0; i < MaxFans; ++i) - { - if (IsBitSet(fanMap, i)) - { - reprap.GetFansManager().SetFanValue(i, f); - } - } + const FansBitmap fanMap = ct->GetFanMapping(); + fanMap.Iterate([f](unsigned int i) { reprap.GetFansManager().SetFanValue(i, f); }); } } @@ -3209,8 +3203,9 @@ void GCodes::SetMappedFanSpeed(float f) noexcept bool GCodes::IsMappedFan(unsigned int fanNumber) noexcept { const Tool * const ct = reprap.GetCurrentTool(); - return (ct == nullptr) ? fanNumber == 0 - : IsBitSet(ct->GetFanMapping(), fanNumber); + return (ct == nullptr) + ? fanNumber == 0 + : ct->GetFanMapping().IsBitSet(fanNumber); } // Save the speeds of all fans @@ -3851,14 +3846,14 @@ void GCodes::ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[ const AxesBitmap yAxes = currentTool->GetYAxisMap(); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - if ( (axis != X_AXIS || IsBitSet(xAxes, X_AXIS)) - && (axis != Y_AXIS || IsBitSet(yAxes, Y_AXIS)) + if ( (axis != X_AXIS || xAxes.IsBitSet(X_AXIS)) + && (axis != Y_AXIS || yAxes.IsBitSet(Y_AXIS)) ) { const float totalOffset = currentBabyStepOffsets[axis] - currentTool->GetOffset(axis); - const size_t inputAxis = (IsBitSet(explicitAxes, axis)) ? axis - : (IsBitSet(xAxes, axis)) ? X_AXIS - : (IsBitSet(yAxes, axis)) ? Y_AXIS + const size_t inputAxis = (explicitAxes.IsBitSet(axis)) ? axis + : (xAxes.IsBitSet(axis)) ? X_AXIS + : (yAxes.IsBitSet(axis)) ? Y_AXIS : axis; coordsOut[axis] = (coordsIn[inputAxis] * axisScaleFactors[axis]) + totalOffset; } @@ -3881,8 +3876,8 @@ void GCodes::ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coo } else { - const uint32_t xAxes = reprap.GetCurrentXAxes(); - const uint32_t yAxes = reprap.GetCurrentYAxes(); + const AxesBitmap xAxes = reprap.GetCurrentXAxes(); + const AxesBitmap yAxes = reprap.GetCurrentYAxes(); float xCoord = 0.0, yCoord = 0.0; size_t numXAxes = 0, numYAxes = 0; for (size_t axis = 0; axis < numVisibleAxes; ++axis) @@ -3890,12 +3885,12 @@ void GCodes::ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coo const float totalOffset = currentBabyStepOffsets[axis] - currentTool->GetOffset(axis); const float coord = (coordsIn[axis] - totalOffset)/axisScaleFactors[axis]; coordsOut[axis] = coord; - if (IsBitSet(xAxes, axis)) + if (xAxes.IsBitSet(axis)) { xCoord += coord; ++numXAxes; } - if (IsBitSet(yAxes, axis)) + if (yAxes.IsBitSet(axis)) { yCoord += coord; ++numYAxes; @@ -3981,20 +3976,20 @@ GCodeResult GCodes::AdvanceHash(const StringRef &reply) noexcept bool GCodes::AllAxesAreHomed() const noexcept { - const AxesBitmap allAxes = LowestNBits(numVisibleAxes); + const AxesBitmap allAxes = AxesBitmap::MakeLowestNBits(numVisibleAxes); return (axesHomed & allAxes) == allAxes; } // Tell us that the axis is now homed void GCodes::SetAxisIsHomed(unsigned int axis) noexcept { - SetBit(axesHomed, axis); + axesHomed.SetBit(axis); } // Tell us that the axis is not homed void GCodes::SetAxisNotHomed(unsigned int axis) noexcept { - ClearBit(axesHomed, axis); + axesHomed.ClearBit(axis); if (axis == Z_AXIS) { zDatumSetByProbing = false; @@ -4004,7 +3999,7 @@ void GCodes::SetAxisNotHomed(unsigned int axis) noexcept // Flag all axes as not homed void GCodes::SetAllAxesNotHomed() noexcept { - axesHomed = 0; + axesHomed.Clear(); zDatumSetByProbing = false; } @@ -4240,7 +4235,7 @@ bool GCodes::LockResource(const GCodeBuffer& gb, Resource r) noexcept if (resourceOwners[r] == nullptr) { resourceOwners[r] = &gb; - SetBit(gb.MachineState().lockedResources, r); + gb.MachineState().lockedResources.SetBit(r); return true; } return false; @@ -4257,7 +4252,7 @@ void GCodes::GrabResource(const GCodeBuffer& gb, Resource r) noexcept GCodeMachineState *m = &(resourceOwners[r]->MachineState()); do { - ClearBit(m->lockedResources, r); + m->lockedResources.ClearBit(r); m = m->previous; } while (m != nullptr); @@ -4296,7 +4291,7 @@ void GCodes::UnlockResource(const GCodeBuffer& gb, Resource r) noexcept GCodeMachineState * mc = &gb.MachineState(); do { - ClearBit(mc->lockedResources, r); + mc->lockedResources.ClearBit(r); mc = mc->previous; } while (mc != nullptr); resourceOwners[r] = nullptr; @@ -4307,13 +4302,13 @@ void GCodes::UnlockResource(const GCodeBuffer& gb, Resource r) noexcept void GCodes::UnlockAll(const GCodeBuffer& gb) noexcept { const GCodeMachineState * const mc = gb.MachineState().previous; - const uint32_t resourcesToKeep = (mc == nullptr) ? 0 : mc->lockedResources; + const GCodeMachineState::ResourceBitmap resourcesToKeep = (mc == nullptr) ? GCodeMachineState::ResourceBitmap() : mc->lockedResources; for (size_t i = 0; i < NumResources; ++i) { - if (resourceOwners[i] == &gb && !IsBitSet(resourcesToKeep, i)) + if (resourceOwners[i] == &gb && !resourcesToKeep.IsBitSet(i)) { resourceOwners[i] = nullptr; - ClearBit(gb.MachineState().lockedResources, i); + gb.MachineState().lockedResources.ClearBit(i); } } } @@ -4321,13 +4316,7 @@ void GCodes::UnlockAll(const GCodeBuffer& gb) noexcept // Append a list of axes to a string void GCodes::AppendAxes(const StringRef& reply, AxesBitmap axes) const noexcept { - for (size_t axis = 0; axis < numVisibleAxes; ++axis) - { - if (IsBitSet(axes, axis)) - { - reply.cat(axisLetters[axis]); - } - } + axes.Iterate([reply, this](unsigned int axis) { reply.cat(this->axisLetters[axis]); }); } // Get the name of the current machine mode diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 3d08efa1..4d876db2 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -109,7 +109,7 @@ public: bool IsDaemonBusy() const noexcept; // Return true if the daemon is busy running config.g or a trigger file bool IsAxisHomed(unsigned int axis) const noexcept // Has the axis been homed? - { return IsBitSet(axesHomed, axis); } + { return axesHomed.IsBitSet(axis); } void SetAxisIsHomed(unsigned int axis) noexcept; // Tell us that the axis is now homed void SetAxisNotHomed(unsigned int axis) noexcept; // Tell us that the axis is not homed void SetAllAxesNotHomed() noexcept; // Flag all axes as not homed @@ -294,7 +294,7 @@ private: void SetMachinePosition(const float positionNow[MaxAxesPlusExtruders], bool doBedCompensation = true) noexcept; // Set the current position to be this void UpdateCurrentUserPosition() noexcept; // Get the current position from the Move class - void ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes], AxesBitmap explicitAxes = 0) const noexcept; + void ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes], AxesBitmap explicitAxes = AxesBitmap()) const noexcept; // Convert user coordinates to head reference point coordinates void ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes]) const noexcept; // Convert head reference point coordinates to user coordinates float GetCurrentToolOffset(size_t axis) const noexcept; // Get an axis offset of the current tool diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 2682321d..d4c68bcb 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -286,7 +286,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) return false; } - if ((reprap.GetMove().GetKinematics().AxesToHomeBeforeProbing() & ~axesHomed) != 0) + if (reprap.GetMove().GetKinematics().AxesToHomeBeforeProbing().Intersects(~axesHomed)) { reply.copy("Insufficient axes homed for bed probing"); result = GCodeResult::error; @@ -2387,12 +2387,12 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) break; } - AxesBitmap axisControls = 0; + AxesBitmap axisControls; for (size_t axis = 0; axis < numTotalAxes; axis++) { if (gb.Seen(axisLetters[axis]) && gb.GetIValue() > 0) { - SetBit(axisControls, axis); + axisControls.SetBit(axis); } } diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 4b07516a..cb7ffda6 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -59,20 +59,20 @@ GCodeResult GCodes::SetPositions(GCodeBuffer& gb) { // Don't wait for the machine to stop if only extruder drives are being reset. // This avoids blobs and seams when the gcode uses absolute E coordinates and periodically includes G92 E0. - AxesBitmap axesIncluded = 0; + AxesBitmap axesIncluded; for (size_t axis = 0; axis < numVisibleAxes; ++axis) { if (gb.Seen(axisLetters[axis])) { const float axisValue = gb.GetFValue(); - if (axesIncluded == 0) + if (axesIncluded.IsEmpty()) { if (!LockMovementAndWaitForStandstill(gb)) // lock movement and get current coordinates { return GCodeResult::notFinished; } } - SetBit(axesIncluded, axis); + axesIncluded.SetBit(axis); currentUserPosition[axis] = gb.ConvertDistance(axisValue); } } @@ -83,10 +83,10 @@ GCodeResult GCodes::SetPositions(GCodeBuffer& gb) virtualExtruderPosition = gb.GetDistance(); } - if (axesIncluded != 0) + if (axesIncluded.IsNonEmpty()) { ToolOffsetTransform(currentUserPosition, moveBuffer.coords); - if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, LowestNBits(numVisibleAxes), false, limitAxes) + if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, AxesBitmap::MakeLowestNBits(numVisibleAxes), false, limitAxes) != LimitPositionResult::ok // pretend that all axes are homed ) { @@ -94,7 +94,7 @@ GCodeResult GCodes::SetPositions(GCodeBuffer& gb) } reprap.GetMove().SetNewPosition(moveBuffer.coords, true); axesHomed |= reprap.GetMove().GetKinematics().AxesAssumedHomed(axesIncluded); - if (IsBitSet(axesIncluded, Z_AXIS)) + if (axesIncluded.IsBitSet(Z_AXIS)) { zDatumSetByProbing -= false; } @@ -383,7 +383,7 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const if (simulationMode == 0) { axesHomedBeforeSimulation = axesHomed; - axesHomed = LowestNBits(numVisibleAxes); // pretend all axes are homed + axesHomed = AxesBitmap::MakeLowestNBits(numVisibleAxes); // pretend all axes are homed SavePosition(simulationRestorePoint, gb); simulationRestorePoint.feedRate = gb.MachineState().feedRate; } @@ -421,7 +421,7 @@ GCodeResult GCodes::ChangeSimulationMode(GCodeBuffer& gb, const StringRef &reply { // Starting a new simulation, so save the current position axesHomedBeforeSimulation = axesHomed; - axesHomed = LowestNBits(numVisibleAxes); // pretend all axes are homed + axesHomed = AxesBitmap::MakeLowestNBits(numVisibleAxes); // pretend all axes are homed SavePosition(simulationRestorePoint, gb); } simulationTime = 0.0; @@ -502,7 +502,7 @@ GCodeResult GCodes::ConfigureTrigger(GCodeBuffer& gb, const StringRef& reply, in return GCodeResult::error; } - tr.inputStates = 0; + tr.inputStates.Clear(); (void)tr.Check(); // set up initial input states return GCodeResult::ok; } @@ -542,10 +542,10 @@ GCodeResult GCodes::CheckTrigger(GCodeBuffer& gb, const StringRef& reply, int co if (triggerNumber < MaxTriggers) { Trigger& tr = triggers[triggerNumber]; - tr.inputStates = 0; + tr.inputStates.Clear(); if (tr.Check()) { - SetBit(triggersPending, triggerNumber); + triggersPending.SetBit(triggerNumber); } return GCodeResult::ok; } @@ -841,7 +841,7 @@ GCodeResult GCodes::ProbeTool(GCodeBuffer& gb, const StringRef& reply) const bool probeOk = (useProbe) ? platform.GetEndstops().EnableZProbe(probeNumberToUse) - : platform.GetEndstops().EnableAxisEndstops(MakeBitmap(axis), false); + : platform.GetEndstops().EnableAxisEndstops(AxesBitmap::MakeFromBits(axis), false); if (!probeOk) { reply.copy("Failed to prime endstop or probe"); @@ -905,7 +905,7 @@ GCodeResult GCodes::FindCenterOfCavity(GCodeBuffer& gb, const StringRef& reply, const bool probeOk = (useProbe) ? platform.GetEndstops().EnableZProbe(probeNumberToUse) - : platform.GetEndstops().EnableAxisEndstops(MakeBitmap(axis), false); + : platform.GetEndstops().EnableAxisEndstops(AxesBitmap::MakeFromBits(axis), false); if (!probeOk) { reply.copy("Failed to prime endstop or probe"); diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp index 33761417..23a31b52 100644 --- a/src/GCodes/GCodes4.cpp +++ b/src/GCodes/GCodes4.cpp @@ -37,7 +37,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) // Check whether we made any G1 S3 moves and need to set the axis limits for (size_t axis = 0; axis < numTotalAxes; ++axis) { - if (IsBitSet(axesToSenseLength, axis)) + if (axesToSenseLength.IsBitSet(axis)) { const EndStopPosition stopType = platform.GetEndstops().GetEndStopPosition(axis); if (stopType == EndStopPosition::highEndStop) @@ -172,7 +172,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) break; case GCodeState::homing1: - if (toBeHomed == 0) + if (toBeHomed.IsEmpty()) { gb.SetState(GCodeState::normal); } @@ -180,7 +180,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) { String nextHomingFileName; AxesBitmap mustHomeFirst = reprap.GetMove().GetKinematics().GetHomingFileName(toBeHomed, axesHomed, numVisibleAxes, nextHomingFileName.GetRef()); - if (mustHomeFirst != 0) + if (mustHomeFirst.IsNonEmpty()) { // Error, can't home this axes reply.copy("Must home these axes:"); @@ -188,7 +188,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) reply.cat(" before homing these:"); AppendAxes(reply, toBeHomed); error = true; - toBeHomed = 0; + toBeHomed.Clear(); gb.SetState(GCodeState::normal); } else @@ -208,7 +208,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) if (LockMovementAndWaitForStandstill(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 & axesHomed) == 0) + if (!toBeHomed.Intersects(axesHomed)) { reply.copy("Homing failed"); error = true; @@ -217,7 +217,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) else { toBeHomed &= ~axesHomed; - gb.SetState((toBeHomed == 0) ? GCodeState::normal : GCodeState::homing1); + gb.SetState((toBeHomed.IsEmpty()) ? GCodeState::normal : GCodeState::homing1); } } break; diff --git a/src/GCodes/Trigger.cpp b/src/GCodes/Trigger.cpp index 37cbeffb..7b193655 100644 --- a/src/GCodes/Trigger.cpp +++ b/src/GCodes/Trigger.cpp @@ -48,16 +48,16 @@ bool Trigger::Check() noexcept break; } const bool b = ports[i].Read(); - if (b != IsBitSet(inputStates, i)) // if the input level has changed + if (b != inputStates.IsBitSet(i)) // if the input level has changed { if (b) { - SetBit(inputStates, i); + inputStates.SetBit(i); triggered = true; } else { - ClearBit(inputStates, i); + inputStates.ClearBit(i); } } } diff --git a/src/GCodes/Trigger.h b/src/GCodes/Trigger.h index 2683ffac..15d4781a 100644 --- a/src/GCodes/Trigger.h +++ b/src/GCodes/Trigger.h @@ -11,10 +11,10 @@ #include "RepRapFirmware.h" #include "Hardware/IoPorts.h" -typedef uint32_t TriggerNumbersBitmap; // Bitmap of trigger numbers -typedef uint16_t TriggerInputStatesBitmap; // Bitmap of input states -static_assert(MaxTriggers <= sizeof(TriggerNumbersBitmap) * CHAR_BIT, "need larger TriggerNumbersBitmap type"); -static_assert(MaxPortsPerTrigger <= sizeof(TriggerInputStatesBitmap) * CHAR_BIT, "need larger TriggerInputStatesBitmap"); +typedef Bitmap TriggerNumbersBitmap; // Bitmap of trigger numbers +typedef Bitmap TriggerInputStatesBitmap; // Bitmap of input states +static_assert(MaxTriggers <= TriggerNumbersBitmap::MaxBits(), "need larger TriggerNumbersBitmap type"); +static_assert(MaxPortsPerTrigger <= TriggerInputStatesBitmap::MaxBits(), "need larger TriggerInputStatesBitmap"); struct Trigger { diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index 34268b7c..214fdac1 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -81,10 +81,10 @@ constexpr ObjectModelTableEntry Heat::objectModelTable[] = { // These entries must be in alphabetical order // 0. Heat class - { "coldExtrudeTemperature", OBJECT_MODEL_FUNC(self->extrusionMinTemp), ObjectModelEntryFlags::none}, - { "coldRetractTemperature", OBJECT_MODEL_FUNC(self->retractionMinTemp), ObjectModelEntryFlags::none}, - { "heaters", OBJECT_MODEL_FUNC_NOSELF(&heatersArrayDescriptor), ObjectModelEntryFlags::live }, - { "sensors", OBJECT_MODEL_FUNC_NOSELF(&sensorsArrayDescriptor), ObjectModelEntryFlags::live }, + { "coldExtrudeTemperature", OBJECT_MODEL_FUNC(self->extrusionMinTemp, 1), ObjectModelEntryFlags::none}, + { "coldRetractTemperature", OBJECT_MODEL_FUNC(self->retractionMinTemp, 1), ObjectModelEntryFlags::none}, + { "heaters", OBJECT_MODEL_FUNC_NOSELF(&heatersArrayDescriptor), ObjectModelEntryFlags::live }, + { "sensors", OBJECT_MODEL_FUNC_NOSELF(&sensorsArrayDescriptor), ObjectModelEntryFlags::live }, }; constexpr uint8_t Heat::objectModelTableDescriptor[] = { 1, 4 }; diff --git a/src/Heating/Heater.cpp b/src/Heating/Heater.cpp index 3c8d49d2..a3a64add 100644 --- a/src/Heating/Heater.cpp +++ b/src/Heating/Heater.cpp @@ -25,9 +25,9 @@ constexpr ObjectModelTableEntry Heater::objectModelTable[] = { // Within each group, these entries must be in alphabetical order // 0. Heater members - { "current", OBJECT_MODEL_FUNC(self->GetTemperature()), ObjectModelEntryFlags::live }, - { "max", OBJECT_MODEL_FUNC(self->GetHighestTemperatureLimit()), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->GetLowestTemperatureLimit()), ObjectModelEntryFlags::none }, + { "current", OBJECT_MODEL_FUNC(self->GetTemperature(), 1), ObjectModelEntryFlags::live }, + { "max", OBJECT_MODEL_FUNC(self->GetHighestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->GetLowestTemperatureLimit(), 1), ObjectModelEntryFlags::none }, { "sensor", OBJECT_MODEL_FUNC((int32_t)self->GetSensorNumber()), ObjectModelEntryFlags::none }, { "state", OBJECT_MODEL_FUNC(self->GetStatus().ToString()), ObjectModelEntryFlags::live }, }; diff --git a/src/Heating/Sensors/TemperatureSensor.cpp b/src/Heating/Sensors/TemperatureSensor.cpp index 63954e99..8934d130 100644 --- a/src/Heating/Sensors/TemperatureSensor.cpp +++ b/src/Heating/Sensors/TemperatureSensor.cpp @@ -37,7 +37,7 @@ constexpr ObjectModelTableEntry TemperatureSensor::objectModelTable[] = { // Within each group, these entries must be in alphabetical order // 0. TemperatureSensor members - { "lastReading", OBJECT_MODEL_FUNC(self->lastTemperature), ObjectModelEntryFlags::live }, + { "lastReading", OBJECT_MODEL_FUNC(self->lastTemperature, 1), ObjectModelEntryFlags::live }, { "name", OBJECT_MODEL_FUNC(self->sensorName), ObjectModelEntryFlags::none }, { "type", OBJECT_MODEL_FUNC(self->sensorType), ObjectModelEntryFlags::none }, }; diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index 7e387e74..9041591b 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -308,7 +308,7 @@ bool DDA::InitStandardMove(DDARing& ring, const RawMove &nextMove, bool doMotorM { const float positionDelta = endCoordinates[drive] - prev->GetEndCoordinate(drive, false); directionVector[drive] = positionDelta; - if (positionDelta != 0.0 && (IsBitSet(Tool::GetXAxes(nextMove.tool), drive) || IsBitSet(Tool::GetYAxes(nextMove.tool), drive))) + if (positionDelta != 0.0 && (Tool::GetXAxes(nextMove.tool).IsBitSet(drive) || Tool::GetYAxes(nextMove.tool).IsBitSet(drive))) { flags.xyMoving = true; } @@ -1253,16 +1253,16 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept platform.EnableLocalDrivers(Z_AXIS); // ensure all Z motors are enabled } - AxesBitmap additionalAxisMotorsToEnable = 0, axisMotorsEnabled = 0; + AxesBitmap additionalAxisMotorsToEnable, axisMotorsEnabled; #if SUPPORT_CAN_EXPANSION - afterPrepare.drivesMoving = 0; + afterPrepare.drivesMoving.Clear(); #endif for (size_t drive = 0; drive < MaxAxesPlusExtruders; ++drive) { if (flags.isLeadscrewAdjustmentMove) { #if SUPPORT_CAN_EXPANSION - SetBit(afterPrepare.drivesMoving, Z_AXIS); + afterPrepare.drivesMoving.SetBit(Z_AXIS); #endif // For a leadscrew adjustment move, the first N elements of the direction vector are the adjustments to the N Z motors const AxisDriversConfig& config = platform.GetAxisDriversConfig(Z_AXIS); @@ -1330,7 +1330,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept } #if SUPPORT_CAN_EXPANSION - SetBit(afterPrepare.drivesMoving, drive); + afterPrepare.drivesMoving.SetBit(drive); const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive); for (size_t i = 0; i < config.numDrivers; ++i) { @@ -1341,7 +1341,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept } } #endif - SetBit(axisMotorsEnabled, drive); + axisMotorsEnabled.SetBit(drive); } else if (drive < reprap.GetGCodes().GetTotalAxes()) { @@ -1386,7 +1386,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept } #if SUPPORT_CAN_EXPANSION - SetBit(afterPrepare.drivesMoving, drive); + afterPrepare.drivesMoving.SetBit(drive); const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive); for (size_t i = 0; i < config.numDrivers; ++i) { @@ -1397,7 +1397,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept } } #endif - SetBit(axisMotorsEnabled, drive); + axisMotorsEnabled.SetBit(drive); additionalAxisMotorsToEnable |= reprap.GetMove().GetKinematics().GetConnectedAxes(drive); } } @@ -1421,7 +1421,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept const size_t extruder = LogicalDriveToExtruder(drive); #if SUPPORT_CAN_EXPANSION - SetBit(afterPrepare.drivesMoving, drive); + afterPrepare.drivesMoving.SetBit(drive); const DriverId driver = platform.GetExtruderDriver(extruder); if (driver.IsRemote()) { @@ -1468,27 +1468,25 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept // On CoreXY and similar architectures, we also need to enable the motors controlling any connected axes additionalAxisMotorsToEnable &= ~axisMotorsEnabled; - for (size_t drive = 0; additionalAxisMotorsToEnable != 0; ++drive) + while (additionalAxisMotorsToEnable.IsNonEmpty()) { - if (IsBitSet(additionalAxisMotorsToEnable, drive)) + const size_t drive = additionalAxisMotorsToEnable.LowestSetBit(); + additionalAxisMotorsToEnable.ClearBit(drive); + if (platform.GetDriversBitmap(drive) != 0) // if any of the connected axis drives is local { - ClearBit(additionalAxisMotorsToEnable, drive); - if (platform.GetDriversBitmap(drive) != 0) // if any of the connected axis drives is local - { - platform.EnableLocalDrivers(drive); - } + platform.EnableLocalDrivers(drive); + } #if SUPPORT_CAN_EXPANSION - const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive); - for (size_t i = 0; i < config.numDrivers; ++i) + const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive); + for (size_t i = 0; i < config.numDrivers; ++i) + { + const DriverId driver = config.driverNumbers[i]; + if (driver.IsRemote()) { - const DriverId driver = config.driverNumbers[i]; - if (driver.IsRemote()) - { - CanMotion::AddMovement(*this, params, driver, 0, false); - } + CanMotion::AddMovement(*this, params, driver, 0, false); } -#endif } +#endif } const DDAState st = prev->state; @@ -1578,12 +1576,12 @@ float DDA::NormaliseXYZ() noexcept const AxesBitmap yAxes = Tool::GetYAxes(tool); for (size_t d = 0; d < MaxAxes; ++d) { - if (IsBitSet(xAxes, d)) + if (xAxes.IsBitSet(d)) { xMagSquared += fsquare(directionVector[d]); ++numXaxes; } - if (IsBitSet(yAxes, d)) + if (yAxes.IsBitSet(d)) { yMagSquared += fsquare(directionVector[d]); ++numYaxes; @@ -1950,8 +1948,8 @@ void DDA::StopDrive(size_t drive) noexcept } #if SUPPORT_CAN_EXPANSION - ClearBit(afterPrepare.drivesMoving, drive); - if (afterPrepare.drivesMoving == 0) + afterPrepare.drivesMoving.ClearBit(drive); + if (afterPrepare.drivesMoving.IsEmpty()) { state = completed; } diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h index cc13fdff..48b54640 100644 --- a/src/Movement/DDA.h +++ b/src/Movement/DDA.h @@ -267,7 +267,7 @@ private: int32_t cKc; // The Z movement fraction multiplied by Kc and converted to integer #if SUPPORT_CAN_EXPANSION - uint32_t drivesMoving; // bitmap of logical drives moving - needed to keep track of whether remote drives are moving + DriversBitmap drivesMoving; // bitmap of logical drives moving - needed to keep track of whether remote drives are moving static_assert(MaxAxesPlusExtruders <= sizeof(drivesMoving) * CHAR_BIT); #endif } afterPrepare; diff --git a/src/Movement/Kinematics/CoreKinematics.cpp b/src/Movement/Kinematics/CoreKinematics.cpp index ac8a30e0..ad0a6e99 100644 --- a/src/Movement/Kinematics/CoreKinematics.cpp +++ b/src/Movement/Kinematics/CoreKinematics.cpp @@ -60,7 +60,7 @@ void CoreKinematics::Recalc() { firstMotor[i] = firstAxis[i] = MaxAxes; lastMotor[i] = lastAxis[i] = 0; - connectedAxes[i] = 0; + connectedAxes[i].Clear(); } for (size_t axis = 0; axis < MaxAxes; ++axis) @@ -77,7 +77,7 @@ void CoreKinematics::Recalc() { lastAxis[motor] = axis; } - SetBit(connectedAxes[axis], motor); + connectedAxes[axis].SetBit(motor); } if (forwardMatrix(motor, axis) != 0.0) // if this motor affects this axes @@ -90,7 +90,7 @@ void CoreKinematics::Recalc() { lastMotor[axis] = motor; } - SetBit(connectedAxes[axis], motor); + connectedAxes[axis].SetBit(motor); } } } @@ -120,7 +120,7 @@ void CoreKinematics::Recalc() // Return true if the axis doesn't have a single dedicated motor inline bool CoreKinematics::HasSharedMotor(size_t axis) const { - return connectedAxes[axis] != MakeBitmap(axis); + return connectedAxes[axis] != AxesBitmap::MakeFromBits(axis); } CoreKinematics::CoreKinematics(KinematicsType k) : ZLeadscrewKinematics(k), modified(false) @@ -408,7 +408,7 @@ AxesBitmap CoreKinematics::GetConnectedAxes(size_t axis) const // This is called to determine whether we can babystep the specified axis independently of regular motion. AxesBitmap CoreKinematics::GetLinearAxes() const { - return LowestNBits(reprap.GetGCodes().GetVisibleAxes()); // we can babystep all axes + return AxesBitmap::MakeLowestNBits(reprap.GetGCodes().GetVisibleAxes()); // we can babystep all axes } // End diff --git a/src/Movement/Kinematics/FiveBarScaraKinematics.cpp b/src/Movement/Kinematics/FiveBarScaraKinematics.cpp index 0a7e7a40..ea16329c 100644 --- a/src/Movement/Kinematics/FiveBarScaraKinematics.cpp +++ b/src/Movement/Kinematics/FiveBarScaraKinematics.cpp @@ -819,10 +819,9 @@ void FiveBarScaraKinematics::GetAssumedInitialPosition(size_t numAxes, float pos AxesBitmap FiveBarScaraKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If both X and Y have been specified then we know the positions of both arm motors, otherwise we don't - const AxesBitmap xyAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); - if ((g92Axes & xyAxes) != xyAxes) + if ((g92Axes & XyAxes) != XyAxes) { - g92Axes &= ~xyAxes; + g92Axes &= ~XyAxes; } return g92Axes; } @@ -830,10 +829,9 @@ AxesBitmap FiveBarScaraKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap FiveBarScaraKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((axesMoving & xyzAxes) != 0) + if (axesMoving.Intersects(XyzAxes)) { - axesMoving |= xyzAxes; + axesMoving |= XyzAxes; } return axesMoving; } @@ -911,14 +909,14 @@ bool FiveBarScaraKinematics::IsContinuousRotationAxis(size_t axis) const AxesBitmap FiveBarScaraKinematics::GetLinearAxes() const { - return MakeBitmap(Z_AXIS); + return AxesBitmap::MakeFromBits(Z_AXIS); } AxesBitmap FiveBarScaraKinematics::GetConnectedAxes(size_t axis) const { return (axis == X_AXIS || axis == Y_AXIS) - ? MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) - : MakeBitmap(axis); + ? XyAxes + : AxesBitmap::MakeFromBits(axis); } // Recalculate the derived parameters diff --git a/src/Movement/Kinematics/HangprinterKinematics.cpp b/src/Movement/Kinematics/HangprinterKinematics.cpp index 54f431b9..5b11bf46 100644 --- a/src/Movement/Kinematics/HangprinterKinematics.cpp +++ b/src/Movement/Kinematics/HangprinterKinematics.cpp @@ -175,9 +175,8 @@ bool HangprinterKinematics::IsReachable(float x, float y, bool isCoordinated) co // Limit the Cartesian position that the user wants to move to returning true if we adjusted the position LimitPositionResult HangprinterKinematics::LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated, bool applyM208Limits) const { - const AxesBitmap allAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); bool limited = false; - if ((axesHomed & allAxes) == allAxes) + if ((axesHomed & XyzAxes) == XyzAxes) { // If axes have been homed on a delta printer and this isn't a homing move, check for movements outside limits. // Skip this check if axes have not been homed, so that extruder-only moves are allowed before homing @@ -225,7 +224,7 @@ void HangprinterKinematics::GetAssumedInitialPosition(size_t numAxes, float posi AxesBitmap HangprinterKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { filename.copy("homeall.g"); - return 0; + return AxesBitmap(); } // This function is called from the step ISR when an endstop switch is triggered during homing. @@ -246,14 +245,13 @@ void HangprinterKinematics::OnHomingSwitchTriggered(size_t axis, bool highEnd, c AxesBitmap HangprinterKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If all of X, Y and Z have been specified then we know the positions of all 4 spool motors, otherwise we don't - const uint32_t xyzAxes = (1u << X_AXIS) | (1u << Y_AXIS) | (1u << Z_AXIS); - if ((g92Axes & xyzAxes) == xyzAxes) + if ((g92Axes & XyzAxes) == XyzAxes) { - g92Axes |= (1u << D_AXIS); + g92Axes.SetBit(D_AXIS); } else { - g92Axes &= ~xyzAxes; + g92Axes &= ~XyzAxes; } return g92Axes; } @@ -261,10 +259,9 @@ AxesBitmap HangprinterKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap HangprinterKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((axesMoving & xyzAxes) != 0) + if (axesMoving.Intersects(XyzAxes)) { - axesMoving |= xyzAxes; + axesMoving |= XyzAxes; } return axesMoving; } @@ -288,7 +285,7 @@ void HangprinterKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *nor // This is called to determine whether we can babystep the specified axis independently of regular motion. AxesBitmap HangprinterKinematics::GetLinearAxes() const { - return 0; + return AxesBitmap(); } #if HAS_MASS_STORAGE diff --git a/src/Movement/Kinematics/Kinematics.cpp b/src/Movement/Kinematics/Kinematics.cpp index 1a6a50bf..668eb4bf 100644 --- a/src/Movement/Kinematics/Kinematics.cpp +++ b/src/Movement/Kinematics/Kinematics.cpp @@ -70,7 +70,7 @@ bool Kinematics::LimitPositionFromAxis(float coords[], size_t firstAxis, size_t bool limited = false; for (size_t axis = firstAxis; axis < numVisibleAxes; axis++) { - if (IsBitSet(axesHomed, axis)) + if (axesHomed.IsBitSet(axis)) { float& f = coords[axis]; // When homing a printer we convert the M208 axis limit to motor positions, then back again to get the user position. @@ -107,26 +107,26 @@ void Kinematics::GetAssumedInitialPosition(size_t numAxes, float positions[]) co // This default is suitable for most kinematics. AxesBitmap Kinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { - const AxesBitmap allAxes = LowestNBits(numVisibleAxes); + const AxesBitmap allAxes = AxesBitmap::MakeLowestNBits(numVisibleAxes); if ((toBeHomed & allAxes) == allAxes) { filename.copy(HomeAllFileName); - return 0; + return AxesBitmap(); } // If Z homing is done using a Z probe then X and Y must be homed before Z - const bool homeZLast = (IsBitSet(toBeHomed, Z_AXIS) && reprap.GetPlatform().GetEndstops().HomingZWithProbe()); + const bool homeZLast = (toBeHomed.IsBitSet(Z_AXIS) && reprap.GetPlatform().GetEndstops().HomingZWithProbe()); const AxesBitmap homeFirst = AxesToHomeBeforeProbing(); // Return the homing file for the lowest axis that we have been asked to home for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - if (IsBitSet(toBeHomed, axis) && (axis != Z_AXIS || !homeZLast || (alreadyHomed & homeFirst) == homeFirst)) + if (toBeHomed.IsBitSet(axis) && (axis != Z_AXIS || !homeZLast || (alreadyHomed & homeFirst) == homeFirst)) { filename.copy("home"); filename.cat(tolower(reprap.GetGCodes().GetAxisLetters()[axis])); filename.cat(".g"); - return 0; + return AxesBitmap(); } } @@ -138,7 +138,7 @@ AxesBitmap Kinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alread // Usually it is just the corresponding motor (hence this default implementation), but CoreXY and similar kinematics move multiple motors to home an individual axis. AxesBitmap Kinematics::GetConnectedAxes(size_t axis) const { - return MakeBitmap(axis); + return AxesBitmap::MakeFromBits(axis); } /*static*/ Kinematics *Kinematics::Create(KinematicsType k) diff --git a/src/Movement/Kinematics/Kinematics.h b/src/Movement/Kinematics/Kinematics.h index a8893c0b..57a9e031 100644 --- a/src/Movement/Kinematics/Kinematics.h +++ b/src/Movement/Kinematics/Kinematics.h @@ -131,7 +131,7 @@ public: // Return the set of axes that must have been homed before bed probing is allowed // The default implementation requires just X and Y, but some kinematics require additional axes to be homed (e.g. delta, CoreXZ) - virtual AxesBitmap AxesToHomeBeforeProbing() const { return MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); } + virtual AxesBitmap AxesToHomeBeforeProbing() const { return XyAxes; } // Return the initial Cartesian coordinates we assume after switching to this kinematics virtual void GetAssumedInitialPosition(size_t numAxes, float positions[]) const; @@ -168,7 +168,7 @@ public: // Return the set of axes that must be homed prior to regular movement of the specified axes // This default is good for Cartesian and Core printers, but not deltas or SCARA - virtual AxesBitmap MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { return (disallowMovesBeforeHoming) ? axesMoving : 0; } + virtual AxesBitmap MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { return (disallowMovesBeforeHoming) ? axesMoving : AxesBitmap(); } #if HAS_MASS_STORAGE // Write any calibration data that we need to resume a print after power fail, returning true if successful. Override where necessary. diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.cpp b/src/Movement/Kinematics/LinearDeltaKinematics.cpp index 1abdcd76..7e158927 100644 --- a/src/Movement/Kinematics/LinearDeltaKinematics.cpp +++ b/src/Movement/Kinematics/LinearDeltaKinematics.cpp @@ -206,12 +206,11 @@ bool LinearDeltaKinematics::IsReachable(float x, float y, bool isCoordinated) co // Limit the Cartesian position that the user wants to move to returning true if we adjusted the position LimitPositionResult LinearDeltaKinematics::LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated, bool applyM208Limits) const { - constexpr AxesBitmap allAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); bool limited = false; // If axes have been homed on a delta printer and this isn't a homing move, check for movements outside limits. // Skip this check if axes have not been homed, so that extruder-only moves are allowed before homing - if ((axesHomed & allAxes) == allAxes) + if ((axesHomed & XyzAxes) == XyzAxes) { // Constrain the move to be within the build radius const float diagonalSquared = fsquare(finalCoords[X_AXIS]) + fsquare(finalCoords[Y_AXIS]); @@ -933,10 +932,9 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const AxesBitmap LinearDeltaKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If all of X, Y and Z have been specified then we know the positions of all 3 tower motors, otherwise we don't - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((g92Axes & xyzAxes) != xyzAxes) + if ((g92Axes & XyzAxes) != XyzAxes) { - g92Axes &= ~xyzAxes; + g92Axes &= ~XyzAxes; } return g92Axes; } @@ -944,10 +942,9 @@ AxesBitmap LinearDeltaKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap LinearDeltaKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((axesMoving & xyzAxes) != 0) + if (axesMoving.Intersects(XyzAxes)) { - axesMoving |= xyzAxes; + axesMoving |= XyzAxes; } return axesMoving; } @@ -958,10 +955,10 @@ AxesBitmap LinearDeltaKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool di AxesBitmap LinearDeltaKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { // If homing X, Y or Z we must home all the towers - if ((toBeHomed & LowestNBits(XYZ_AXES)) != 0) + if (toBeHomed.Intersects(XyzAxes)) { filename.copy("homedelta.g"); - return 0; + return AxesBitmap(); } return Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); @@ -1013,7 +1010,7 @@ void LinearDeltaKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *nor // The DDA class has special support for delta printers, so we can baystep the Z axis. AxesBitmap LinearDeltaKinematics::GetLinearAxes() const { - return MakeBitmap(Z_AXIS); + return AxesBitmap::MakeFromBits(Z_AXIS); } // End diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.h b/src/Movement/Kinematics/LinearDeltaKinematics.h index 1e203d6c..8a572e23 100644 --- a/src/Movement/Kinematics/LinearDeltaKinematics.h +++ b/src/Movement/Kinematics/LinearDeltaKinematics.h @@ -35,7 +35,7 @@ public: bool IsReachable(float x, float y, bool isCoordinated) const override; LimitPositionResult LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated, bool applyM208Limits) const override; void GetAssumedInitialPosition(size_t numAxes, float positions[]) const override; - AxesBitmap AxesToHomeBeforeProbing() const override { return MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); } + AxesBitmap AxesToHomeBeforeProbing() const override { return XyzAxes; } MotionType GetMotionType(size_t axis) const override; size_t NumHomingButtons(size_t numVisibleAxes) const override { return 0; } HomingMode GetHomingMode() const override { return HomingMode::homeIndividualMotors; } diff --git a/src/Movement/Kinematics/PolarKinematics.cpp b/src/Movement/Kinematics/PolarKinematics.cpp index 9f6446cb..44eb064d 100644 --- a/src/Movement/Kinematics/PolarKinematics.cpp +++ b/src/Movement/Kinematics/PolarKinematics.cpp @@ -184,10 +184,9 @@ void PolarKinematics::GetAssumedInitialPosition(size_t numAxes, float positions[ AxesBitmap PolarKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If both X and Y have been specified then we know the positions the radius motor and the turntable, otherwise we don't - const AxesBitmap xyAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); - if ((g92Axes & xyAxes) != xyAxes) + if ((g92Axes & XyAxes) != XyAxes) { - g92Axes &= ~xyAxes; + g92Axes &= ~XyAxes; } return g92Axes; } @@ -195,10 +194,9 @@ AxesBitmap PolarKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap PolarKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((axesMoving & xyzAxes) != 0) + if (axesMoving.Intersects(XyzAxes)) { - axesMoving |= xyzAxes; + axesMoving |= XyzAxes; } return axesMoving; } @@ -210,8 +208,8 @@ AxesBitmap PolarKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallow AxesBitmap PolarKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { // Ask the base class which homing file we should call first - AxesBitmap ret = Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); - if (ret == 0) + const AxesBitmap ret = Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); + if (ret.IsNonEmpty()) { // Change the returned name if it is X or Y if (StringEqualsIgnoreCase(filename.c_str(), "homex.g")) @@ -293,7 +291,7 @@ bool PolarKinematics::IsContinuousRotationAxis(size_t axis) const // This is called to determine whether we can babystep the specified axis independently of regular motion. AxesBitmap PolarKinematics::GetLinearAxes() const { - return MakeBitmap(Z_AXIS); + return AxesBitmap::MakeFromBits(Z_AXIS); } // Update the derived parameters after the master parameters have been changed diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.cpp b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp index 60da78e5..72172997 100644 --- a/src/Movement/Kinematics/RotaryDeltaKinematics.cpp +++ b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp @@ -242,9 +242,8 @@ bool RotaryDeltaKinematics::IsReachable(float x, float y, bool isCoordinated) co // Limit the Cartesian position that the user wants to move to returning true if we adjusted the position LimitPositionResult RotaryDeltaKinematics::LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated, bool applyM208Limits) const { - constexpr AxesBitmap allAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); bool limited = false; - if ((axesHomed & allAxes) == allAxes) + if ((axesHomed & XyzAxes) == XyzAxes) { // If axes have been homed on a rotary delta printer and this isn't a homing move, check for movements outside limits. // Skip this check if axes have not been homed, so that extruder-only moves are allowed before homing @@ -293,10 +292,9 @@ void RotaryDeltaKinematics::GetAssumedInitialPosition(size_t numAxes, float posi AxesBitmap RotaryDeltaKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If all of X, Y and Z have been specified then we know the positions of all 3 tower motors, otherwise we don't - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((g92Axes & xyzAxes) != xyzAxes) + if ((g92Axes & XyzAxes) != XyzAxes) { - g92Axes &= ~xyzAxes; + g92Axes &= ~XyzAxes; } return g92Axes; } @@ -304,10 +302,9 @@ AxesBitmap RotaryDeltaKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap RotaryDeltaKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyzAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); - if ((axesMoving & xyzAxes) != 0) + if (axesMoving.Intersects(XyzAxes)) { - axesMoving |= xyzAxes; + axesMoving |= XyzAxes; } return axesMoving; } @@ -318,10 +315,10 @@ AxesBitmap RotaryDeltaKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool di AxesBitmap RotaryDeltaKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { // If homing X, Y or Z we must home all the towers - if ((toBeHomed & LowestNBits(DELTA_AXES)) != 0) + if (toBeHomed.Intersects(AxesBitmap::MakeLowestNBits(DELTA_AXES))) { filename.copy("homedelta.g"); - return 0; + return AxesBitmap(); } return Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); @@ -384,7 +381,7 @@ void RotaryDeltaKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *nor // This is called to determine whether we can babystep the specified axis independently of regular motion. AxesBitmap RotaryDeltaKinematics::GetLinearAxes() const { - return 0; + return AxesBitmap(); } // Calculate the motor position for a single tower from a Cartesian coordinate. diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.h b/src/Movement/Kinematics/RotaryDeltaKinematics.h index 6fa2b595..380884df 100644 --- a/src/Movement/Kinematics/RotaryDeltaKinematics.h +++ b/src/Movement/Kinematics/RotaryDeltaKinematics.h @@ -30,7 +30,7 @@ public: bool IsReachable(float x, float y, bool isCoordinated) const override; LimitPositionResult LimitPosition(float finalCoords[], const float * null initialCoords, size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated, bool applyM208Limits) const override; void GetAssumedInitialPosition(size_t numAxes, float positions[]) const override; - AxesBitmap AxesToHomeBeforeProbing() const override { return MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS) | MakeBitmap(Z_AXIS); } + AxesBitmap AxesToHomeBeforeProbing() const override { return XyzAxes; } size_t NumHomingButtons(size_t numVisibleAxes) const override { return 0; } HomingMode GetHomingMode() const override { return HomingMode::homeIndividualMotors; } AxesBitmap AxesAssumedHomed(AxesBitmap g92Axes) const override; diff --git a/src/Movement/Kinematics/ScaraKinematics.cpp b/src/Movement/Kinematics/ScaraKinematics.cpp index b590bb58..cdd24c78 100644 --- a/src/Movement/Kinematics/ScaraKinematics.cpp +++ b/src/Movement/Kinematics/ScaraKinematics.cpp @@ -324,10 +324,9 @@ void ScaraKinematics::GetAssumedInitialPosition(size_t numAxes, float positions[ AxesBitmap ScaraKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const { // If both X and Y have been specified then we know the positions of both arm motors, otherwise we don't - const AxesBitmap xyAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); - if ((g92Axes & xyAxes) != xyAxes) + if ((g92Axes & XyAxes) != XyAxes) { - g92Axes &= ~xyAxes; + g92Axes &= ~XyAxes; } return g92Axes; } @@ -335,10 +334,9 @@ AxesBitmap ScaraKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const // Return the set of axes that must be homed prior to regular movement of the specified axes AxesBitmap ScaraKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const { - constexpr AxesBitmap xyAxes = MakeBitmap(X_AXIS) | MakeBitmap(Y_AXIS); - if ((axesMoving & xyAxes) != 0) + if (axesMoving.Intersects(XyAxes)) { - axesMoving |= xyAxes; + axesMoving |= XyAxes; } return axesMoving; } @@ -369,9 +367,9 @@ size_t ScaraKinematics::NumHomingButtons(size_t numVisibleAxes) const AxesBitmap ScaraKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, const StringRef& filename) const { // Ask the base class which homing file we should call first - AxesBitmap ret = Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); + const AxesBitmap ret = Kinematics::GetHomingFileName(toBeHomed, alreadyHomed, numVisibleAxes, filename); - if (ret == 0) + if (ret.IsEmpty()) { // Change the returned name if it is X or Y if (StringEqualsIgnoreCase(filename.c_str(), "homex.g")) @@ -468,7 +466,7 @@ bool ScaraKinematics::IsContinuousRotationAxis(size_t axis) const // This is called to determine whether we can babystep the specified axis independently of regular motion. AxesBitmap ScaraKinematics::GetLinearAxes() const { - return (crosstalk[1] == 0.0 && crosstalk[2] == 0.0) ? MakeBitmap(Z_AXIS) : 0; + return (crosstalk[1] == 0.0 && crosstalk[2] == 0.0) ? AxesBitmap::MakeFromBits(Z_AXIS) : AxesBitmap(); } // Recalculate the derived parameters diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index 56ccd6aa..49b1f954 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -80,24 +80,24 @@ constexpr ObjectModelTableEntry Move::objectModelTable[] = { "idle", OBJECT_MODEL_FUNC(self, 2), ObjectModelEntryFlags::none }, { "initialDeviation", OBJECT_MODEL_FUNC(self, 5), ObjectModelEntryFlags::none }, { "meshDeviation", OBJECT_MODEL_FUNC(self, 6), ObjectModelEntryFlags::none }, - { "printingAcceleration", OBJECT_MODEL_FUNC(self->maxPrintingAcceleration), ObjectModelEntryFlags::none }, - { "speedFactor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetSpeedFactor()), ObjectModelEntryFlags::live }, - { "travelAcceleration", OBJECT_MODEL_FUNC(self->maxTravelAcceleration), ObjectModelEntryFlags::none }, + { "printingAcceleration", OBJECT_MODEL_FUNC(self->maxPrintingAcceleration, 1), ObjectModelEntryFlags::none }, + { "speedFactor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetSpeedFactor(), 1), ObjectModelEntryFlags::live }, + { "travelAcceleration", OBJECT_MODEL_FUNC(self->maxTravelAcceleration, 1), ObjectModelEntryFlags::none }, // 1. Move.Daa members { "enabled", OBJECT_MODEL_FUNC(self->drcEnabled), ObjectModelEntryFlags::none }, - { "minimumAcceleration", OBJECT_MODEL_FUNC(self->drcMinimumAcceleration), ObjectModelEntryFlags::none }, - { "period", OBJECT_MODEL_FUNC(self->drcPeriod), ObjectModelEntryFlags::none }, + { "minimumAcceleration", OBJECT_MODEL_FUNC(self->drcMinimumAcceleration, 1), ObjectModelEntryFlags::none }, + { "period", OBJECT_MODEL_FUNC(self->drcPeriod, 1), ObjectModelEntryFlags::none }, // 2. Move.Idle members - { "factor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetPlatform().GetIdleCurrentFactor()), ObjectModelEntryFlags::none }, - { "timeout", OBJECT_MODEL_FUNC(0.001f * (float)self->idleTimeout), ObjectModelEntryFlags::none }, + { "factor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetPlatform().GetIdleCurrentFactor(), 1), ObjectModelEntryFlags::none }, + { "timeout", OBJECT_MODEL_FUNC(0.001f * (float)self->idleTimeout, 1), ObjectModelEntryFlags::none }, // 3. move.currentMove members - { "acceleration", OBJECT_MODEL_FUNC(self->GetAcceleration()), ObjectModelEntryFlags::live }, - { "deceleration", OBJECT_MODEL_FUNC(self->GetDeceleration()), ObjectModelEntryFlags::live }, - { "requestedSpeed", OBJECT_MODEL_FUNC(self->GetRequestedSpeed()), ObjectModelEntryFlags::live }, - { "topSpeed", OBJECT_MODEL_FUNC(self->GetTopSpeed()), ObjectModelEntryFlags::live }, + { "acceleration", OBJECT_MODEL_FUNC(self->GetAcceleration(), 1), ObjectModelEntryFlags::live }, + { "deceleration", OBJECT_MODEL_FUNC(self->GetDeceleration(), 1), ObjectModelEntryFlags::live }, + { "requestedSpeed", OBJECT_MODEL_FUNC(self->GetRequestedSpeed(), 1), ObjectModelEntryFlags::live }, + { "topSpeed", OBJECT_MODEL_FUNC(self->GetTopSpeed(), 1), ObjectModelEntryFlags::live }, // 4. move.calibrationDeviation members { "deviation", OBJECT_MODEL_FUNC(self->latestCalibrationDeviation.GetDeviationFromMean(), 3), ObjectModelEntryFlags::none }, @@ -538,18 +538,18 @@ void Move::AxisTransform(float xyzPoint[MaxAxes], const Tool *tool) const noexce // Identify the lowest Y axis const size_t numVisibleAxes = reprap.GetGCodes().GetVisibleAxes(); const AxesBitmap yAxes = Tool::GetYAxes(tool); - const size_t lowestYAxis = LowestSetBit(yAxes); + const size_t lowestYAxis = yAxes.LowestSetBit(); if (lowestYAxis < numVisibleAxes) { // Found a Y axis. Use this one when correcting the X coordinate. const AxesBitmap xAxes = Tool::GetXAxes(tool); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - if (IsBitSet(xAxes, axis)) + if (xAxes.IsBitSet(axis)) { xyzPoint[axis] += tanXY*xyzPoint[lowestYAxis] + tanXZ*xyzPoint[Z_AXIS]; } - if (IsBitSet(yAxes, axis)) + if (yAxes.IsBitSet(axis)) { xyzPoint[axis] += tanYZ*xyzPoint[Z_AXIS]; } @@ -569,18 +569,18 @@ void Move::InverseAxisTransform(float xyzPoint[MaxAxes], const Tool *tool) const // Identify the lowest Y axis const size_t numVisibleAxes = reprap.GetGCodes().GetVisibleAxes(); const AxesBitmap yAxes = Tool::GetYAxes(tool); - const size_t lowestYAxis = LowestSetBit(yAxes); + const size_t lowestYAxis = yAxes.LowestSetBit(); if (lowestYAxis < numVisibleAxes) { // Found a Y axis. Use this one when correcting the X coordinate. const AxesBitmap xAxes = Tool::GetXAxes(tool); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - if (IsBitSet(yAxes, axis)) + if (yAxes.IsBitSet(axis)) { xyzPoint[axis] -= tanYZ*xyzPoint[Z_AXIS]; } - if (IsBitSet(xAxes, axis)) + if (xAxes.IsBitSet(axis)) { xyzPoint[axis] -= (tanXY*xyzPoint[lowestYAxis] + tanXZ*xyzPoint[Z_AXIS]); } @@ -602,12 +602,12 @@ void Move::BedTransform(float xyzPoint[MaxAxes], const Tool *tool) const noexcep // Transform the Z coordinate based on the average correction for each axis used as an X or Y axis. for (uint32_t xAxis = 0; xAxis < numAxes; ++xAxis) { - if (IsBitSet(xAxes, xAxis)) + if (xAxes.IsBitSet(xAxis)) { const float xCoord = xyzPoint[xAxis] + Tool::GetOffset(tool, xAxis); for (uint32_t yAxis = 0; yAxis < numAxes; ++yAxis) { - if (IsBitSet(yAxes, yAxis)) + if (yAxes.IsBitSet(yAxis)) { const float yCoord = xyzPoint[yAxis] + Tool::GetOffset(tool, yAxis); zCorrection += GetInterpolatedHeightError(xCoord, yCoord); @@ -639,12 +639,12 @@ void Move::InverseBedTransform(float xyzPoint[MaxAxes], const Tool *tool) const // Transform the Z coordinate based on the average correction for each axis used as an X or Y axis. for (uint32_t xAxis = 0; xAxis < numAxes; ++xAxis) { - if (IsBitSet(xAxes, xAxis)) + if (xAxes.IsBitSet(xAxis)) { const float xCoord = xyzPoint[xAxis] + Tool::GetOffset(tool, xAxis); for (uint32_t yAxis = 0; yAxis < numAxes; ++yAxis) { - if (IsBitSet(yAxes, yAxis)) + if (yAxes.IsBitSet(yAxis)) { const float yCoord = xyzPoint[yAxis] + Tool::GetOffset(tool, yAxis); zCorrection += GetInterpolatedHeightError(xCoord, yCoord); diff --git a/src/Movement/StepperDrivers/TMC2660.cpp b/src/Movement/StepperDrivers/TMC2660.cpp index fc85a64d..abc7a494 100644 --- a/src/Movement/StepperDrivers/TMC2660.cpp +++ b/src/Movement/StepperDrivers/TMC2660.cpp @@ -250,7 +250,7 @@ private: uint32_t pin; // the pin number that drives the chip select pin of this driver uint32_t configuredChopConfReg; // the configured chopper control register, in the Enabled state volatile uint32_t registersToUpdate; // bitmap of register values that need to be sent to the driver chip - uint32_t driverBit; // 1 << the driver number + DriversBitmap driverBit; // bitmap of just this driver number uint32_t axisNumber; // the axis number of this driver as used to index the DriveMovements in the DDA uint32_t microstepShiftFactor; // how much we need to shift 1 left by to get the current microstepping uint32_t maxStallStepInterval; // maximum interval between full steps to take any notice of stall detection @@ -401,7 +401,7 @@ void TmcDriverState::Init(uint32_t driverNumber, uint32_t p_pin) noexcept pre(!driversPowered) { axisNumber = driverNumber; // assume straight through mapping at initialisation - driverBit = 1ul << driverNumber; + driverBit = DriversBitmap::MakeFromBits(driverNumber); pin = p_pin; pinMode(pin, OUTPUT_HIGH); enabled = false; @@ -915,7 +915,7 @@ namespace SmartDrivers #endif driversPowered = false; - EndstopOrZProbe::UpdateStalledDrivers(LowestNBits(MaxSmartDrivers), false); + EndstopOrZProbe::UpdateStalledDrivers(DriversBitmap::MakeLowestNBits(MaxSmartDrivers), false); for (size_t driver = 0; driver < numTmc2660Drivers; ++driver) { driverStates[driver].Init(driver, driverSelectPins[driver]); // axes are mapped straight through to drivers initially @@ -1025,7 +1025,7 @@ namespace SmartDrivers if (!wasPowered) { // Power to the drivers has been provided or restored, so we need to enable and re-initialise them - EndstopOrZProbe::UpdateStalledDrivers(LowestNBits(MaxSmartDrivers), false); + EndstopOrZProbe::UpdateStalledDrivers(DriversBitmap::MakeLowestNBits(MaxSmartDrivers), false); digitalWrite(GlobalTmc2660EnablePin, LOW); delayMicroseconds(10); @@ -1044,7 +1044,7 @@ namespace SmartDrivers else if (wasPowered) { digitalWrite(GlobalTmc2660EnablePin, HIGH); // disable the drivers - EndstopOrZProbe::UpdateStalledDrivers(LowestNBits(MaxSmartDrivers), false); + EndstopOrZProbe::UpdateStalledDrivers(DriversBitmap::MakeLowestNBits(MaxSmartDrivers), false); } } @@ -1053,7 +1053,7 @@ namespace SmartDrivers { digitalWrite(GlobalTmc2660EnablePin, HIGH); // disable the drivers driversPowered = false; - EndstopOrZProbe::UpdateStalledDrivers(LowestNBits(MaxSmartDrivers), false); + EndstopOrZProbe::UpdateStalledDrivers(DriversBitmap::MakeLowestNBits(MaxSmartDrivers), false); } void SetStallThreshold(size_t driver, int sgThreshold) noexcept diff --git a/src/Movement/StepperDrivers/TMC51xx.cpp b/src/Movement/StepperDrivers/TMC51xx.cpp index 798b27ea..f4298926 100644 --- a/src/Movement/StepperDrivers/TMC51xx.cpp +++ b/src/Movement/StepperDrivers/TMC51xx.cpp @@ -357,7 +357,7 @@ private: volatile uint32_t newRegistersToUpdate; // bitmap of register indices whose values need to be sent to the driver chip uint32_t registersToUpdate; // bitmap of register indices whose values need to be sent to the driver chip - uint32_t driverBit; // 1 << the driver number + DriversBitmap driverBit; // bitmap of just this driver number uint32_t axisNumber; // the axis number of this driver as used to index the DriveMovements in the DDA uint32_t microstepShiftFactor; // how much we need to shift 1 left by to get the current microstepping uint32_t motorCurrent; // the configured motor current in mA @@ -404,7 +404,7 @@ void TmcDriverState::Init(uint32_t p_driverNumber) noexcept pre(!driversPowered) { axisNumber = p_driverNumber; // axes are mapped straight through to drivers initially - driverBit = 1ul << p_driverNumber; + driverBit = DriversBitmap::MakeFromBits(p_driverNumber); enabled = false; registersToUpdate = newRegistersToUpdate = 0; motorCurrent = 0; diff --git a/src/Movement/StraightProbeSettings.cpp b/src/Movement/StraightProbeSettings.cpp index a1d90f64..a514cde8 100644 --- a/src/Movement/StraightProbeSettings.cpp +++ b/src/Movement/StraightProbeSettings.cpp @@ -15,7 +15,7 @@ StraightProbeSettings::StraightProbeSettings() noexcept void StraightProbeSettings::Reset() noexcept { - movingAxes = (AxesBitmap) 0; + movingAxes = AxesBitmap(); type = StraightProbeType::unset; for (size_t axis = 0; axis < MaxAxes; ++axis) { diff --git a/src/Movement/StraightProbeSettings.h b/src/Movement/StraightProbeSettings.h index 05667dd6..e7c30762 100644 --- a/src/Movement/StraightProbeSettings.h +++ b/src/Movement/StraightProbeSettings.h @@ -52,7 +52,7 @@ private: inline void StraightProbeSettings::AddMovingAxis(const size_t axis) noexcept { - SetBit(movingAxes, axis); + movingAxes.SetBit(axis); } inline const bool StraightProbeSettings::ProbingAway() const noexcept diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index 74fe3af0..d6d448a1 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -14,6 +14,14 @@ #include #include +// Get the format string to use assuming this is a floating point number +const char *ExpressionValue::GetFloatFormatString() const noexcept +{ + static constexpr const char *FormatStrings[] = { "%.7f", "%.1f", "%.2f", "%.3f", "%.4f", "%.5f", "%.6f", "%.7f" }; + static_assert(ARRAY_SIZE(FormatStrings) == MaxFloatDigitsDisplayedAfterPoint + 1); + return FormatStrings[min(param, MaxFloatDigitsDisplayedAfterPoint)]; +} + void ObjectExplorationContext::AddIndex(int32_t index) { if (numIndicesCounted == MaxIndices) @@ -225,7 +233,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& break; case TYPE_OF(float): - buf->catf((val.param == 3) ? "%.3f" : (val.param == 2) ? "%.2f" : "%.1f", (double)val.fVal); + buf->catf(val.GetFloatFormatString(), (double)val.fVal); break; case TYPE_OF(uint32_t): @@ -240,22 +248,86 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& buf->EncodeString(val.sVal, true); break; - case TYPE_OF(Bitmap32): + case TYPE_OF(Bitmap): + if (context.ShortFormReport()) + { + buf->catf("%" PRIu16, (uint16_t)val.uVal); + } + else + { + Bitmap bm = Bitmap::MakeFromRaw((uint16_t)val.uVal); + buf->cat('['); + bool first = true; + bm.Iterate + ([buf, &first](unsigned int bn) + { + if (first) + { + first = false; + } + else + { + buf->cat(','); + } + buf->catf("%u", bn); + } + ); + buf->cat(']'); + } + break; + + case TYPE_OF(Bitmap): if (context.ShortFormReport()) { buf->catf("%" PRIu32, val.uVal); } else { - uint32_t v = val.uVal; + Bitmap bm = Bitmap::MakeFromRaw(val.uVal); buf->cat('['); - buf->cat((v & 1) ? '1' : '0'); - for (unsigned int i = 1; i < 32; ++i) - { - v >>= 1; - buf->cat(','); - buf->cat((v & 1) ? '1' : '0'); - } + bool first = true; + bm.Iterate + ([buf, &first](unsigned int bn) + { + if (first) + { + first = false; + } + else + { + buf->cat(','); + } + buf->catf("%u", bn); + } + ); + buf->cat(']'); + } + break; + + case TYPE_OF(Bitmap): + if (context.ShortFormReport()) + { + buf->catf("%" PRIu64, val.Get56BitValue()); + } + else + { + Bitmap bm = Bitmap::MakeFromRaw(val.Get56BitValue()); + buf->cat('['); + bool first = true; + bm.Iterate + ([buf, &first](unsigned int bn) + { + if (first) + { + first = false; + } + else + { + buf->cat(','); + } + buf->catf("%u", bn); + } + ); buf->cat(']'); } break; @@ -297,7 +369,7 @@ void ObjectModel::ReportItemAsJson(OutputBuffer *buf, ObjectExplorationContext& case TYPE_OF(DateTime): { - const time_t time = val.Get40BitValue(); + const time_t time = val.Get56BitValue(); tm timeInfo; gmtime_r(&time, &timeInfo); buf->catf("\"%04u-%02u-%02uT%02u:%02u:%02u\"", diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h index f6514d8d..eac396fc 100644 --- a/src/ObjectModel/ObjectModel.h +++ b/src/ObjectModel/ObjectModel.h @@ -14,6 +14,7 @@ #if SUPPORT_OBJECT_MODEL #include +#include #include typedef uint8_t TypeCode; @@ -21,6 +22,7 @@ constexpr TypeCode NoType = 0; // code for an invalid or unknown type // Dummy types, used to define type codes class Bitmap32; +class Bitmap64; class Enum32; class ObjectModel; // forward declaration class ObjectModelArrayDescriptor; // forward declaration @@ -37,19 +39,21 @@ struct DateTime // Each type must return a unique type code in the range 1 to 127 (0 is NoType) template constexpr TypeCode TypeOf() noexcept; -template<> constexpr TypeCode TypeOf() noexcept { return 1; } -template<> constexpr TypeCode TypeOf() noexcept { return 2; } -template<> constexpr TypeCode TypeOf() noexcept { return 3; } -template<> constexpr TypeCode TypeOf() noexcept { return 4; } -template<> constexpr TypeCode TypeOf() noexcept { return 5; } -template<> constexpr TypeCode TypeOf() noexcept { return 6; } -template<> constexpr TypeCode TypeOf() noexcept { return 7; } -template<> constexpr TypeCode TypeOf() noexcept { return 8; } -template<> constexpr TypeCode TypeOf() noexcept { return 9; } -template<> constexpr TypeCode TypeOf() noexcept { return 10; } -template<> constexpr TypeCode TypeOf() noexcept { return 11; } -template<> constexpr TypeCode TypeOf() noexcept { return 12; } -template<> constexpr TypeCode TypeOf() noexcept { return 13; } +template<> constexpr TypeCode TypeOf () noexcept { return 1; } +template<> constexpr TypeCode TypeOf () noexcept { return 2; } +template<> constexpr TypeCode TypeOf () noexcept { return 3; } +template<> constexpr TypeCode TypeOf () noexcept { return 4; } +template<> constexpr TypeCode TypeOf () noexcept { return 5; } +template<> constexpr TypeCode TypeOf> () noexcept { return 6; } +template<> constexpr TypeCode TypeOf> () noexcept { return 7; } +template<> constexpr TypeCode TypeOf> () noexcept { return 8; } +template<> constexpr TypeCode TypeOf () noexcept { return 9; } +template<> constexpr TypeCode TypeOf () noexcept { return 10; } +template<> constexpr TypeCode TypeOf () noexcept { return 11; } +template<> constexpr TypeCode TypeOf () noexcept { return 12; } +template<> constexpr TypeCode TypeOf () noexcept { return 13; } +template<> constexpr TypeCode TypeOf () noexcept { return 14; } +template<> constexpr TypeCode TypeOf () noexcept { return 15; } #define TYPE_OF(_t) (TypeOf<_t>()) @@ -61,9 +65,9 @@ class StringParser; // Struct used to hold the expressions with polymorphic types struct ExpressionValue { - TypeCode type; // what type is stored in the union - uint8_t param; // additional parameter, e.g. number of usual displayed decimal places for a float, - // or table # for an ObjectModel, or 8 extra bits for a date/time + uint32_t type : 8, // what type is stored in the union + param : 24; // additional parameter, e.g. number of usual displayed decimal places for a float, + // or table # for an ObjectModel, or 24 extra bits for a date/time or a long bitmap union { bool bVal; @@ -72,14 +76,14 @@ struct ExpressionValue int32_t iVal; uint32_t uVal; // used for enumerations, bitmaps and IP addresses (not for integers, we always use int32_t for those) const char *sVal; - const ObjectModel *omVal; // object of some class derived form ObkectModel + const ObjectModel *omVal; // object of some class derived form ObjectModel const ObjectModelArrayDescriptor *omadVal; }; ExpressionValue() noexcept : type(NoType) { } explicit constexpr ExpressionValue(bool b) noexcept : type(TYPE_OF(bool)), param(0), bVal(b) { } explicit constexpr ExpressionValue(char c) noexcept : type(TYPE_OF(char)), param(0), cVal(c) { } - explicit constexpr ExpressionValue(float f) noexcept : type(TYPE_OF(float)), param(1), fVal(f) { } + explicit constexpr ExpressionValue(float f) noexcept : type(TYPE_OF(float)), param(MaxFloatDigitsDisplayedAfterPoint), fVal(f) { } constexpr ExpressionValue(float f, uint8_t numDecimalPlaces) noexcept : type(TYPE_OF(float)), param(numDecimalPlaces), fVal(f) { } explicit constexpr ExpressionValue(int32_t i) noexcept : type(TYPE_OF(int32_t)), param(0), iVal(i) { } explicit constexpr ExpressionValue(const ObjectModel *om) noexcept : type(TYPE_OF(const ObjectModel*)), param(0), omVal(om) { } @@ -90,6 +94,9 @@ struct ExpressionValue explicit constexpr ExpressionValue(nullptr_t dummy) noexcept : type(NoType), param(0), uVal(0) { } explicit ExpressionValue(DateTime t) noexcept : type((t.tim == 0) ? NoType : TYPE_OF(DateTime)), param(t.tim >> 32), uVal((uint32_t)t.tim) { } explicit ExpressionValue(DriverId id) noexcept : type(TYPE_OF(DriverId)), param(0), uVal(id.AsU32()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap bm) noexcept : type(TYPE_OF(Bitmap)), param(bm.GetRaw() >> 32), uVal((uint32_t)bm.GetRaw()) { } void Set(bool b) noexcept { type = TYPE_OF(bool); bVal = b; } void Set(char c) noexcept { type = TYPE_OF(char); cVal = c; } @@ -98,8 +105,11 @@ struct ExpressionValue void Set(float f) noexcept { type = TYPE_OF(float); fVal = f; param = 1; } void Set(const char *s) noexcept { type = TYPE_OF(const char*); sVal = s; } - // Extract a 40-bit value that we have stored. Used to retrieve date/times. - uint64_t Get40BitValue() const noexcept { return ((uint64_t)param << 32) | uVal; } + // Extract a 56-bit value that we have stored. Used to retrieve date/times and large bitmaps. + uint64_t Get56BitValue() const noexcept { return ((uint64_t)param << 32) | uVal; } + + // Get the format string to use assuming this is a floating point number + const char *GetFloatFormatString() const noexcept; }; // Flags field of a table entry diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index 36ebb69f..47a72487 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -125,6 +125,18 @@ size_t OutputBuffer::catf(const char *fmt, ...) noexcept return cat(formatBuffer); } +size_t OutputBuffer::lcatf(const char *fmt, ...) noexcept +{ + char formatBuffer[FormatStringLength]; + va_list vargs; + va_start(vargs, fmt); + SafeVsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); + va_end(vargs); + + formatBuffer[ARRAY_UPB(formatBuffer)] = 0; + return lcat(formatBuffer); +} + size_t OutputBuffer::copy(const char c) noexcept { // Unlink existing entries before starting the copy process @@ -194,6 +206,11 @@ size_t OutputBuffer::cat(const char *src) noexcept return cat(src, strlen(src)); } +size_t OutputBuffer::lcat(const char *src) noexcept +{ + return lcat(src, strlen(src)); +} + size_t OutputBuffer::cat(const char *src, size_t len) noexcept { size_t copied = 0; @@ -225,6 +242,15 @@ size_t OutputBuffer::cat(const char *src, size_t len) noexcept return copied; } +size_t OutputBuffer::lcat(const char *src, size_t len) noexcept +{ + if (Length() != 0) + { + cat('\n'); + } + return cat(src, len); +} + size_t OutputBuffer::cat(StringRef &str) noexcept { return cat(str.c_str(), str.strlen()); diff --git a/src/OutputMemory.h b/src/OutputMemory.h index 9006f371..27d12e46 100644 --- a/src/OutputMemory.h +++ b/src/OutputMemory.h @@ -48,6 +48,7 @@ class OutputBuffer size_t printf(const char *fmt, ...) noexcept __attribute__ ((format (printf, 2, 3))); size_t vprintf(const char *fmt, va_list vargs) noexcept; size_t catf(const char *fmt, ...) noexcept __attribute__ ((format (printf, 2, 3))); + size_t lcatf(const char *fmt, ...) noexcept __attribute__ ((format (printf, 2, 3))); size_t copy(const char c) noexcept; size_t copy(const char *src) noexcept; @@ -55,7 +56,9 @@ class OutputBuffer size_t cat(const char c) noexcept; size_t cat(const char *src) noexcept; + size_t lcat(const char *src) noexcept; size_t cat(const char *src, size_t len) noexcept; + size_t lcat(const char *src, size_t len) noexcept; size_t cat(StringRef &str) noexcept; size_t EncodeString(const char *src, bool allowControlChars, bool prependAsterisk = false) noexcept; diff --git a/src/Platform.cpp b/src/Platform.cpp index bf71ce3b..5103dce2 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -169,14 +169,14 @@ extern "C" void UrgentInit() DriversBitmap AxisDriversConfig::GetDriversBitmap() const noexcept { - DriversBitmap rslt = 0; + DriversBitmap rslt; for (size_t i = 0; i < numDrivers; ++i) { #if SUPPORT_CAN_EXPANSION if (driverNumbers[i].IsLocal()) #endif { - SetBit(rslt, driverNumbers[i].localDriver); + rslt.SetBit(driverNumbers[i].localDriver); } } return rslt; @@ -227,43 +227,43 @@ constexpr ObjectModelTableEntry Platform::objectModelTable[] = { "vIn", OBJECT_MODEL_FUNC(self, 2), ObjectModelEntryFlags::live }, // 1. mcuTemp members - { "current", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().current), ObjectModelEntryFlags::live }, - { "max", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().max), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().min), ObjectModelEntryFlags::none }, + { "current", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().current, 1), ObjectModelEntryFlags::live }, + { "max", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().max, 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->GetMcuTemperatures().min, 1), ObjectModelEntryFlags::none }, // 2. vIn members - { "current", OBJECT_MODEL_FUNC(self->GetCurrentPowerVoltage()), ObjectModelEntryFlags::live }, - { "max", OBJECT_MODEL_FUNC(self->GetPowerVoltages().max), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->GetPowerVoltages().min), ObjectModelEntryFlags::none }, + { "current", OBJECT_MODEL_FUNC(self->GetCurrentPowerVoltage(), 1), ObjectModelEntryFlags::live }, + { "max", OBJECT_MODEL_FUNC(self->GetPowerVoltages().max, 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->GetPowerVoltages().min, 1), ObjectModelEntryFlags::none }, // 3. move.axes[] members - { "acceleration", OBJECT_MODEL_FUNC(self->Acceleration(context.GetLastIndex())), ObjectModelEntryFlags::none }, + { "acceleration", OBJECT_MODEL_FUNC(self->Acceleration(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, { "drivers", OBJECT_MODEL_FUNC_NOSELF(&axisDriversArrayDescriptor), ObjectModelEntryFlags::none }, { "homed", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().IsAxisHomed(context.GetLastIndex())), ObjectModelEntryFlags::live }, - { "jerk", OBJECT_MODEL_FUNC(self->GetInstantDv(context.GetLastIndex())), ObjectModelEntryFlags::none }, + { "jerk", OBJECT_MODEL_FUNC(MinutesToSeconds * self->GetInstantDv(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, { "letter", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetAxisLetters()[context.GetLastIndex()]), ObjectModelEntryFlags::none }, - { "max", OBJECT_MODEL_FUNC(self->AxisMaximum(context.GetLastIndex())), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->AxisMinimum(context.GetLastIndex())), ObjectModelEntryFlags::none }, - { "speed", OBJECT_MODEL_FUNC(self->MaxFeedrate(context.GetLastIndex())), ObjectModelEntryFlags::none }, + { "max", OBJECT_MODEL_FUNC(self->AxisMaximum(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->AxisMinimum(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, + { "speed", OBJECT_MODEL_FUNC(MinutesToSeconds * self->MaxFeedrate(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, { "userPosition", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetUserCoordinate(context.GetLastIndex()), 3), ObjectModelEntryFlags::live }, { "visible", OBJECT_MODEL_FUNC_NOSELF(context.GetLastIndex() < (int32_t)reprap.GetGCodes().GetVisibleAxes()), ObjectModelEntryFlags::none }, // 4. move.extruders[] members { "driver", OBJECT_MODEL_FUNC(self->extruderDrivers[context.GetLastIndex()]), ObjectModelEntryFlags::none }, - { "factor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetExtrusionFactor(context.GetLastIndex())), ObjectModelEntryFlags::none }, + { "factor", OBJECT_MODEL_FUNC_NOSELF(reprap.GetGCodes().GetExtrusionFactor(context.GetLastIndex()), 1), ObjectModelEntryFlags::none }, { "nonlinear", OBJECT_MODEL_FUNC(self, 5), ObjectModelEntryFlags::none }, - { "pressureAdvance", OBJECT_MODEL_FUNC(self->GetPressureAdvance(context.GetLastIndex())), ObjectModelEntryFlags::none }, + { "pressureAdvance", OBJECT_MODEL_FUNC(self->GetPressureAdvance(context.GetLastIndex()), 2), ObjectModelEntryFlags::none }, // 5. move.extruders[].nonlinear members - { "a", OBJECT_MODEL_FUNC(self->nonlinearExtrusionA[context.GetLastIndex()]), ObjectModelEntryFlags::none }, - { "b", OBJECT_MODEL_FUNC(self->nonlinearExtrusionB[context.GetLastIndex()]), ObjectModelEntryFlags::none }, - { "upperLimit", OBJECT_MODEL_FUNC(self->nonlinearExtrusionLimit[context.GetLastIndex()]), ObjectModelEntryFlags::none }, + { "a", OBJECT_MODEL_FUNC(self->nonlinearExtrusionA[context.GetLastIndex()], 3), ObjectModelEntryFlags::none }, + { "b", OBJECT_MODEL_FUNC(self->nonlinearExtrusionB[context.GetLastIndex()], 3), ObjectModelEntryFlags::none }, + { "upperLimit", OBJECT_MODEL_FUNC(self->nonlinearExtrusionLimit[context.GetLastIndex()], 2), ObjectModelEntryFlags::none }, #if HAS_12V_MONITOR // 6. v12 members - { "current", OBJECT_MODEL_FUNC(self->GetV12Voltages().current), ObjectModelEntryFlags::live }, - { "max", OBJECT_MODEL_FUNC(self->GetV12Voltages().max), ObjectModelEntryFlags::none }, - { "min", OBJECT_MODEL_FUNC(self->GetV12Voltages().min), ObjectModelEntryFlags::none }, + { "current", OBJECT_MODEL_FUNC(self->GetV12Voltages().current, 1), ObjectModelEntryFlags::live }, + { "max", OBJECT_MODEL_FUNC(self->GetV12Voltages().max, 1), ObjectModelEntryFlags::none }, + { "min", OBJECT_MODEL_FUNC(self->GetV12Voltages().min, 1), ObjectModelEntryFlags::none }, #endif }; @@ -534,7 +534,8 @@ void Platform::Init() noexcept } minimumMovementSpeed = DefaultMinFeedrate; - axisMaximaProbed = axisMinimaProbed = 0; + axisMaximaProbed.Clear(); + axisMinimaProbed.Clear(); idleCurrentFactor = DefaultIdleCurrentFactor; // Motors @@ -639,13 +640,23 @@ void Platform::Init() noexcept # else SmartDrivers::Init(ENABLE_PINS, numSmartDrivers); # endif - temperatureShutdownDrivers = temperatureWarningDrivers = shortToGroundDrivers = openLoadADrivers = openLoadBDrivers = notOpenLoadADrivers = notOpenLoadBDrivers = 0; + temperatureShutdownDrivers.Clear(); + temperatureWarningDrivers.Clear(); + shortToGroundDrivers.Clear(); + openLoadADrivers.Clear(); + openLoadBDrivers.Clear(); + notOpenLoadADrivers.Clear(); + notOpenLoadBDrivers.Clear(); #endif #if HAS_STALL_DETECT - stalledDrivers = 0; - logOnStallDrivers = pauseOnStallDrivers = rehomeOnStallDrivers = 0; - stalledDriversToLog = stalledDriversToPause = stalledDriversToRehome = 0; + stalledDrivers.Clear(); + logOnStallDrivers.Clear(); + pauseOnStallDrivers.Clear(); + rehomeOnStallDrivers.Clear(); + stalledDriversToLog.Clear(); + stalledDriversToPause.Clear(); + stalledDriversToRehome.Clear(); #endif #if HAS_VOLTAGE_MONITOR @@ -660,12 +671,12 @@ void Platform::Init() noexcept extrusionAncilliaryPwmValue = 0.0; // Initialise the configured heaters to just the default bed heater (there are no default chamber heaters) - configuredHeaters = 0; + configuredHeaters.Clear(); #ifndef DUET3 if (DefaultBedHeater >= 0) { - SetBit(configuredHeaters, DefaultBedHeater); + configuredHeaters.SetBit(DefaultBedHeater); } #endif @@ -1008,7 +1019,7 @@ void Platform::Spin() noexcept if (enableValues[nextDriveToPoll] >= 0) // don't poll driver if it is flagged "no poll" { const uint32_t stat = SmartDrivers::GetAccumulatedStatus(nextDriveToPoll, 0); - const DriversBitmap mask = MakeBitmap(nextDriveToPoll); + const DriversBitmap mask = DriversBitmap::MakeFromBits(nextDriveToPoll); if (stat & TMC_RR_OT) { temperatureShutdownDrivers |= mask; @@ -1033,14 +1044,15 @@ void Platform::Spin() noexcept if (!openLoadATimer.IsRunning()) { openLoadATimer.Start(); - openLoadADrivers = notOpenLoadADrivers = 0; + openLoadADrivers.Clear(); + notOpenLoadADrivers.Clear(); } openLoadADrivers |= mask; } else if (openLoadATimer.IsRunning()) { notOpenLoadADrivers |= mask; - if ((openLoadADrivers & ~notOpenLoadADrivers) == 0) + if (!openLoadADrivers.Intersects(~notOpenLoadADrivers)) { openLoadATimer.Stop(); } @@ -1051,14 +1063,15 @@ void Platform::Spin() noexcept if (!openLoadBTimer.IsRunning()) { openLoadBTimer.Start(); - openLoadBDrivers = notOpenLoadBDrivers = 0; + openLoadBDrivers.Clear(); + notOpenLoadBDrivers.Clear(); } openLoadBDrivers |= mask; } else if (openLoadBTimer.IsRunning()) { notOpenLoadBDrivers |= mask; - if ((openLoadBDrivers & ~notOpenLoadBDrivers) == 0) + if (!openLoadBDrivers.Intersects(~notOpenLoadBDrivers)) { openLoadBTimer.Stop(); } @@ -1067,18 +1080,18 @@ void Platform::Spin() noexcept # if HAS_STALL_DETECT if ((stat & TMC_RR_SG) != 0) { - if ((stalledDrivers & mask) == 0) + if (!stalledDrivers.Intersects(mask)) { // This stall is new so check whether we need to perform some action in response to the stall - if ((rehomeOnStallDrivers & mask) != 0) + if (rehomeOnStallDrivers.Intersects(mask)) { stalledDriversToRehome |= mask; } - else if ((pauseOnStallDrivers & mask) != 0) + else if (pauseOnStallDrivers.Intersects(mask)) { stalledDriversToPause |= mask; } - else if ((logOnStallDrivers & mask) != 0) + else if (logOnStallDrivers.Intersects(mask)) { stalledDriversToLog |= mask; } @@ -1094,18 +1107,18 @@ void Platform::Spin() noexcept # if HAS_STALL_DETECT // Action any pause or rehome actions due to motor stalls. This may have to be done more than once. - if (stalledDriversToRehome != 0) + if (stalledDriversToRehome.IsNonEmpty()) { if (reprap.GetGCodes().ReHomeOnStall(stalledDriversToRehome)) { - stalledDriversToRehome = 0; + stalledDriversToRehome.Clear(); } } - else if (stalledDriversToPause != 0) + else if (stalledDriversToPause.IsNonEmpty()) { if (reprap.GetGCodes().PauseOnStall(stalledDriversToPause)) { - stalledDriversToPause = 0; + stalledDriversToPause.Clear(); } } # endif @@ -1140,7 +1153,13 @@ void Platform::Spin() noexcept #if HAS_SMART_DRIVERS openLoadATimer.Stop(); openLoadBTimer.Stop(); - temperatureShutdownDrivers = temperatureWarningDrivers = shortToGroundDrivers = openLoadADrivers = openLoadBDrivers = notOpenLoadADrivers = notOpenLoadBDrivers = 0; + temperatureShutdownDrivers.Clear(); + temperatureWarningDrivers.Clear(); + shortToGroundDrivers.Clear(); + openLoadADrivers.Clear(); + openLoadBDrivers.Clear(); + notOpenLoadADrivers.Clear(); + notOpenLoadBDrivers.Clear(); #endif } @@ -1185,15 +1204,15 @@ void Platform::Spin() noexcept } // Don't warn about a hot driver if we recently turned on a fan to cool it - if (temperatureWarningDrivers != 0) + if (temperatureWarningDrivers.IsNonEmpty()) { const DriversBitmap driversMonitored[NumTmcDriversSenseChannels] = # ifdef DUET_NG - { LowestNBits(5), LowestNBits(5) << 5 }; // first channel is Duet, second is DueX5 + { DriversBitmap::MakeLowestNBits(5), DriversBitmap::MakeLowestNBits(5).ShiftUp(5) }; // first channel is Duet, second is DueX5 # elif defined(DUET_M) - { LowestNBits(5), LowestNBits(2) << 5 }; // first channel is Duet, second is daughter board + { DriversBitmap::MakeLowestNBits(5), DriversBitmap::MakeLowestNBits(2).ShiftUp(5) }; // first channel is Duet, second is daughter board # else - { LowestNBits(NumDirectDrivers) }; + { DriversBitmap::MakeLowestNBits(NumDirectDrivers) }; # endif for (unsigned int i = 0; i < NumTmcDriversSenseChannels; ++i) { @@ -1212,11 +1231,11 @@ void Platform::Spin() noexcept #if HAS_STALL_DETECT // Check for stalled drivers that need to be reported and logged - if (stalledDriversToLog != 0 && reprap.GetGCodes().IsReallyPrinting()) + if (stalledDriversToLog.IsNonEmpty() && reprap.GetGCodes().IsReallyPrinting()) { String scratchString; ListDrivers(scratchString.GetRef(), stalledDriversToLog); - stalledDriversToLog = 0; + stalledDriversToLog.Clear(); float liveCoordinates[MaxAxesPlusExtruders]; reprap.GetMove().LiveCoordinates(liveCoordinates, reprap.GetCurrentTool()); MessageF(WarningMessage, "Driver(s)%s stalled at Z height %.2f", scratchString.c_str(), (double)liveCoordinates[Z_AXIS]); @@ -1338,22 +1357,14 @@ void Platform::Spin() noexcept // Sets 'reported' if we reported anything, else leaves 'reported' alone. void Platform::ReportDrivers(MessageType mt, DriversBitmap& whichDrivers, const char* text, bool& reported) noexcept { - if (whichDrivers != 0) + if (whichDrivers.IsNonEmpty()) { String scratchString; scratchString.printf("%s reported by driver(s)", text); - DriversBitmap wd = whichDrivers; - for (unsigned int drive = 0; wd != 0; ++drive) - { - if ((wd & 1) != 0) - { - scratchString.catf(" %u", drive); - } - wd >>= 1; - } + whichDrivers.Iterate([&scratchString](unsigned int drive) { scratchString.catf(" %u", drive); }); MessageF(mt, "%s\n", scratchString.c_str()); reported = true; - whichDrivers = 0; + whichDrivers.Clear(); } } @@ -2166,22 +2177,21 @@ GCodeResult Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, un #if HAS_SMART_DRIVERS // This is called when a fan that monitors driver temperatures is turned on when it was off -void Platform::DriverCoolingFansOnOff(uint32_t driverChannelsMonitored, bool on) noexcept +void Platform::DriverCoolingFansOnOff(DriverChannelsBitmap driverChannelsMonitored, bool on) noexcept { - for (unsigned int i = 0; i < NumTmcDriversSenseChannels; ++i) - { - if ((driverChannelsMonitored & (1 << i)) != 0) - { - if (on) + driverChannelsMonitored.Iterate + ([this, on](unsigned int i) { - driversFanTimers[i].Start(); - } - else - { - driversFanTimers[i].Stop(); + if (on) + { + this->driversFanTimers[i].Start(); + } + else + { + this->driversFanTimers[i].Stop(); + } } - } - } + ); } #endif @@ -2201,7 +2211,7 @@ int Platform::GetAveragingFilterIndex(const IoPort& port) const noexcept void Platform::UpdateConfiguredHeaters() noexcept { - configuredHeaters = 0; + configuredHeaters.Clear(); // Check bed heaters for (size_t i = 0; i < MaxBedHeaters; i++) @@ -2209,7 +2219,7 @@ void Platform::UpdateConfiguredHeaters() noexcept const int8_t bedHeater = reprap.GetHeat().GetBedHeater(i); if (bedHeater >= 0) { - SetBit(configuredHeaters, bedHeater); + configuredHeaters.SetBit(bedHeater); } } @@ -2219,7 +2229,7 @@ void Platform::UpdateConfiguredHeaters() noexcept const int8_t chamberHeater = reprap.GetHeat().GetChamberHeater(i); if (chamberHeater >= 0) { - SetBit(configuredHeaters, chamberHeater); + configuredHeaters.SetBit(chamberHeater); } } @@ -2228,7 +2238,7 @@ void Platform::UpdateConfiguredHeaters() noexcept { if (reprap.IsHeaterAssignedToTool(heater)) { - SetBit(configuredHeaters, heater); + configuredHeaters.SetBit(heater); } } } @@ -2239,7 +2249,7 @@ void Platform::UpdateConfiguredHeaters() noexcept bool Platform::WritePlatformParameters(FileStore *f, bool includingG31) const noexcept { bool ok; - if (axisMinimaProbed != 0 || axisMaximaProbed != 0) + if (axisMinimaProbed.IsNonEmpty() || axisMaximaProbed.IsNonEmpty()) { ok = f->Write("; Probed axis limits\n"); if (ok) @@ -2266,20 +2276,14 @@ bool Platform::WritePlatformParameters(FileStore *f, bool includingG31) const no bool Platform::WriteAxisLimits(FileStore *f, AxesBitmap axesProbed, const float limits[MaxAxes], int sParam) noexcept { - if (axesProbed == 0) + if (axesProbed.IsEmpty()) { return true; } String scratchString; scratchString.printf("M208 S%d", sParam); - for (size_t axis = 0; axis < reprap.GetGCodes().GetTotalAxes(); ++axis) - { - if (IsBitSet(axesProbed, axis)) - { - scratchString.catf(" %c%.2f", reprap.GetGCodes().GetAxisLetters()[axis], (double)limits[axis]); - } - } + axesProbed.Iterate([&scratchString, limits](unsigned int axis) { scratchString.catf(" %c%.2f", reprap.GetGCodes().GetAxisLetters()[axis], (double)limits[axis]); }); scratchString.cat('\n'); return f->Write(scratchString.c_str()); } @@ -2809,7 +2813,7 @@ void Platform::SetEnableValue(size_t driver, int8_t eVal) noexcept if (eVal == -1) { // User has asked to disable status monitoring for this driver, so clear its error bits - DriversBitmap mask = ~MakeBitmap(driver); + const DriversBitmap mask = ~DriversBitmap::MakeFromBits(driver); temperatureShutdownDrivers &= mask; temperatureWarningDrivers &= mask; shortToGroundDrivers &= mask; @@ -3797,7 +3801,7 @@ void Platform::SetAxisMaximum(size_t axis, float value, bool byProbing) noexcept axisMaxima[axis] = value; if (byProbing) { - SetBit(axisMaximaProbed, axis); + axisMaximaProbed.SetBit(axis); } } @@ -3806,7 +3810,7 @@ void Platform::SetAxisMinimum(size_t axis, float value, bool byProbing) noexcept axisMinima[axis] = value; if (byProbing) { - SetBit(axisMinimaProbed, axis); + axisMinimaProbed.SetBit(axis); } } @@ -3918,24 +3922,24 @@ MinMaxCurrent Platform::GetV12Voltages() const noexcept float Platform::GetTmcDriversTemperature(unsigned int board) const noexcept { #if defined(DUET3) - const uint16_t mask = LowestNBits(6); // there are 6 drivers, only one board + const DriversBitmap mask = DriversBitmap::MakeLowestNBits(6); // there are 6 drivers, only one board #elif defined(DUET_NG) - const uint16_t mask = LowestNBits(5) << (5 * board); // there are 5 drivers on each board + const DriversBitmap mask = DriversBitmap::MakeLowestNBits(5).ShiftUp(5 * board); // there are 5 drivers on each board #elif defined(DUET_M) - const uint16_t mask = (board == 0) - ? LowestNBits(5) // drivers 0-4 are on the main board - : LowestNBits(2) << 5; // drivers 5-6 are on the daughter board + const DriversBitmap mask = (board == 0) + ? DriversBitmap::MakeLowestNBits(5) // drivers 0-4 are on the main board + : DriversBitmap::MakeLowestNBits(2).ShiftUp(5); // drivers 5-6 are on the daughter board #elif defined(PCCB_10) - const uint16_t mask = (board == 0) - ? LowestNBits(2) // drivers 0,1 are on-board - : LowestNBits(5) << 2; // drivers 2-7 are on the DueX5 + const DriversBitmap mask = (board == 0) + ? DriversBitmap::MakeLowestNBits(2) // drivers 0,1 are on-board + : DriversBitmap::MakeLowestNBits(5).ShiftUp(2); // drivers 2-7 are on the DueX5 #elif defined(PCCB_08_X5) - const uint16_t mask = LowestNBits(5); // all drivers (0-4) are on the DueX, no further expansion supported + const DriversBitmap mask = DriversBitmap::MakeLowestNBits(5); // all drivers (0-4) are on the DueX, no further expansion supported #elif defined(PCCB_08) - const uint16_t mask = LowestNBits(2); // drivers 0, 1 are on-board, no expansion supported + const DriversBitmap mask = DriversBitmap::MakeLowestNBits(2); // drivers 0, 1 are on-board, no expansion supported #endif - return ((temperatureShutdownDrivers & mask) != 0) ? 150.0 - : ((temperatureWarningDrivers & mask) != 0) ? 100.0 + return (temperatureShutdownDrivers.Intersects(mask)) ? 150.0 + : (temperatureWarningDrivers.Intersects(mask)) ? 100.0 : 0.0; } @@ -3948,7 +3952,7 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& { // Build a bitmap of all the drivers referenced // First looks for explicit driver numbers - DriversBitmap drivers = 0; + DriversBitmap drivers; #if SUPPORT_CAN_EXPANSION CanDriversList canDrivers; #endif @@ -3966,7 +3970,7 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& reply.printf("Invalid local drive number '%u'", drives[i].localDriver); return GCodeResult::error; } - SetBit(drivers, drives[i].localDriver); + drivers.SetBit(drives[i].localDriver); } #if SUPPORT_CAN_EXPANSION else @@ -3983,7 +3987,7 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& if (gb.Seen(reprap.GetGCodes().GetAxisLetters()[axis])) { IterateDrivers(axis, - [&drivers](uint8_t driver){ SetBit(drivers, driver); } + [&drivers](uint8_t driver){ drivers.SetBit(driver); } #if SUPPORT_CAN_EXPANSION , [&canDrivers](DriverId driver){ canDrivers.AddEntry(driver); } #endif @@ -4004,7 +4008,7 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& const DriverId driver = GetExtruderDriver(extruderNumbers[i]); if (driver.IsLocal()) { - SetBit(drivers, driver.localDriver); + drivers.SetBit(driver.localDriver); } #if SUPPORT_CAN_EXPANSION else @@ -4022,49 +4026,25 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& { seen = true; const int sgThreshold = gb.GetIValue(); - for (size_t drive = 0; drive < numSmartDrivers; ++drive) - { - if (IsBitSet(drivers, drive)) - { - SmartDrivers::SetStallThreshold(drive, sgThreshold); - } - } + drivers.Iterate([sgThreshold](unsigned int drive) { SmartDrivers::SetStallThreshold(drive, sgThreshold); }); } if (gb.Seen('F')) { seen = true; const bool sgFilter = (gb.GetIValue() == 1); - for (size_t drive = 0; drive < numSmartDrivers; ++drive) - { - if (IsBitSet(drivers, drive)) - { - SmartDrivers::SetStallFilter(drive, sgFilter); - } - } + drivers.Iterate([sgFilter](unsigned int drive) { SmartDrivers::SetStallFilter(drive, sgFilter); }); } if (gb.Seen('H')) { seen = true; const unsigned int stepsPerSecond = gb.GetUIValue(); - for (size_t drive = 0; drive < numSmartDrivers; ++drive) - { - if (IsBitSet(drivers, drive)) - { - SmartDrivers::SetStallMinimumStepsPerSecond(drive, stepsPerSecond); - } - } + drivers.Iterate([stepsPerSecond](unsigned int drive) { SmartDrivers::SetStallMinimumStepsPerSecond(drive, stepsPerSecond); }); } if (gb.Seen('T')) { seen = true; const uint16_t coolStepConfig = (uint16_t)gb.GetUIValue(); - for (size_t drive = 0; drive < numSmartDrivers; ++drive) - { - if (IsBitSet(drivers, drive)) - { - SmartDrivers::SetRegister(drive, SmartDriverRegister::coolStep, coolStepConfig); - } - } + drivers.Iterate([coolStepConfig](unsigned int drive) { SmartDrivers::SetRegister(drive, SmartDriverRegister::coolStep, coolStepConfig); } ); } if (gb.Seen('R')) { @@ -4114,33 +4094,26 @@ GCodeResult Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& return GCodeResult::notFinished; } - if (drivers == 0) + if (drivers.IsEmpty()) { - drivers = LowestNBits(numSmartDrivers); + drivers = DriversBitmap::MakeLowestNBits(numSmartDrivers); } - bool printed = false; - for (size_t drive = 0; drive < numSmartDrivers; ++drive) - { - if (IsBitSet(drivers, drive)) - { - if (printed) + drivers.Iterate + ([buf, this, reply](unsigned int drive) { - buf->cat('\n'); + buf->lcatf("Driver %u: ", drive); + reply.Clear(); // we use 'reply' as a temporary buffer + SmartDrivers::AppendStallConfig(drive, reply); + buf->cat(reply.c_str()); + buf->catf(", action: %s", + (rehomeOnStallDrivers.IsBitSet(drive)) ? "rehome" + : (pauseOnStallDrivers.IsBitSet(drive)) ? "pause" + : (logOnStallDrivers.IsBitSet(drive)) ? "log" + : "none" + ); } - buf->catf("Driver %u: ", drive); - reply.Clear(); // we use 'reply' as a temporary buffer - SmartDrivers::AppendStallConfig(drive, reply); - buf->cat(reply.c_str()); - buf->catf(", action: %s", - (IsBitSet(rehomeOnStallDrivers, drive)) ? "rehome" - : (IsBitSet(pauseOnStallDrivers, drive)) ? "pause" - : (IsBitSet(logOnStallDrivers, drive)) ? "log" - : "none" - ); - printed = true; - } - } + ); return GCodeResult::ok; } diff --git a/src/Platform.h b/src/Platform.h index 001758db..7f387070 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -274,6 +274,7 @@ public: enum class DriverStatus : uint8_t { disabled, idle, enabled }; Platform() noexcept; + Platform(const Platform&) = delete; //------------------------------------------------------------------------------------------------------------- @@ -511,7 +512,7 @@ public: #if HAS_SMART_DRIVERS float GetTmcDriversTemperature(unsigned int board) const noexcept; - void DriverCoolingFansOnOff(uint32_t driverChannelsMonitored, bool on) noexcept; + void DriverCoolingFansOnOff(DriverChannelsBitmap driverChannelsMonitored, bool on) noexcept; unsigned int GetNumSmartDrivers() const noexcept { return numSmartDrivers; } #endif @@ -559,23 +560,21 @@ protected: OBJECT_MODEL_ARRAY(axisDrivers) private: - Platform(const Platform&) noexcept; // private copy constructor to make sure we don't try to copy a Platform - - const char* InternalGetSysDir() const noexcept; // where the system files are - not thread-safe! + const char* InternalGetSysDir() const noexcept; // where the system files are - not thread-safe! void RawMessage(MessageType type, const char *message) noexcept; // called by Message after handling error/warning flags - void ResetChannel(size_t chan) noexcept; // re-initialise a serial channel + void ResetChannel(size_t chan) noexcept; // re-initialise a serial channel float AdcReadingToCpuTemperature(uint32_t reading) const noexcept; GCodeResult ConfigureGpioOrServo(uint32_t gpioNumber, bool isServo, GCodeBuffer& gb, const StringRef& reply); #if SUPPORT_CAN_EXPANSION - void IterateDrivers(size_t axisOrExtruder, std::function localFunc, std::function remoteFunc) noexcept; - void IterateLocalDrivers(size_t axisOrExtruder, std::function func) noexcept { IterateDrivers(axisOrExtruder, func, [](DriverId){}); } + void IterateDrivers(size_t axisOrExtruder, std::function localFunc, std::function remoteFunc) noexcept; + void IterateLocalDrivers(size_t axisOrExtruder, std::function func) noexcept { IterateDrivers(axisOrExtruder, func, [](DriverId){}); } #else - void IterateDrivers(size_t axisOrExtruder, std::function localFunc) noexcept; - void IterateLocalDrivers(size_t axisOrExtruder, std::function func) noexcept { IterateDrivers(axisOrExtruder, func); } + void IterateDrivers(size_t axisOrExtruder, std::function localFunc) noexcept; + void IterateLocalDrivers(size_t axisOrExtruder, std::function func) noexcept { IterateDrivers(axisOrExtruder, func); } #endif #if HAS_SMART_DRIVERS diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp index d3752d15..a2762756 100644 --- a/src/PrintMonitor.cpp +++ b/src/PrintMonitor.cpp @@ -41,7 +41,7 @@ const ObjectModelArrayDescriptor PrintMonitor::filamentArrayDescriptor = [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const PrintMonitor*)self)->printingFileInfo.numFilaments; }, [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue - { return ExpressionValue(((const PrintMonitor*)self)->printingFileInfo.filamentNeeded[context.GetIndex(0)]); } + { return ExpressionValue(((const PrintMonitor*)self)->printingFileInfo.filamentNeeded[context.GetIndex(0)], 1); } }; constexpr ObjectModelTableEntry PrintMonitor::objectModelTable[] = @@ -55,11 +55,11 @@ constexpr ObjectModelTableEntry PrintMonitor::objectModelTable[] = // 1. ParsedFileInfo members { "filament", OBJECT_MODEL_FUNC_NOSELF(&filamentArrayDescriptor), ObjectModelEntryFlags::none }, - { "firstLayerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.firstLayerHeight), ObjectModelEntryFlags::none }, + { "firstLayerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.firstLayerHeight, 2), ObjectModelEntryFlags::none }, { "generatedBy", OBJECT_MODEL_FUNC_IF(!self->printingFileInfo.generatedBy.IsEmpty(), self->printingFileInfo.generatedBy.c_str()), ObjectModelEntryFlags::none }, - { "height", OBJECT_MODEL_FUNC(self->printingFileInfo.objectHeight), ObjectModelEntryFlags::none }, + { "height", OBJECT_MODEL_FUNC(self->printingFileInfo.objectHeight, 2), ObjectModelEntryFlags::none }, { "lastModified", OBJECT_MODEL_FUNC(DateTime(self->printingFileInfo.lastModifiedTime)), ObjectModelEntryFlags::none }, - { "layerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.layerHeight), ObjectModelEntryFlags::none }, + { "layerHeight", OBJECT_MODEL_FUNC(self->printingFileInfo.layerHeight, 2), ObjectModelEntryFlags::none }, { "numLayers", OBJECT_MODEL_FUNC((int32_t)self->printingFileInfo.GetNumLayers()), ObjectModelEntryFlags::none }, { "printTime", OBJECT_MODEL_FUNC_IF(self->printingFileInfo.printTime != 0, (int32_t)self->printingFileInfo.printTime), ObjectModelEntryFlags::none }, { "simulatedTime", OBJECT_MODEL_FUNC_IF(self->printingFileInfo.simulatedTime != 0, (int32_t)self->printingFileInfo.simulatedTime), ObjectModelEntryFlags::none }, @@ -492,7 +492,7 @@ float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const noexcep ExpressionValue PrintMonitor::EstimateTimeLeftAsExpression(PrintEstimationMethod method) const noexcept { const float time = EstimateTimeLeft(method); - return (time > 0.0) ? ExpressionValue(time) : ExpressionValue(nullptr); + return (time > 0.0) ? ExpressionValue(lrintf(time)) : ExpressionValue(nullptr); } #endif diff --git a/src/RepRap.cpp b/src/RepRap.cpp index 8b78e4bf..5bc74024 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -1129,7 +1129,7 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) noe response->EncodeString(mbox.message, false); response->cat(",\"title\":"); response->EncodeString(mbox.title, false); - response->catf(",\"mode\":%d,\"seq\":%" PRIu32 ",\"timeout\":%.1f,\"controls\":%u}", mbox.mode, mbox.seq, (double)timeLeft, mbox.controls); + response->catf(",\"mode\":%d,\"seq\":%" PRIu32 ",\"timeout\":%.1f,\"controls\":%u}", mbox.mode, mbox.seq, (double)timeLeft, mbox.controls.GetRaw()); } response->cat('}'); } @@ -1430,15 +1430,15 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) noe } // Controllable Fans - FansBitmap controllableFans = 0; + FansBitmap controllableFans; for (size_t fan = 0; fan < MaxFans; fan++) { if (fansManager->IsFanControllable(fan)) { - SetBit(controllableFans, fan); + controllableFans.SetBit(fan); } } - response->catf(",\"controllableFans\":%lu", controllableFans); + response->catf(",\"controllableFans\":%lu", controllableFans.GetRaw()); // Maximum hotend temperature - DWC just wants the highest one response->catf(",\"tempLimit\":%.1f", (double)(heat->GetHighestTemperatureLimit())); @@ -1532,42 +1532,41 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) noe // Axis mapping response->cat("],\"axisMap\":[["); bool first = true; - for (size_t xi = 0; xi < MaxAxes; ++xi) - { - if (IsBitSet(tool->GetXAxisMap(), xi)) - { - if (first) - { - first = false; - } - else + tool->GetXAxisMap().Iterate + ([&response, &first](unsigned int xi) { - response->cat(','); + if (first) + { + first = false; + } + else + { + response->cat(','); + } + response->catf("%u", xi); } - response->catf("%u", xi); - } - } + ); response->cat("],["); + first = true; - for (size_t yi = 0; yi < MaxAxes; ++yi) - { - if (IsBitSet(tool->GetYAxisMap(), yi)) - { - if (first) - { - first = false; - } - else + tool->GetYAxisMap().Iterate + ([&response, &first](unsigned int yi) { - response->cat(','); + if (first) + { + first = false; + } + else + { + response->cat(','); + } + response->catf("%u", yi); } - response->catf("%u", yi); - } - } + ); response->cat("]]"); // Fan mapping - response->catf(",\"fans\":%lu", tool->GetFanMapping()); + response->catf(",\"fans\":%lu", tool->GetFanMapping().GetRaw()); // Filament (if any) if (tool->GetFilament() != nullptr) @@ -1983,7 +1982,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq) noexcept if (mbox.active) { response->catf(",\"msgBox.mode\":%d,\"msgBox.seq\":%" PRIu32 ",\"msgBox.timeout\":%.1f,\"msgBox.controls\":%u", - mbox.mode, mbox.seq, (double)timeLeft, mbox.controls); + mbox.mode, mbox.seq, (double)timeLeft, mbox.controls.GetRaw()); response->cat(",\"msgBox.msg\":"); response->EncodeString(mbox.message, false); response->cat(",\"msgBox.title\":"); @@ -2570,7 +2569,7 @@ bool RepRap::WriteToolParameters(FileStore *f, const bool forceWriteOffsets) noe for (const Tool *t = toolList; ok && t != nullptr; t = t->Next()) { const AxesBitmap axesProbed = t->GetAxisOffsetsProbed(); - if (axesProbed != 0 || forceWriteOffsets) + if (axesProbed.IsNonEmpty() || forceWriteOffsets) { String scratchString; if (!written) @@ -2581,7 +2580,7 @@ bool RepRap::WriteToolParameters(FileStore *f, const bool forceWriteOffsets) noe scratchString.catf("G10 P%d", t->Number()); for (size_t axis = 0; axis < MaxAxes; ++axis) { - if (forceWriteOffsets || IsBitSet(axesProbed, axis)) + if (forceWriteOffsets || axesProbed.IsBitSet(axis)) { scratchString.catf(" %c%.2f", gCodes->GetAxisLetters()[axis], (double)(t->GetOffset(axis))); } diff --git a/src/RepRapFirmware.cpp b/src/RepRapFirmware.cpp index 101a57f2..42f87c85 100644 --- a/src/RepRapFirmware.cpp +++ b/src/RepRapFirmware.cpp @@ -259,14 +259,7 @@ double HideNan(float val) noexcept // Append a list of driver numbers to a string, with a space before each one void ListDrivers(const StringRef& str, DriversBitmap drivers) noexcept { - for (unsigned int d = 0; drivers != 0; ++d) - { - if ((drivers & 1) != 0) - { - str.catf(" %u", d); - } - drivers >>= 1; - } + drivers.Iterate([str](unsigned int d) { str.catf(" %u", d); }); } // End diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index 8d8bf2ca..5fab76eb 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -264,31 +264,33 @@ class LinuxInterface; // 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 older processors -typedef float floatc_t; // type of matrix element used for calibration +typedef float floatc_t; // type of matrix element used for calibration #endif -typedef uint16_t AxesBitmap; // Type of a bitmap representing a set of axes -typedef uint32_t ExtrudersBitmap; // Type of a bitmap representing a set of extruder drive numbers -typedef uint32_t DriversBitmap; // Type of a bitmap representing a set of local driver numbers -typedef uint32_t FansBitmap; // Type of a bitmap representing a set of fan numbers -typedef uint32_t HeatersBitmap; // Type of a bitmap representing a set of heater numbers -typedef uint16_t Pwm_t; // Type of a PWM value when we don't want to use floats +typedef Bitmap AxesBitmap; // Type of a bitmap representing a set of axes +typedef Bitmap ExtrudersBitmap; // Type of a bitmap representing a set of extruder drive numbers +typedef Bitmap DriversBitmap; // Type of a bitmap representing a set of local driver numbers +typedef Bitmap FansBitmap; // Type of a bitmap representing a set of fan numbers +typedef Bitmap HeatersBitmap; // Type of a bitmap representing a set of heater numbers +typedef Bitmap DriverChannelsBitmap; // Type of a bitmap representing a set of drivers that typically have a common cooling fan + +typedef uint16_t Pwm_t; // Type of a PWM value when we don't want to use floats #if SUPPORT_CAN_EXPANSION -typedef uint64_t SensorsBitmap; +typedef Bitmap SensorsBitmap; #else -typedef uint32_t SensorsBitmap; +typedef Bitmap SensorsBitmap; #endif -static_assert(MaxAxes <= sizeof(AxesBitmap) * CHAR_BIT); -static_assert(MaxExtruders <= sizeof(ExtrudersBitmap) * CHAR_BIT); -static_assert(MaxFans <= sizeof(FansBitmap) * CHAR_BIT); -static_assert(MaxHeaters <= sizeof(HeatersBitmap) * CHAR_BIT); -static_assert(NumDirectDrivers <= sizeof(DriversBitmap) * CHAR_BIT); -static_assert(MaxSensors <= sizeof(SensorsBitmap) * CHAR_BIT); +static_assert(MaxAxes <= AxesBitmap::MaxBits()); +static_assert(MaxExtruders <= ExtrudersBitmap::MaxBits()); +static_assert(MaxFans <= FansBitmap::MaxBits()); +static_assert(MaxHeaters <= HeatersBitmap::MaxBits()); +static_assert(NumDirectDrivers <= DriversBitmap::MaxBits()); +static_assert(MaxSensors <= SensorsBitmap::MaxBits()); #if SUPPORT_IOBITS typedef uint16_t IoBits_t; // Type of the port control bitmap (G1 P parameter) @@ -399,6 +401,7 @@ private: // Common definitions used by more than one module +constexpr size_t XY_AXES = 2; // The number of Cartesian axes constexpr size_t XYZ_AXES = 3; // The number of Cartesian axes constexpr size_t X_AXIS = 0, Y_AXIS = 1, Z_AXIS = 2; // The indices of the Cartesian axes in drive arrays constexpr size_t U_AXIS = 3; // The assumed index of the U axis when executing M673 @@ -419,8 +422,10 @@ constexpr size_t MaxTotalDrivers = NumDirectDrivers; inline size_t ExtruderToLogicalDrive(size_t extruder) noexcept { return MaxAxesPlusExtruders - 1 - extruder; } inline size_t LogicalDriveToExtruder(size_t drive) noexcept { return MaxAxesPlusExtruders - 1 - drive; } -constexpr AxesBitmap DefaultXAxisMapping = MakeBitmap(X_AXIS); // by default, X is mapped to X -constexpr AxesBitmap DefaultYAxisMapping = MakeBitmap(Y_AXIS); // by default, Y is mapped to Y +const AxesBitmap DefaultXAxisMapping = AxesBitmap::MakeFromBits(X_AXIS); // by default, X is mapped to X +const AxesBitmap DefaultYAxisMapping = AxesBitmap::MakeFromBits(Y_AXIS); // by default, Y is mapped to Y +const AxesBitmap XyzAxes = AxesBitmap::MakeLowestNBits(XYZ_AXES); +const AxesBitmap XyAxes = AxesBitmap::MakeLowestNBits(XY_AXES); // Common conversion factors constexpr float MinutesToSeconds = 60.0; @@ -433,6 +438,8 @@ constexpr float TwoPi = 3.141592653589793 * 2; constexpr float DegreesToRadians = 3.141592653589793/180.0; constexpr float RadiansToDegrees = 180.0/3.141592653589793; +constexpr unsigned int MaxFloatDigitsDisplayedAfterPoint = 7; + #define DEGREE_SYMBOL "\xC2\xB0" // degree-symbol encoding in UTF8 // Type of an offset in a file diff --git a/src/Tools/Tool.cpp b/src/Tools/Tool.cpp index f1322058..2e2a29cb 100644 --- a/src/Tools/Tool.cpp +++ b/src/Tools/Tool.cpp @@ -44,14 +44,14 @@ constexpr ObjectModelArrayDescriptor Tool::activeTempsArrayDescriptor = { nullptr, // no lock needed [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const Tool*)self)->heaterCount; }, - [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->activeTemperatures[context.GetLastIndex()]); } + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->activeTemperatures[context.GetLastIndex()], 1); } }; constexpr ObjectModelArrayDescriptor Tool::standbyTempsArrayDescriptor = { nullptr, // no lock needed [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const Tool*)self)->heaterCount; }, - [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->standbyTemperatures[context.GetLastIndex()]); } + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->standbyTemperatures[context.GetLastIndex()], 1); } }; constexpr ObjectModelArrayDescriptor Tool::heatersArrayDescriptor = @@ -68,19 +68,60 @@ constexpr ObjectModelArrayDescriptor Tool::extrudersArrayDescriptor = [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue((int32_t)((const Tool*)self)->drives[context.GetLastIndex()]); } }; +constexpr ObjectModelArrayDescriptor Tool::mixArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const Tool*)self)->driveCount; }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->mix[context.GetLastIndex()], 2); } +}; + +constexpr ObjectModelArrayDescriptor Tool::fansArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return ((const Tool*)self)->fanMapping.CountSetBits(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue((int32_t)((const Tool*)self)->fanMapping.GetSetBitNumber(context.GetLastIndex())); } +}; + +constexpr ObjectModelArrayDescriptor Tool::offsetsArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return reprap.GetGCodes().GetVisibleAxes(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(((const Tool*)self)->offset[context.GetLastIndex()], 2); } +}; + +constexpr ObjectModelArrayDescriptor Tool::axesArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext&) noexcept -> size_t { return 2; }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue { return ExpressionValue(&oneAxisArrayDescriptor); } +}; + +constexpr ObjectModelArrayDescriptor Tool::oneAxisArrayDescriptor = +{ + nullptr, // no lock needed + [] (const ObjectModel *self, const ObjectExplorationContext& context) noexcept -> size_t { return ((const Tool*)self)->axisMapping[context.GetLastIndex()].CountSetBits(); }, + [] (const ObjectModel *self, ObjectExplorationContext& context) noexcept -> ExpressionValue + { return ExpressionValue((int32_t)((const Tool*)self)->axisMapping[context.GetIndex(1)].GetSetBitNumber(context.GetLastIndex())); } +}; + constexpr ObjectModelTableEntry Tool::objectModelTable[] = { // Within each group, these entries must be in alphabetical order // 0. Tool members - { "active", OBJECT_MODEL_FUNC_NOSELF(&activeTempsArrayDescriptor), ObjectModelEntryFlags::live }, - { "extruders", OBJECT_MODEL_FUNC_NOSELF(&extrudersArrayDescriptor), ObjectModelEntryFlags::none }, - { "heaters", OBJECT_MODEL_FUNC_NOSELF(&heatersArrayDescriptor), ObjectModelEntryFlags::none }, - { "name", OBJECT_MODEL_FUNC(self->name), ObjectModelEntryFlags::none }, - { "standby", OBJECT_MODEL_FUNC_NOSELF(&standbyTempsArrayDescriptor), ObjectModelEntryFlags::live }, - { "state", OBJECT_MODEL_FUNC(self->state.ToString()), ObjectModelEntryFlags::live }, + { "active", OBJECT_MODEL_FUNC_NOSELF(&activeTempsArrayDescriptor), ObjectModelEntryFlags::live }, + { "axes", OBJECT_MODEL_FUNC_NOSELF(&axesArrayDescriptor), ObjectModelEntryFlags::none }, + { "extruders", OBJECT_MODEL_FUNC_NOSELF(&extrudersArrayDescriptor), ObjectModelEntryFlags::none }, + { "fans", OBJECT_MODEL_FUNC_NOSELF(&fansArrayDescriptor), ObjectModelEntryFlags::none }, + { "heaters", OBJECT_MODEL_FUNC_NOSELF(&heatersArrayDescriptor), ObjectModelEntryFlags::none }, + { "mix", OBJECT_MODEL_FUNC_NOSELF(&mixArrayDescriptor), ObjectModelEntryFlags::none }, + { "name", OBJECT_MODEL_FUNC(self->name), ObjectModelEntryFlags::none }, + { "offsets", OBJECT_MODEL_FUNC_NOSELF(&offsetsArrayDescriptor), ObjectModelEntryFlags::none }, + { "standby", OBJECT_MODEL_FUNC_NOSELF(&standbyTempsArrayDescriptor), ObjectModelEntryFlags::live }, + { "state", OBJECT_MODEL_FUNC(self->state.ToString()), ObjectModelEntryFlags::live }, }; -constexpr uint8_t Tool::objectModelTableDescriptor[] = { 1, 6 }; +constexpr uint8_t Tool::objectModelTableDescriptor[] = { 1, 10 }; DEFINE_GET_OBJECT_MODEL_TABLE(Tool) @@ -151,11 +192,11 @@ DEFINE_GET_OBJECT_MODEL_TABLE(Tool) t->state = ToolState::off; t->driveCount = (uint8_t)dCount; t->heaterCount = (uint8_t)hCount; - t->xMapping = xMap; - t->yMapping = yMap; + t->axisMapping[0] = xMap; + t->axisMapping[1] = yMap; t->fanMapping = fanMap; t->heaterFault = false; - t->axisOffsetsProbed = 0; + t->axisOffsetsProbed.Clear(); t->displayColdExtrudeWarning = false; for (size_t axis = 0; axis < MaxAxes; axis++) @@ -186,12 +227,12 @@ DEFINE_GET_OBJECT_MODEL_TABLE(Tool) /*static*/ AxesBitmap Tool::GetXAxes(const Tool *tool) noexcept { - return (tool == nullptr) ? DefaultXAxisMapping : tool->xMapping; + return (tool == nullptr) ? DefaultXAxisMapping : tool->axisMapping[0]; } /*static*/ AxesBitmap Tool::GetYAxes(const Tool *tool) noexcept { - return (tool == nullptr) ? DefaultYAxisMapping : tool->yMapping; + return (tool == nullptr) ? DefaultYAxisMapping : tool->axisMapping[1]; } /*static*/ float Tool::GetOffset(const Tool *tool, size_t axis) noexcept @@ -241,7 +282,7 @@ void Tool::Print(const StringRef& reply) const noexcept char sep = ' '; for (size_t xi = 0; xi < MaxAxes; ++xi) { - if ((xMapping & (1u << xi)) != 0) + if (axisMapping[0].IsBitSet(xi)) { reply.catf("%c%c", sep, reprap.GetGCodes().GetAxisLetters()[xi]); sep = ','; @@ -252,7 +293,7 @@ void Tool::Print(const StringRef& reply) const noexcept sep = ' '; for (size_t yi = 0; yi < MaxAxes; ++yi) { - if ((yMapping & (1u << yi)) != 0) + if (axisMapping[1].IsBitSet(yi)) { reply.catf("%c%c", sep, reprap.GetGCodes().GetAxisLetters()[yi]); sep = ','; @@ -263,7 +304,7 @@ void Tool::Print(const StringRef& reply) const noexcept sep = ' '; for (size_t fi = 0; fi < MaxFans; ++fi) { - if ((fanMapping & (1u << fi)) != 0) + if (fanMapping.IsBitSet(fi)) { reply.catf("%c%u", sep, fi); sep = ','; @@ -455,7 +496,7 @@ void Tool::SetOffset(size_t axis, float offs, bool byProbing) noexcept offset[axis] = offs; if (byProbing) { - SetBit(axisOffsetsProbed, axis); + axisOffsetsProbed.SetBit(axis); } } diff --git a/src/Tools/Tool.h b/src/Tools/Tool.h index 3f6f7f7b..8291c30b 100644 --- a/src/Tools/Tool.h +++ b/src/Tools/Tool.h @@ -70,8 +70,8 @@ public: void DefineMix(const float m[]) noexcept; const float* GetMix() const noexcept; void Print(const StringRef& reply) const noexcept; - AxesBitmap GetXAxisMap() const noexcept { return xMapping; } - AxesBitmap GetYAxisMap() const noexcept { return yMapping; } + AxesBitmap GetXAxisMap() const noexcept { return axisMapping[0]; } + AxesBitmap GetYAxisMap() const noexcept { return axisMapping[1]; } FansBitmap GetFanMapping() const noexcept { return fanMapping; } Filament *GetFilament() const noexcept { return filament; } Tool *Next() const noexcept { return next; } @@ -93,13 +93,15 @@ public: protected: DECLARE_OBJECT_MODEL - -#if SUPPORT_OBJECT_MODEL - static const ObjectModelArrayDescriptor activeTempsArrayDescriptor; - static const ObjectModelArrayDescriptor standbyTempsArrayDescriptor; - static const ObjectModelArrayDescriptor heatersArrayDescriptor; - static const ObjectModelArrayDescriptor extrudersArrayDescriptor; -#endif + OBJECT_MODEL_ARRAY(activeTemps) + OBJECT_MODEL_ARRAY(axes) + OBJECT_MODEL_ARRAY(extruders) + OBJECT_MODEL_ARRAY(fans) + OBJECT_MODEL_ARRAY(heaters) + OBJECT_MODEL_ARRAY(mix) + OBJECT_MODEL_ARRAY(offsets) + OBJECT_MODEL_ARRAY(standbyTemps) + OBJECT_MODEL_ARRAY(oneAxis) void Activate() noexcept; void Standby() noexcept; @@ -126,7 +128,7 @@ private: uint8_t driveCount; uint8_t heaterCount; uint16_t myNumber; - AxesBitmap xMapping, yMapping; + AxesBitmap axisMapping[2]; AxesBitmap axisOffsetsProbed; FansBitmap fanMapping; uint8_t drives[MaxExtrudersPerTool]; diff --git a/src/Version.h b/src/Version.h index 988ea29f..73f802ec 100644 --- a/src/Version.h +++ b/src/Version.h @@ -20,7 +20,7 @@ #endif #ifndef DATE -# define DATE "2020-01-18b1" +# define DATE "2020-01-18b3" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d" -- cgit v1.2.3