diff options
author | David Crocker <dcrocker@eschertech.com> | 2020-01-19 02:03:39 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2020-01-19 02:03:39 +0300 |
commit | c812ce5e14cf476526d955edbce2effa9d922902 (patch) | |
tree | da67dc55e46efdd38a0647318977a342da730345 /src | |
parent | e0bbf71357b07c22e6d43be3cca5c7422163be32 (diff) |
Major refactoring, bug fixes in function evaluation
Changed all bitmaps to use the bitmap class from RRFLibraries
Fixed bugs in functoin evaluation
Diffstat (limited to 'src')
61 files changed, 781 insertions, 699 deletions
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<CanMessageMultipleDrivesRequest>(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<CanMessageMultipleDrivesRequest>(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<uint16_t> 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<CanMessageStopMovement>(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<AxesBitmap>(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<AxesBitmap>(GetAxis())) != 0); + stopAll = kin.GetConnectedAxes(GetAxis()).Intersects(~AxesBitmap::MakeFromBits(GetAxis())); numPortsLeftToTrigger = (numPortsUsed != axisDrivers.numDrivers) ? 1 : numPortsUsed; - portsLeftToTrigger = LowestNBits<PortsBitmap>(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<uint16_t> 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<AxesBitmap>(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<StringLength20> 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<Fan*>(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<float>(reqVal, (bangBangMode) ? max<float>(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<float>(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<float>(0.5, val) : minVal; - reqVal = constrain<float>(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<float>(reqVal, (bangBangMode) ? max<float>(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<float>(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<float>(0.5, val) : minVal; + reqVal = constrain<float>(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<long>(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<float>(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<float>(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<uint32_t> 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<StringLength20> 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<AxesBitmap>(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<AxesBitmap>(numTotalAxes); - if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & LowestNBits<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(xMapping, xCount) & LowestNBits<AxesBitmap>(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<AxesBitmap>(yMapping, yCount) & LowestNBits<AxesBitmap>(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<FansBitmap>(fanMapping, fanCount) & LowestNBits<FansBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<StringLength20> 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<uint32_t> TriggerNumbersBitmap; // Bitmap of trigger numbers +typedef Bitmap<uint16_t> 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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(Z_AXIS); + return AxesBitmap::MakeFromBits(Z_AXIS); } AxesBitmap FiveBarScaraKinematics::GetConnectedAxes(size_t axis) const { return (axis == X_AXIS || axis == Y_AXIS) - ? MakeBitmap<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) - : MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(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<AxesBitmap>(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<DriversBitmap>(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<DriversBitmap>(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<DriversBitmap>(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<DriversBitmap>(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 <cstring> #include <General/SafeStrtod.h> +// 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<unsigned int>(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<uint16_t>): + if (context.ShortFormReport()) + { + buf->catf("%" PRIu16, (uint16_t)val.uVal); + } + else + { + Bitmap<uint16_t> bm = Bitmap<uint16_t>::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<uint32_t>): if (context.ShortFormReport()) { buf->catf("%" PRIu32, val.uVal); } else { - uint32_t v = val.uVal; + Bitmap<uint32_t> bm = Bitmap<uint32_t>::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<uint64_t>): + if (context.ShortFormReport()) + { + buf->catf("%" PRIu64, val.Get56BitValue()); + } + else + { + Bitmap<uint64_t> bm = Bitmap<uint64_t>::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 <General/IPAddress.h> +#include <General/Bitmap.h> #include <RTOSIface/RTOSIface.h> 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<class T> constexpr TypeCode TypeOf() noexcept; -template<> constexpr TypeCode TypeOf<bool>() noexcept { return 1; } -template<> constexpr TypeCode TypeOf<char>() noexcept { return 2; } -template<> constexpr TypeCode TypeOf<uint32_t>() noexcept { return 3; } -template<> constexpr TypeCode TypeOf<int32_t>() noexcept { return 4; } -template<> constexpr TypeCode TypeOf<float>() noexcept { return 5; } -template<> constexpr TypeCode TypeOf<Bitmap32>() noexcept { return 6; } -template<> constexpr TypeCode TypeOf<Enum32>() noexcept { return 7; } -template<> constexpr TypeCode TypeOf<const ObjectModel*>() noexcept { return 8; } -template<> constexpr TypeCode TypeOf<const char*>() noexcept { return 9; } -template<> constexpr TypeCode TypeOf<IPAddress>() noexcept { return 10; } -template<> constexpr TypeCode TypeOf<const ObjectModelArrayDescriptor*>() noexcept { return 11; } -template<> constexpr TypeCode TypeOf<DateTime>() noexcept { return 12; } -template<> constexpr TypeCode TypeOf<DriverId>() noexcept { return 13; } +template<> constexpr TypeCode TypeOf<bool> () noexcept { return 1; } +template<> constexpr TypeCode TypeOf<char> () noexcept { return 2; } +template<> constexpr TypeCode TypeOf<uint32_t> () noexcept { return 3; } +template<> constexpr TypeCode TypeOf<int32_t> () noexcept { return 4; } +template<> constexpr TypeCode TypeOf<float> () noexcept { return 5; } +template<> constexpr TypeCode TypeOf<Bitmap<uint16_t>> () noexcept { return 6; } +template<> constexpr TypeCode TypeOf<Bitmap<uint32_t>> () noexcept { return 7; } +template<> constexpr TypeCode TypeOf<Bitmap<uint64_t>> () noexcept { return 8; } +template<> constexpr TypeCode TypeOf<Enum32> () noexcept { return 9; } +template<> constexpr TypeCode TypeOf<const ObjectModel*> () noexcept { return 10; } +template<> constexpr TypeCode TypeOf<const char*> () noexcept { return 11; } +template<> constexpr TypeCode TypeOf<IPAddress> () noexcept { return 12; } +template<> constexpr TypeCode TypeOf<const ObjectModelArrayDescriptor*> () noexcept { return 13; } +template<> constexpr TypeCode TypeOf<DateTime> () noexcept { return 14; } +template<> constexpr TypeCode TypeOf<DriverId> () 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<uint16_t> bm) noexcept : type(TYPE_OF(Bitmap<uint16_t>)), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap<uint32_t> bm) noexcept : type(TYPE_OF(Bitmap<uint32_t>)), param(0), uVal(bm.GetRaw()) { } + explicit ExpressionValue(Bitmap<uint64_t> bm) noexcept : type(TYPE_OF(Bitmap<uint64_t>)), 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<DriversBitmap>(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<DriversBitmap>(5), LowestNBits<DriversBitmap>(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<DriversBitmap>(5), LowestNBits<DriversBitmap>(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<DriversBitmap>(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<StringLength100> 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<StringLength100> 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<StringLength100> 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<DriversBitmap>(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<uint16_t>(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<uint16_t>(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<uint16_t>(5) // drivers 0-4 are on the main board - : LowestNBits<uint16_t>(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<uint16_t>(2) // drivers 0,1 are on-board - : LowestNBits<uint16_t>(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<uint16_t>(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<uint16_t>(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<DriversBitmap>(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<void(uint8_t)> localFunc, std::function<void(DriverId)> remoteFunc) noexcept; - void IterateLocalDrivers(size_t axisOrExtruder, std::function<void(uint8_t)> func) noexcept { IterateDrivers(axisOrExtruder, func, [](DriverId){}); } + void IterateDrivers(size_t axisOrExtruder, std::function<void(uint8_t) /*noexcept*/ > localFunc, std::function<void(DriverId) /*noexcept*/ > remoteFunc) noexcept; + void IterateLocalDrivers(size_t axisOrExtruder, std::function<void(uint8_t) /*noexcept*/ > func) noexcept { IterateDrivers(axisOrExtruder, func, [](DriverId){}); } #else - void IterateDrivers(size_t axisOrExtruder, std::function<void(uint8_t)> localFunc) noexcept; - void IterateLocalDrivers(size_t axisOrExtruder, std::function<void(uint8_t)> func) noexcept { IterateDrivers(axisOrExtruder, func); } + void IterateDrivers(size_t axisOrExtruder, std::function<void(uint8_t) /*noexcept*/ > localFunc) noexcept; + void IterateLocalDrivers(size_t axisOrExtruder, std::function<void(uint8_t) /*noexcept*/ > 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<StringLength256> 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<uint16_t> AxesBitmap; // Type of a bitmap representing a set of axes +typedef Bitmap<uint32_t> ExtrudersBitmap; // Type of a bitmap representing a set of extruder drive numbers +typedef Bitmap<uint32_t> DriversBitmap; // Type of a bitmap representing a set of local driver numbers +typedef Bitmap<uint32_t> FansBitmap; // Type of a bitmap representing a set of fan numbers +typedef Bitmap<uint32_t> HeatersBitmap; // Type of a bitmap representing a set of heater numbers +typedef Bitmap<uint16_t> DriverChannelsBitmap; // Type of a bitmap representing a set of drivers that typically have a common cooling fan + +typedef 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<uint64_t> SensorsBitmap; #else -typedef uint32_t SensorsBitmap; +typedef Bitmap<uint32_t> 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<AxesBitmap>(X_AXIS); // by default, X is mapped to X -constexpr AxesBitmap DefaultYAxisMapping = MakeBitmap<AxesBitmap>(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" |