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

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-01-19 02:03:39 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-01-19 02:03:39 +0300
commitc812ce5e14cf476526d955edbce2effa9d922902 (patch)
treeda67dc55e46efdd38a0647318977a342da730345 /src
parente0bbf71357b07c22e6d43be3cca5c7422163be32 (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')
-rw-r--r--src/CAN/CanInterface.cpp24
-rw-r--r--src/CAN/CanInterface.h6
-rw-r--r--src/CAN/CanMotion.cpp4
-rw-r--r--src/Display/Menu.cpp6
-rw-r--r--src/Endstops/Endstop.cpp2
-rw-r--r--src/Endstops/Endstop.h8
-rw-r--r--src/Endstops/EndstopsManager.cpp22
-rw-r--r--src/Endstops/StallDetectionEndstop.cpp14
-rw-r--r--src/Endstops/SwitchEndstop.cpp10
-rw-r--r--src/Endstops/SwitchEndstop.h2
-rw-r--r--src/Endstops/ZProbe.cpp20
-rw-r--r--src/Endstops/ZProbeEndstop.cpp2
-rw-r--r--src/Fans/Fan.cpp73
-rw-r--r--src/Fans/Fan.h5
-rw-r--r--src/Fans/FansManager.cpp2
-rw-r--r--src/Fans/LocalFan.cpp73
-rw-r--r--src/Fans/RemoteFan.cpp2
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.cpp22
-rw-r--r--src/GCodes/GCodeMachineState.cpp2
-rw-r--r--src/GCodes/GCodeMachineState.h2
-rw-r--r--src/GCodes/GCodes.cpp145
-rw-r--r--src/GCodes/GCodes.h4
-rw-r--r--src/GCodes/GCodes2.cpp6
-rw-r--r--src/GCodes/GCodes3.cpp26
-rw-r--r--src/GCodes/GCodes4.cpp12
-rw-r--r--src/GCodes/Trigger.cpp6
-rw-r--r--src/GCodes/Trigger.h8
-rw-r--r--src/Heating/Heat.cpp8
-rw-r--r--src/Heating/Heater.cpp6
-rw-r--r--src/Heating/Sensors/TemperatureSensor.cpp2
-rw-r--r--src/Movement/DDA.cpp54
-rw-r--r--src/Movement/DDA.h2
-rw-r--r--src/Movement/Kinematics/CoreKinematics.cpp10
-rw-r--r--src/Movement/Kinematics/FiveBarScaraKinematics.cpp16
-rw-r--r--src/Movement/Kinematics/HangprinterKinematics.cpp19
-rw-r--r--src/Movement/Kinematics/Kinematics.cpp14
-rw-r--r--src/Movement/Kinematics/Kinematics.h4
-rw-r--r--src/Movement/Kinematics/LinearDeltaKinematics.cpp19
-rw-r--r--src/Movement/Kinematics/LinearDeltaKinematics.h2
-rw-r--r--src/Movement/Kinematics/PolarKinematics.cpp16
-rw-r--r--src/Movement/Kinematics/RotaryDeltaKinematics.cpp19
-rw-r--r--src/Movement/Kinematics/RotaryDeltaKinematics.h2
-rw-r--r--src/Movement/Kinematics/ScaraKinematics.cpp16
-rw-r--r--src/Movement/Move.cpp42
-rw-r--r--src/Movement/StepperDrivers/TMC2660.cpp12
-rw-r--r--src/Movement/StepperDrivers/TMC51xx.cpp4
-rw-r--r--src/Movement/StraightProbeSettings.cpp2
-rw-r--r--src/Movement/StraightProbeSettings.h2
-rw-r--r--src/ObjectModel/ObjectModel.cpp94
-rw-r--r--src/ObjectModel/ObjectModel.h50
-rw-r--r--src/OutputMemory.cpp26
-rw-r--r--src/OutputMemory.h3
-rw-r--r--src/Platform.cpp281
-rw-r--r--src/Platform.h17
-rw-r--r--src/PrintMonitor.cpp10
-rw-r--r--src/RepRap.cpp67
-rw-r--r--src/RepRapFirmware.cpp9
-rw-r--r--src/RepRapFirmware.h43
-rw-r--r--src/Tools/Tool.cpp77
-rw-r--r--src/Tools/Tool.h22
-rw-r--r--src/Version.h2
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"