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:
Diffstat (limited to 'src')
-rw-r--r--src/CAN/CommandProcessor.cpp55
-rw-r--r--src/Config/Pins_Duet3Mini.h1
-rw-r--r--src/Config/Pins_Duet3_MB6HC.h1
-rw-r--r--src/Config/Pins_Duet3_MB6XD.h1
-rw-r--r--src/GCodes/GCodes4.cpp4
-rw-r--r--src/Movement/DDA.cpp136
-rw-r--r--src/Movement/DDA.h5
-rw-r--r--src/Movement/DDARing.cpp23
-rw-r--r--src/Movement/DDARing.h8
-rw-r--r--src/Movement/DriveMovement.cpp389
-rw-r--r--src/Movement/DriveMovement.h21
-rw-r--r--src/Movement/ExtruderShaper.h18
-rw-r--r--src/Movement/Move.cpp40
-rw-r--r--src/Movement/Move.h7
-rw-r--r--src/Movement/MoveSegment.cpp12
-rw-r--r--src/Movement/MoveSegment.h84
-rw-r--r--src/Platform/RepRap.cpp82
-rw-r--r--src/Platform/RepRap.h15
18 files changed, 322 insertions, 580 deletions
diff --git a/src/CAN/CommandProcessor.cpp b/src/CAN/CommandProcessor.cpp
index a91e8cd2..9b5b61b5 100644
--- a/src/CAN/CommandProcessor.cpp
+++ b/src/CAN/CommandProcessor.cpp
@@ -382,7 +382,30 @@ static GCodeResult EutGetInfo(const CanMessageReturnInfo& msg, const StringRef&
return GCodeResult::ok;
}
-#endif
+static GCodeResult InitiateFirmwareUpdate(const CanMessageUpdateYourFirmware& msg, const StringRef& reply)
+{
+ if (msg.boardId != CanInterface::GetCanAddress() || msg.invertedBoardId != (uint8_t)~CanInterface::GetCanAddress() || (msg.module != 0 && msg.module != 3))
+ {
+ reply.printf("Invalid firmware update command received");
+ return GCodeResult::error;
+ }
+
+ if (msg.module == 0)
+ {
+ if (!reprap.GetPlatform().FileExists(FIRMWARE_DIRECTORY, IAP_CAN_LOADER_FILE))
+ {
+ reply.printf("In-application programming binary \"%s\" not found on board %u", FIRMWARE_DIRECTORY IAP_CAN_LOADER_FILE, CanInterface::GetCanAddress());
+ return GCodeResult::error;
+ }
+ reply.printf("Board %u starting firmware update", CanInterface::GetCanAddress());
+ reprap.ScheduleFirmwareUpdateOverCan();
+ return GCodeResult::ok;
+ }
+ reply.copy("unknown firmware module number");
+ return GCodeResult::error;
+}
+
+#endif // SUPPORT_REMOTE_COMMANDS
// Process a received broadcast or request message. Don't free the message buffer
void CommandProcessor::ProcessReceivedMessage(CanMessageBuffer *buf) noexcept
@@ -410,20 +433,46 @@ void CommandProcessor::ProcessReceivedMessage(CanMessageBuffer *buf) noexcept
StepTimer::ProcessTimeSyncMessage(buf->msg.sync, buf->dataLength, buf->timeStamp);
return; // no reply needed
+ case CanMessageType::emergencyStop:
+ reprap.EmergencyStop();
+ reprap.ScheduleReset();
+ return; // no reply needed
+
case CanMessageType::movementLinear:
reprap.GetMove().AddMoveFromRemote(buf->msg.moveLinear);
return; // no reply needed
-#if USE_REMOTE_INPUT_SHAPING
+# if USE_REMOTE_INPUT_SHAPING
case CanMessageType::movementLinearShaped:
reprap.GetMove().AddShapedMoveFromRemote(buf->msg.moveLinearShaped);
return; // no reply needed
-#endif
+# endif
+
+ case CanMessageType::stopMovement:
+ reprap.GetMove().StopDrivers(buf->msg.stopMovement.whichDrives);
+ return; // no reply needed
+
+ case CanMessageType::revertPosition:
+ reprap.GetMove().RevertPosition(buf->msg.revertPosition);
+ return; // no reply needed
case CanMessageType::acknowledgeAnnounce:
CanInterface::MainBoardAcknowledgedAnnounce();
return;
+ case CanMessageType::updateFirmware:
+ requestId = buf->msg.updateYourFirmware.requestId;
+ rslt = InitiateFirmwareUpdate(buf->msg.updateYourFirmware, replyRef);
+ break;
+
+ case CanMessageType::reset:
+ requestId = buf->msg.reset.requestId;
+ reply.printf("Board %u resetting", CanInterface::GetCanAddress());
+ reprap.EmergencyStop();
+ reprap.ScheduleReset();
+ rslt = GCodeResult::ok;
+ break;
+
case CanMessageType::returnInfo:
requestId = buf->msg.getInfo.requestId;
rslt = EutGetInfo(buf->msg.getInfo, replyRef, extra);
diff --git a/src/Config/Pins_Duet3Mini.h b/src/Config/Pins_Duet3Mini.h
index 188c7f79..42612f96 100644
--- a/src/Config/Pins_Duet3Mini.h
+++ b/src/Config/Pins_Duet3Mini.h
@@ -23,6 +23,7 @@
#define IAP_FIRMWARE_FILE "Duet3Firmware_" BOARD_SHORT_NAME ".uf2"
#define IAP_UPDATE_FILE "Duet3_SDiap32_" BOARD_SHORT_NAME ".bin"
#define IAP_UPDATE_FILE_SBC "Duet3_SBCiap32_" BOARD_SHORT_NAME ".bin"
+#define IAP_CAN_LOADER_FILE "Duet3_CANiap32" BOARD_SHORT_NAME ".bin"
constexpr uint32_t IAP_IMAGE_START = 0x20038000;
#define WIFI_FIRMWARE_FILE "DuetWiFiServer.bin"
diff --git a/src/Config/Pins_Duet3_MB6HC.h b/src/Config/Pins_Duet3_MB6HC.h
index d9076bed..168d82f9 100644
--- a/src/Config/Pins_Duet3_MB6HC.h
+++ b/src/Config/Pins_Duet3_MB6HC.h
@@ -11,6 +11,7 @@
#define IAP_UPDATE_FILE "Duet3_SDiap32_" BOARD_SHORT_NAME ".bin"
#define IAP_UPDATE_FILE_SBC "Duet3_SBCiap32_" BOARD_SHORT_NAME ".bin"
+#define IAP_CAN_LOADER_FILE "Duet3_CANiap32" BOARD_SHORT_NAME ".bin"
constexpr uint32_t IAP_IMAGE_START = 0x20458000; // last 32kb of RAM
// Features definition
diff --git a/src/Config/Pins_Duet3_MB6XD.h b/src/Config/Pins_Duet3_MB6XD.h
index ac87e4dd..aa1c3bce 100644
--- a/src/Config/Pins_Duet3_MB6XD.h
+++ b/src/Config/Pins_Duet3_MB6XD.h
@@ -11,6 +11,7 @@
#define IAP_UPDATE_FILE "Duet3_SDiap32_" BOARD_SHORT_NAME ".bin"
#define IAP_UPDATE_FILE_SBC "Duet3_SBCiap32_" BOARD_SHORT_NAME ".bin"
+#define IAP_CAN_LOADER_FILE "Duet3_CANiap32" BOARD_SHORT_NAME ".bin"
constexpr uint32_t IAP_IMAGE_START = 0x20458000; // last 32kb of RAM
// Features definition
diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp
index 48256718..5c0a6cf5 100644
--- a/src/GCodes/GCodes4.cpp
+++ b/src/GCodes/GCodes4.cpp
@@ -591,12 +591,12 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept
{
// Update main firmware
firmwareUpdateModuleMap.Clear();
- String<MaxFilenameLength> filenameString;
try
{
+ String<MaxFilenameLength> filenameString;
bool dummy;
gb.TryGetQuotedString('P', filenameString.GetRef(), dummy);
- reprap.UpdateFirmware(filenameString.GetRef());
+ reprap.UpdateFirmware(IAP_UPDATE_FILE, filenameString.c_str());
// The above call does not return unless an error occurred
}
catch (const GCodeException&) { }
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index 7abd7a5c..488aac3c 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -725,6 +725,7 @@ bool DDA::InitFromRemote(const CanMessageMovementLinear& msg) noexcept
shapedSegments = unshapedSegments = nullptr;
activeDMs = completedDMs = nullptr;
+ afterPrepare.drivesMoving.Clear();
# if USE_REMOTE_INPUT_SHAPING
const size_t numDrivers = min<size_t>(msg.numDriversMinusOne + 1, min<size_t>(NumDirectDrivers, MaxLinearDriversPerCanSlave));
@@ -820,15 +821,12 @@ bool DDA::InitFromRemote(const CanMessageMovementLinear& msg) noexcept
const int32_t delta = msg.perDrive[drive].steps;
if (delta != 0)
{
- if (shapedSegments == nullptr)
- {
- EnsureUnshapedSegments(params);
- }
+ EnsureUnshapedSegments(params); // there are no shaped segments, so set up the unshaped ones
DriveMovement* const pdm = DriveMovement::Allocate(drive, DMState::idle);
pdm->totalSteps = labs(delta); // for now this is the number of net steps, but gets adjusted later if there is a reverse in direction
pdm->direction = (delta >= 0); // for now this is the direction of net movement, but gets adjusted later if it is a delta movement
-
+ afterPrepare.drivesMoving.SetBit(drive);
reprap.GetPlatform().EnableDrivers(drive, false);
const bool stepsToDo = ((msg.pressureAdvanceDrives & (1u << drive)) != 0)
? pdm->PrepareExtruder(*this, params)
@@ -876,7 +874,21 @@ bool DDA::InitFromRemote(const CanMessageMovementLinear& msg) noexcept
return true;
}
-#endif
+void DDA::StopDrivers(uint16_t whichDrives) noexcept
+{
+ if (state == executing)
+ {
+ for (size_t drive = 0; drive < NumDirectDrivers; ++drive)
+ {
+ if (whichDrives & (1u << drive))
+ {
+ StopDrive(drive);
+ }
+ }
+ }
+}
+
+#endif // SUPPORT_REMOTE_COMMANDS
// Return true if this move is or might have been intended to be a deceleration-only move
// A move planned as a deceleration-only move may have a short acceleration segment at the start because of rounding error
@@ -1330,11 +1342,6 @@ void DDA::Prepare(SimulationMode simMode) noexcept
// This code assumes that the previous move in the DDA ring is the previously-executed move, because it fetches the X and Y end coordinates from that move.
// Therefore the Move code must not store a new move in that entry until this one has been prepared! (It took me ages to track this down.)
// Ideally we would store the initial X and Y coordinates in the DDA, but we need to be economical with memory
-# if MS_USE_FPU
- // Nothing needed here, use directionVector[Z_AXIS] directly
-# else
- afterPrepare.cKc = lrintf(directionVector[Z_AXIS] * MoveSegment::KdirectionVector);
-# endif
params.a2plusb2 = fsquare(directionVector[X_AXIS]) + fsquare(directionVector[Y_AXIS]);
params.initialX = prev->GetEndCoordinate(X_AXIS, false);
params.initialY = prev->GetEndCoordinate(Y_AXIS, false);
@@ -1894,73 +1901,86 @@ pre(state == frozen)
{
p.EnableAllSteppingDrivers(); // make sure that all drivers are enabled
}
- const size_t numTotalAxes = reprap.GetGCodes().GetTotalAxes();
- unsigned int extrusions = 0, retractions = 0; // bitmaps of extruding and retracting drives
- float extrusionFraction = 0.0;
- for (const DriveMovement* pdm = activeDMs; pdm != nullptr; pdm = pdm->nextDM)
+
+#if SUPPORT_REMOTE_COMMANDS
+ if (flags.isRemote)
{
- const size_t drive = pdm->drive;
- p.SetDirection(drive, pdm->direction);
- if (drive >= numTotalAxes && drive < MaxAxesPlusExtruders) // if it's an extruder
+ for (const DriveMovement* pdm = activeDMs; pdm != nullptr; pdm = pdm->nextDM)
{
- const size_t extruder = LogicalDriveToExtruder(drive);
- if (pdm->direction == FORWARDS)
- {
- extrusions |= (1u << extruder);
- extrusionFraction += directionVector[drive];
- }
- else
- {
- retractions |= (1u << extruder);
- }
+ p.SetDirection(pdm->drive, pdm->direction);
}
}
-
- bool extruding = false;
- if ((extrusions | retractions) != 0)
+ else
+#endif
{
- // Check for trying to extrude or retract when the hot end temperature is too low
- const unsigned int prohibitedMovements = reprap.GetProhibitedExtruderMovements(extrusions, retractions);
- for (DriveMovement **dmpp = &activeDMs; *dmpp != nullptr; )
+ const size_t numTotalAxes = reprap.GetGCodes().GetTotalAxes();
+ unsigned int extrusions = 0, retractions = 0; // bitmaps of extruding and retracting drives
+ float extrusionFraction = 0.0;
+ for (const DriveMovement* pdm = activeDMs; pdm != nullptr; pdm = pdm->nextDM)
{
- DriveMovement* const dm = *dmpp;
- const size_t drive = dm->drive;
- if (drive >= numTotalAxes && drive < MaxAxesPlusExtruders)
+ const size_t drive = pdm->drive;
+ p.SetDirection(drive, pdm->direction);
+ if (drive >= numTotalAxes && drive < MaxAxesPlusExtruders) // if it's an extruder
{
- if ((prohibitedMovements & (1u << LogicalDriveToExtruder(drive))) != 0)
+ const size_t extruder = LogicalDriveToExtruder(drive);
+ if (pdm->direction == FORWARDS)
{
- *dmpp = dm->nextDM;
- dm->nextDM = completedDMs;
- completedDMs = dm;
+ extrusions |= (1u << extruder);
+ extrusionFraction += directionVector[drive];
}
else
{
- extruding = true;
- dmpp = &(dm->nextDM);
+ retractions |= (1u << extruder);
}
}
- else
+ }
+
+ bool extruding = false;
+ if ((extrusions | retractions) != 0)
+ {
+ // Check for trying to extrude or retract when the hot end temperature is too low
+ const unsigned int prohibitedMovements = reprap.GetProhibitedExtruderMovements(extrusions, retractions);
+ for (DriveMovement **dmpp = &activeDMs; *dmpp != nullptr; )
{
- dmpp = &(dm->nextDM);
+ DriveMovement* const dm = *dmpp;
+ const size_t drive = dm->drive;
+ if (drive >= numTotalAxes && drive < MaxAxesPlusExtruders)
+ {
+ if ((prohibitedMovements & (1u << LogicalDriveToExtruder(drive))) != 0)
+ {
+ *dmpp = dm->nextDM;
+ dm->nextDM = completedDMs;
+ completedDMs = dm;
+ }
+ else
+ {
+ extruding = true;
+ dmpp = &(dm->nextDM);
+ }
+ }
+ else
+ {
+ dmpp = &(dm->nextDM);
+ }
}
}
- }
- if (extruding)
- {
- p.ExtrudeOn();
- if (tool != nullptr)
+ if (extruding)
{
- // Pass the extrusion speed averaged over the whole move in mm/sec
- tool->ApplyFeedForward((extrusionFraction * totalDistance * (float)StepClockRate)/(float)clocksNeeded);
+ p.ExtrudeOn();
+ if (tool != nullptr)
+ {
+ // Pass the extrusion speed averaged over the whole move in mm/sec
+ tool->ApplyFeedForward((extrusionFraction * totalDistance * (float)StepClockRate)/(float)clocksNeeded);
+ }
}
- }
- else
- {
- p.ExtrudeOff();
- if (tool != nullptr)
+ else
{
- tool->StopFeedForward();
+ p.ExtrudeOff();
+ if (tool != nullptr)
+ {
+ tool->StopFeedForward();
+ }
}
}
}
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 96a1ab86..fe37aee3 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -131,6 +131,7 @@ public:
# else
bool InitFromRemote(const CanMessageMovementLinear& msg) noexcept;
# endif
+ void StopDrivers(uint16_t whichDrives) noexcept;
#endif
const int32_t *DriveCoordinates() const noexcept { return endPoint; } // Get endpoints of a move in machine coordinates
@@ -344,10 +345,6 @@ private:
DriversBitmap drivesMoving; // bitmap of logical drives moving - needed to keep track of whether remote drives are moving
static_assert(MaxAxesPlusExtruders <= DriversBitmap::MaxBits());
#endif
- // These are used only in delta calculations
-#if SUPPORT_LINEAR_DELTA && !MS_USE_FPU
- int32_t cKc; // The Z movement fraction multiplied by Kc and converted to integer
-#endif
} afterPrepare;
};
diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp
index ed8d9e00..9054705b 100644
--- a/src/Movement/DDARing.cpp
+++ b/src/Movement/DDARing.cpp
@@ -580,6 +580,13 @@ void DDARing::CurrentMoveCompleted() noexcept
liveCoordinatesValid = cdda->FetchEndPosition(const_cast<int32_t*>(liveEndPoints), const_cast<float *>(liveCoordinates));
liveCoordinatesChanged = true;
+#if SUPPORT_REMOTE_COMMANDS
+ for (size_t driver = 0; driver < NumDirectDrivers; ++driver)
+ {
+ lastMoveStepsTaken[driver] = cdda->GetStepsTaken(driver);
+ }
+#endif
+
// Disable interrupts before we touch any extrusion accumulators until after we set currentDda to null, in case the filament monitor interrupt has higher priority than ours
{
AtomicCriticalSectionLocker lock;
@@ -1020,6 +1027,22 @@ void DDARing::AddMoveFromRemote(const CanMessageMovementLinear& msg) noexcept
}
# endif
+
+void DDARing::StopDrivers(uint16_t whichDrives) noexcept
+{
+ const uint32_t oldPrio = ChangeBasePriority(NvicPriorityStep);
+ DDA *cdda = currentDda; // capture volatile
+ if (cdda != nullptr)
+ {
+ cdda->StopDrivers(whichDrives);
+ if (cdda->GetState() == DDA::completed)
+ {
+ CurrentMoveCompleted(); // tell the DDA ring that the current move is complete
+ }
+ }
+ RestoreBasePriority(oldPrio);
+}
+
#endif
// End
diff --git a/src/Movement/DDARing.h b/src/Movement/DDARing.h
index a9fd9a2f..e0c28685 100644
--- a/src/Movement/DDARing.h
+++ b/src/Movement/DDARing.h
@@ -92,6 +92,11 @@ public:
# else
void AddMoveFromRemote(const CanMessageMovementLinear& msg) noexcept; // add a move from the ATE to the movement queue
# endif
+ void StopDrivers(uint16_t whichDrives) noexcept;
+#endif
+
+#if SUPPORT_REMOTE_COMMANDS
+ const volatile int32_t *GetLastMoveStepsTaken() const noexcept { return lastMoveStepsTaken; }
#endif
protected:
@@ -127,6 +132,9 @@ private:
unsigned int stepErrors; // count of step errors, for diagnostics
float simulationTime; // Print time since we started simulating
+#if SUPPORT_REMOTE_COMMANDS
+ volatile int32_t lastMoveStepsTaken[NumDirectDrivers]; // how many steps were taken in the last move we did
+#endif
volatile int32_t movementAccumulators[MaxAxesPlusExtruders]; // Accumulated motor steps, used by filament monitors
volatile uint32_t extrudersPrintingSince; // The milliseconds clock time when extrudersPrinting was set to true
diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp
index fce12e1f..86fc214b 100644
--- a/src/Movement/DriveMovement.cpp
+++ b/src/Movement/DriveMovement.cpp
@@ -13,16 +13,6 @@
#include <Math/Isqrt.h>
#include "Kinematics/LinearDeltaKinematics.h"
-#if !MS_USE_FPU
-
-// The code in this file relies on right shift of a signed operand being arithmetic shift
-// Shifting generates fewer instructions than dividing by a constant power of 2 in ARM gcc even though gcc converts the division to other instructions.
-// Arithmetic shift rounds towards minus infinity, so it doesn't give quite the same result as dividing when there is a remainder.
-static_assert(((int32_t)-21 >> 1) == (int32_t)-11);
-static_assert(((int64_t)-10000000001 >> 1) == (int64_t)-5000000001);
-
-#endif
-
// Static members
DriveMovement *DriveMovement::freeList = nullptr;
@@ -68,7 +58,6 @@ void DriveMovement::DebugPrint() const noexcept
const char c = (drive < reprap.GetGCodes().GetTotalAxes()) ? reprap.GetGCodes().GetAxisLetters()[drive] : (char)('0' + LogicalDriveToExtruder(drive));
if (state != DMState::idle)
{
-#if MS_USE_FPU
debugPrintf("DM%c%s dir=%c steps=%" PRIu32 " next=%" PRIu32 " rev=%" PRIu32 " interval=%" PRIu32 " ssl=%" PRIu32 " A=%.4e B=%.4e C=%.4e dsf=%.4e tsf=%.1f",
c, (state == DMState::stepError) ? " ERR:" : ":", (direction) ? 'F' : 'B', totalSteps, nextStep, reverseStartStep, stepInterval, segmentStepLimit,
(double)pA, (double)pB, (double)pC, (double)distanceSoFar, (double)timeSoFar);
@@ -85,24 +74,6 @@ void DriveMovement::DebugPrint() const noexcept
{
debugPrintf("\n");
}
-#else
- debugPrintf("DM%c%s dir=%c steps=%" PRIu32 " next=%" PRIu32 " rev=%" PRIu32 " interval=%" PRIu32 " ssl=%" PRIu32 " A=%" PRIi64 " B=%" PRIi32 " C=%" PRIi32 " dsf=%" PRIu32 " tsf=%" PRIu32,
- c, (state == DMState::stepError) ? " ERR:" : ":", (direction) ? 'F' : 'B', totalSteps, nextStep, reverseStartStep, stepInterval, segmentStepLimit,
- iA, iB, iC, iDistanceSoFar, iTimeSoFar);
- if (isDelta)
- {
- debugPrintf(" hmz0sk=%" PRIi32 " minusAaPlusBbTimesS=%" PRIi32 " dSquaredMinusAsquaredMinusBsquared=%" PRIi64 " drev=%" PRIu32 "\n",
- mp.delta.hmz0sK, mp.delta.minusAaPlusBbTimesKs, mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared, mp.delta.iReverseStartDistance);
- }
- else if (isExtruder)
- {
- debugPrintf(" pa=%" PRIu32 " eed=%" PRIu32 " ebf=%.4e\n", mp.cart.iPressureAdvanceK, mp.cart.iExtraExtrusionDistance, (double)mp.cart.extrusionBroughtForwards);
- }
- else
- {
- debugPrintf("\n");
- }
-#endif
}
else
{
@@ -121,7 +92,6 @@ bool DriveMovement::NewCartesianSegment() noexcept
}
// Work out the movement limit in steps
-#if MS_USE_FPU
pC = currentSegment->CalcC(mp.cart.effectiveMmPerStep);
if (currentSegment->IsLinear())
{
@@ -141,27 +111,6 @@ bool DriveMovement::NewCartesianSegment() noexcept
timeSoFar += currentSegment->GetSegmentTime();
segmentStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)(distanceSoFar * mp.cart.effectiveStepsPerMm) + 1;
-#else
- iC = currentSegment->CalcC(mp.cart.iEffectiveMmPerStepTimesK);
- if (currentSegment->IsLinear())
- {
- // Set up pB, pC such that for forward motion, time = pB + pC * stepNumber
- iB = currentSegment->CalcLinearB(iDistanceSoFar, iTimeSoFar);
- state = DMState::cartLinear;
- }
- else
- {
- // Set up pA, pB, pC such that for forward motion, time = pB + sqrt(pA + pC * stepNumber)
- iA = currentSegment->CalcNonlinearA(iDistanceSoFar);
- iB = currentSegment->CalcNonlinearB(iTimeSoFar);
- state = (currentSegment->IsAccelerating()) ? DMState::cartAccel : DMState::cartDecelNoReverse;
- }
-
- iDistanceSoFar += currentSegment->GetSegmentLength();
- iTimeSoFar += currentSegment->GetSegmentTime();
-
- segmentStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)(((iDistanceSoFar * (uint64_t)mp.cart.iEffectiveStepsPerMmTimesK)) >> MoveSegment::SFstepsPerMm) + 1;
-#endif
if (nextStep < segmentStepLimit)
{
@@ -185,7 +134,6 @@ bool DriveMovement::NewDeltaSegment(const DDA& dda) noexcept
}
const float stepsPerMm = reprap.GetPlatform().DriveStepsPerUnit(drive);
-#if MS_USE_FPU
pC = currentSegment->GetC()/stepsPerMm; //TODO store the reciprocal to avoid the division
if (currentSegment->IsLinear())
{
@@ -253,56 +201,6 @@ bool DriveMovement::NewDeltaSegment(const DDA& dda) noexcept
state = DMState::deltaForwardsReversing;
}
}
-#else
- iC = currentSegment->GetC()/stepsPerMm; //TODO store the reciprocal to avoid the division? Use a scaling factor for C
- if (currentSegment->IsLinear())
- {
- // Set up pB, pC such that for forward motion, time = pB + pC * (distanceMoved * steps/mm)
- iB = currentSegment->CalcLinearB(iDistanceSoFar, iTimeSoFar);
- }
- else
- {
- // Set up pA, pB, pC such that for forward motion, time = pB + sqrt(pA + pC * (distanceMoved * steps/mm))
- iA = currentSegment->CalcNonlinearA(iDistanceSoFar);
- iB = currentSegment->CalcNonlinearB(iTimeSoFar);
- }
-
- const uint32_t startDistance = iDistanceSoFar;
- iDistanceSoFar += currentSegment->GetSegmentLength();
- iTimeSoFar += currentSegment->GetSegmentTime();
-
- // Work out whether we reverse in this segment and the movement limit in steps
- const float sDx = iDistanceSoFar * dda.directionVector[0]; //TODO avoid float maths
- const float sDy = iDistanceSoFar * dda.directionVector[1]; //TODO avoid float maths
- const int32_t netStepsAtEnd = (int32_t)(isqrt64(mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - fsquare(stepsPerMm) * (sDx * (sDx + mp.delta.fTwoA) + sDy * (sDy + mp.delta.fTwoB)))
- + (iDistanceSoFar * dda.directionVector[2] - mp.delta.h0MinusZ0) * stepsPerMm); //TODO avoid float maths
-
- if (mp.delta.iReverseStartDistance <= (int32_t)startDistance)
- {
- // This segment is purely downwards motion and we want the greater of the two quadratic solutions. There may have been upwards motion earlier in the move.
- if (direction)
- {
- direction = false;
- directionChanged = true;
- }
- state = DMState::deltaReverse;
- segmentStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1
- : (reverseStartStep <= totalSteps) ? (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd)
- : 1 - netStepsAtEnd;
- }
- else if ((int32_t)iDistanceSoFar <= mp.delta.iReverseStartDistance)
- {
- // This segment is purely upwards motion of the tower and we want the lower quadratic solution
- state = DMState::deltaForwardsNoReverse;
- segmentStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)(netStepsAtEnd + 1);
- }
- else
- {
- // This segment ends with reverse motion. We want the lower quadratic solution initially.
- segmentStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd);
- state = DMState::deltaForwardsReversing;
- }
-#endif
if (segmentStepLimit > nextStep)
{
@@ -325,7 +223,6 @@ bool DriveMovement::NewExtruderSegment() noexcept
return false;
}
-#if MS_USE_FPU
const float startDistance = distanceSoFar;
const float startTime = timeSoFar;
@@ -359,41 +256,6 @@ bool DriveMovement::NewExtruderSegment() noexcept
// Work out the movement limit in steps
segmentStepLimit = ((currentSegment->GetNext() == nullptr) ? totalSteps : (uint32_t)(distanceSoFar * mp.cart.effectiveStepsPerMm)) + 1;
-#else
- const uint32_t startDistance = iDistanceSoFar;
- const uint32_t startTime = iTimeSoFar;
-
- // Work out the movement limit in steps
- iDistanceSoFar += currentSegment->GetSegmentLength();
- iTimeSoFar += currentSegment->GetSegmentTime();
-
- iC = currentSegment->CalcC(mp.cart.iEffectiveMmPerStepTimesK);
- if (currentSegment->IsLinear())
- {
- // Set up pB, pC such that for forward motion, time = pB + pC * stepNumber
- iB = currentSegment->CalcLinearB(startDistance, startTime);
- state = DMState::cartLinear;
- }
- else
- {
- // Set up pA, pB, pC such that for forward motion, time = pB + sqrt(pA + pC * stepNumber)
- iA = currentSegment->CalcNonlinearA(startDistance, mp.cart.iPressureAdvanceK);
- iB = currentSegment->CalcNonlinearB(startTime, mp.cart.iPressureAdvanceK);
- if (currentSegment->IsAccelerating())
- {
- // Extruders have a single acceleration segment. We need to add the extra extrusion distance due to pressure advance to the extrusion distance.
- iDistanceSoFar += mp.cart.iExtraExtrusionDistance;
- state = DMState::cartAccel;
- }
- else
- {
- // This is the single decelerating segment. If it includes pressure advance then it may include reversal.
- state = DMState::cartDecelForwardsReversing; // assume that it may reverse
- }
- }
-
- segmentStepLimit = ((currentSegment->GetNext() == nullptr) ? totalSteps : (uint32_t)((iDistanceSoFar * (uint64_t)mp.cart.iEffectiveStepsPerMmTimesK)) >> MoveSegment::SFstepsPerMm) + 1;
-#endif
if (nextStep < segmentStepLimit)
{
@@ -407,22 +269,12 @@ bool DriveMovement::NewExtruderSegment() noexcept
// Prepare this DM for a Cartesian axis move, returning true if there are steps to do
bool DriveMovement::PrepareCartesianAxis(const DDA& dda, const PrepParams& params) noexcept
{
-#if MS_USE_FPU
distanceSoFar = 0.0;
timeSoFar = 0.0;
mp.cart.pressureAdvanceK = 0.0;
// We can't use directionVector here because those values relate to Cartesian space, whereas we may be CoreXY etc.
mp.cart.effectiveStepsPerMm = (float)totalSteps/dda.totalDistance;
mp.cart.effectiveMmPerStep = 1.0/mp.cart.effectiveStepsPerMm;
-#else
- iDistanceSoFar = 0;
- iTimeSoFar = 0;
- mp.cart.iPressureAdvanceK = 0;
- // We can't use directionVector here because those values relate to Cartesian space, whereas we may be CoreXY etc.
- const float stepsTimesK = (float)((uint64_t)totalSteps << MoveSegment::SFstepsPerMm);
- mp.cart.iEffectiveStepsPerMmTimesK = stepsTimesK/dda.totalDistance;
- mp.cart.iEffectiveMmPerStepTimesK = dda.totalDistance/stepsTimesK;
-#endif
isDelta = false;
isExtruder = false;
currentSegment = (dda.shapedSegments != nullptr) ? dda.shapedSegments : dda.unshapedSegments;
@@ -453,7 +305,6 @@ bool DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) n
const float dSquaredMinusAsquaredMinusBsquared = params.dparams->GetDiagonalSquared(drive) - fsquare(A) - fsquare(B);
const float h0MinusZ0 = fastSqrtf(dSquaredMinusAsquaredMinusBsquared);
-#if MS_USE_FPU
mp.delta.h0MinusZ0 = h0MinusZ0;
mp.delta.fTwoA = 2.0 * A;
mp.delta.fTwoB = 2.0 * B;
@@ -539,72 +390,6 @@ bool DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) n
distanceSoFar = 0.0;
timeSoFar = 0.0;
-#else
- mp.delta.h0MinusZ0 = h0MinusZ0; //TODO change to integer
- mp.delta.fTwoA = 2.0 * A; //TODO change to integer
- mp.delta.fTwoB = 2.0 * B; //TODO change to integer
- mp.delta.hmz0sK = lrintf(h0MinusZ0 * stepsPerMm * MoveSegment::Kdelta);
- mp.delta.minusAaPlusBbTimesKs = -lrintf(aAplusbB * stepsPerMm * MoveSegment::Kdelta);
- mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared = llrintf(dSquaredMinusAsquaredMinusBsquared * fsquare(stepsPerMm * MoveSegment::Kdelta));
-
- // Calculate the distance at which we need to reverse direction.
- if (params.a2plusb2 <= 0.0)
- {
- // Pure Z movement. We can't use the main calculation because it divides by a2plusb2.
- direction = (dda.directionVector[Z_AXIS] >= 0.0);
- const float reverseStartDistance = (direction) ? dda.totalDistance + 1.0 : -1.0; // so that we never reverse and NewDeltaSegment knows which way we are going
- mp.delta.iReverseStartDistance = (int32_t)(reverseStartDistance * MoveSegment::Kdistance);
- reverseStartStep = totalSteps + 1;
- }
- else
- {
- // The distance to reversal is the solution to a quadratic equation. One root corresponds to the carriages being below the bed,
- // the other root corresponds to the carriages being above the bed.
- const float drev = ((dda.directionVector[Z_AXIS] * fastSqrtf(params.a2plusb2 * params.dparams->GetDiagonalSquared(drive) - fsquare(A * dda.directionVector[Y_AXIS] - B * dda.directionVector[X_AXIS])))
- - aAplusbB)/params.a2plusb2;
- mp.delta.iReverseStartDistance = (int32_t)(drev * MoveSegment::Kdistance);
- if (drev > 0.0 && drev < dda.totalDistance) // if the reversal point is within range
- {
- // Calculate how many steps we need to move up before reversing
- const float hrev = dda.directionVector[Z_AXIS] * drev + fastSqrtf(dSquaredMinusAsquaredMinusBsquared - 2 * drev * aAplusbB - params.a2plusb2 * fsquare(drev));
- const int32_t numStepsUp = (int32_t)((hrev - mp.delta.h0MinusZ0) * stepsPerMm);
-
- // We may be almost at the peak height already, in which case we don't really have a reversal.
- if (numStepsUp < 1)
- {
- mp.delta.iReverseStartDistance = -1; // so that we know we have reversed already
- reverseStartStep = totalSteps + 1;
- direction = false;
- }
- else
- {
- reverseStartStep = (uint32_t)numStepsUp + 1;
-
- // Correct the initial direction and the total number of steps
- if (direction)
- {
- // Net movement is up, so we will go up first and then down by a lesser amount
- totalSteps = (2 * numStepsUp) - totalSteps;
- }
- else
- {
- // Net movement is down, so we will go up first and then down by a greater amount
- direction = true;
- totalSteps = (2 * numStepsUp) + totalSteps;
- }
- }
- }
- else
- {
- // No reversal
- reverseStartStep = totalSteps + 1;
- direction = (drev >= 0.0);
- }
- }
-
- iDistanceSoFar = 0;
- iTimeSoFar = 0;
-#endif
isDelta = true;
currentSegment = (dda.shapedSegments != nullptr) ? dda.shapedSegments : dda.unshapedSegments;
@@ -633,11 +418,19 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no
const float effStepsPerMm = stepsPerMm * fabsf(dda.directionVector[drive]);
const float effMmPerStep = 1.0/effStepsPerMm;
- ExtruderShaper& shaper = reprap.GetMove().GetExtruderShaper(LogicalDriveToExtruder(drive));
- float forwardDistance = mp.cart.extrusionBroughtForwards = shaper.GetExtrusionPending()/dda.directionVector[drive];
+ ExtruderShaper& shaper = reprap.GetMove().GetExtruderShaper(
+#if SUPPORT_REMOTE_COMMANDS
+ (dda.flags.isRemote) ? drive :
+#endif
+ LogicalDriveToExtruder(drive)
+ );
+ float forwardDistance = mp.cart.extrusionBroughtForwards =
+#if SUPPORT_REMOTE_COMMANDS
+ (dda.flags.isRemote) ? 0.0 :
+#endif
+ shaper.GetExtrusionPending()/dda.directionVector[drive];
float reverseDistance;
-#if MS_USE_FPU
mp.cart.effectiveStepsPerMm = effStepsPerMm;
mp.cart.effectiveMmPerStep = effMmPerStep;
distanceSoFar = forwardDistance;
@@ -741,71 +534,6 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no
forwardDistance += dda.totalDistance;
reverseDistance = 0.0;
}
-#else
- mp.cart.iEffectiveStepsPerMmTimesK = lrintf(effStepsPerMm * (float)(1u << MoveSegment::SFstepsPerMm));
- mp.cart.iEffectiveMmPerStepTimesK = lrintf(effMmPerStep * (float)(1u << MoveSegment::SFstepsPerMm));
- iTimeSoFar = 0;
-
- // Calculate the total forward and reverse movement distances
- //TODO distances as integer?
-
- if (dda.flags.usePressureAdvance && shaper.GetKclocks() > 0.0)
- {
- // We are using nonzero pressure advance. Movement must be forwards.
- mp.cart.iPressureAdvanceK = shaper.GetKclocks();
- const float extraExtrusionDistance = (float)mp.cart.iPressureAdvanceK * (dda.topSpeed - dda.startSpeed);
- mp.cart.iExtraExtrusionDistance = lrintf(extraExtrusionDistance * (float)(1u << MoveSegment::SFdistance));
- forwardDistance += extraExtrusionDistance;
-
- // Check if there is a reversal in the deceleration segment
- // There is at most one deceleration segment in the unshaped segments
- const MoveSegment *decelSeg = dda.unshapedSegments;
- while (decelSeg != nullptr && (decelSeg->IsLinear() || decelSeg->IsAccelerating()))
- {
- decelSeg = decelSeg->GetNext();
- }
-
- if (decelSeg == nullptr)
- {
- forwardDistance += dda.totalDistance; // no deceleration segment
- reverseDistance = 0.0;
- }
- else
- {
- const float initialDecelSpeed = dda.topSpeed - (float)mp.cart.iPressureAdvanceK * params.unshaped.deceleration;
- if (initialDecelSpeed <= 0.0)
- {
- // The entire deceleration segment is in reverse
- forwardDistance += params.unshaped.decelStartDistance;
- reverseDistance = ((0.5 * params.unshaped.deceleration * params.unshaped.decelClocks) - initialDecelSpeed) * params.unshaped.decelClocks;
- }
- else
- {
- const float timeToReverse = initialDecelSpeed * ((-0.5) * decelSeg->GetC()); // 'c' is -2/deceleration, so -0.5*c is 1/deceleration
- if (timeToReverse < params.unshaped.decelClocks)
- {
- // There is a reversal, although it could be tiny
- const float distanceToReverse = fsquare(initialDecelSpeed) * decelSeg->GetC() * (-0.25); // because (v^2-u^2) = 2as, so if v=0 then s=-u^2/2a = u^2/2d = -0.25*u^2*c
- forwardDistance += params.unshaped.decelStartDistance + distanceToReverse;
- reverseDistance = 0.5 * params.unshaped.deceleration * fsquare(params.unshaped.decelClocks - timeToReverse); // because s = 0.5*a*t^2
- }
- else
- {
- // No reversal
- forwardDistance += dda.totalDistance - ((float)mp.cart.iPressureAdvanceK * params.unshaped.deceleration * params.unshaped.decelClocks);
- reverseDistance = 0.0;
- }
- }
- }
- }
- else
- {
- // No pressure advance. Movement may be backwards but this still counts as forward distance in the calculations.
- mp.cart.iPressureAdvanceK = mp.cart.iExtraExtrusionDistance = 0;
- forwardDistance += dda.totalDistance;
- reverseDistance = 0.0;
- }
-#endif
// Check whether there are any steps at all
const float forwardSteps = forwardDistance * effStepsPerMm;
@@ -819,7 +547,12 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no
// No movement at all
nextStep = totalSteps = 0;
reverseStartStep = 1;
- shaper.SetExtrusionPending(netDistance * dda.directionVector[drive]);
+#if SUPPORT_REMOTE_COMMANDS
+ if (!dda.flags.isRemote)
+#endif
+ {
+ shaper.SetExtrusionPending(netDistance * dda.directionVector[drive]);
+ }
return false;
}
@@ -842,21 +575,36 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no
}
totalSteps = (uint32_t)((int32_t)(2 * reverseStartStep) - netSteps - 2);
}
- shaper.SetExtrusionPending((netDistance - (float)netSteps * effMmPerStep) * dda.directionVector[drive]);
+#if SUPPORT_REMOTE_COMMANDS
+ if (!dda.flags.isRemote)
+#endif
+ {
+ shaper.SetExtrusionPending((netDistance - (float)netSteps * effMmPerStep) * dda.directionVector[drive]);
+ }
}
else
{
if (forwardSteps >= 1.0)
{
totalSteps = (uint32_t)forwardSteps;
- shaper.SetExtrusionPending((forwardDistance - (float)totalSteps * effMmPerStep) * dda.directionVector[drive]);
+#if SUPPORT_REMOTE_COMMANDS
+ if (!dda.flags.isRemote)
+#endif
+ {
+ shaper.SetExtrusionPending((forwardDistance - (float)totalSteps * effMmPerStep) * dda.directionVector[drive]);
+ }
}
else
{
// No steps at all, or negative forward steps which I think should be impossible unless the steps/mm is changed
nextStep = totalSteps = 0;
reverseStartStep = 1;
- shaper.SetExtrusionPending(forwardDistance * dda.directionVector[drive]);
+#if SUPPORT_REMOTE_COMMANDS
+ if (!dda.flags.isRemote)
+#endif
+ {
+ shaper.SetExtrusionPending(forwardDistance * dda.directionVector[drive]);
+ }
return false;
}
reverseStartStep = totalSteps + 1; // no reverse phase
@@ -879,23 +627,12 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no
return CalcNextStepTime(dda);
}
-#if MS_USE_FPU
-
// Version of fastSqrtf that allows for slightly negative operands caused by rounding error
static inline float fastLimSqrtf(float f) noexcept
{
return (f > 0.0) ? fastSqrtf(f) : 0.0;
}
-#else
-
-static inline uint32_t LimISqrt64(int64_t num) noexcept
-{
- return (num <= 0) ? 0 : isqrt64((uint64_t)num);
-}
-
-#endif
-
// Calculate and store the time since the start of the move when the next step for the specified DriveMovement is due.
// We have already incremented nextStep and checked that it does not exceed totalSteps, so at least one more step is due
// Return true if all OK, false to abort this move because the calculation has gone wrong
@@ -962,39 +699,23 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0)
stepsTillRecalc = (1u << shiftFactor) - 1u; // store number of additional steps to generate
-#if MS_USE_FPU
float nextCalcStepTime;
-#else
- uint32_t iNextCalcStepTime;
-#endif
// Work out the time of the step
switch (state)
{
case DMState::cartLinear: // linear steady speed
-#if MS_USE_FPU
nextCalcStepTime = pB + (float)(nextStep + stepsTillRecalc) * pC;
-#else
- iNextCalcStepTime = iB + (nextStep + stepsTillRecalc) * iC; //TODO ??scaling factor for iC ?
-#endif
break;
case DMState::cartAccel: // Cartesian accelerating
-#if MS_USE_FPU
nextCalcStepTime = pB + fastLimSqrtf(pA + pC * (float)(nextStep + stepsTillRecalc));
-#else
- iNextCalcStepTime = iB + LimISqrt64(iA + iC * (nextStep + stepsTillRecalc)); //TODO ??scaling factor for iC ?
-#endif
break;
case DMState::cartDecelForwardsReversing:
if (nextStep + stepsTillRecalc < reverseStartStep)
{
-#if MS_USE_FPU
nextCalcStepTime = pB - fastLimSqrtf(pA + pC * (float)(nextStep + stepsTillRecalc));
-#else
- iNextCalcStepTime = iB - LimISqrt64(iA + iC * (nextStep + stepsTillRecalc)); //TODO ??scaling factor for iC ?
-#endif
break;
}
@@ -1003,19 +724,11 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0)
state = DMState::cartDecelReverse;
// no break
case DMState::cartDecelReverse: // Cartesian decelerating, reverse motion. Convert the steps to int32_t because the net steps may be negative.
-#if MS_USE_FPU
nextCalcStepTime = pB + fastLimSqrtf(pA + pC * (float)((2 * (int32_t)(reverseStartStep - 1)) - (int32_t)(nextStep + stepsTillRecalc)));
-#else
- iNextCalcStepTime = iB + LimISqrt64(iA + iC * ((2 * (int32_t)(reverseStartStep - 1)) - (int32_t)(nextStep + stepsTillRecalc))); //TODO ??scaling factor for iC ?
-#endif
break;
case DMState::cartDecelNoReverse: // Cartesian accelerating with no reversal
-#if MS_USE_FPU
nextCalcStepTime = pB - fastLimSqrtf(pA + pC * (float)(nextStep + stepsTillRecalc));
-#else
- iNextCalcStepTime = iB - LimISqrt64(iA + iC * (nextStep + stepsTillRecalc)); //TODO ??scaling factor for iC ?
-#endif
break;
case DMState::deltaForwardsReversing: // moving forwards
@@ -1029,7 +742,6 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0)
case DMState::deltaNormal:
// Calculate d*s where d = distance the head has travelled, s = steps/mm for this drive
{
-#if MS_USE_FPU
const float steps = (float)(1u << shiftFactor);
if (direction)
{
@@ -1060,35 +772,6 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0)
: (currentSegment->IsAccelerating()) ? pB + fastLimSqrtf(pA + pCds)
: pB - fastLimSqrtf(pA + pCds);
//if (currentSegment->IsLinear()) { pA = ds; } //DEBUG
-#else
- int32_t shiftedK2 = (int32_t)(MoveSegment::Kdelta << shiftFactor);
- if (!direction)
- {
- shiftedK2 = -shiftedK2;
- }
- mp.delta.hmz0sK += shiftedK2; // get K2 * (new carriage height above Z in steps)
-
- const int32_t hmz0scK = (int32_t)(((int64_t)mp.delta.hmz0sK * dda.afterPrepare.cKc) >> MoveSegment::SFdelta);
- const int32_t t1 = mp.delta.minusAaPlusBbTimesKs + hmz0scK;
- const int32_t t2a = (int32_t)(mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - (int64_t)isquare64(mp.delta.hmz0sK) + (int64_t)isquare64(t1));
- // Due to rounding error we can end up trying to take the square root of a negative number if we do not take precautions here
- const uint32_t t2 = LimISqrt64(t2a);
- const int32_t dsK = (direction) ? t1 - t2 : t1 + t2;
-
- // Now feed dsK into the step algorithm for Cartesian motion
- if (dsK < 0)
- {
- state = DMState::stepError;
- nextStep += 110000000; // so that we can tell what happened in the debug print
- return false;
- }
-
- const int32_t iCds = ((int64_t)iC * dsK) >> (MoveSegment::SFdelta + MoveSegment::SFdistance);
- iNextCalcStepTime = (currentSegment->IsLinear()) ? iB + iCds
- : (currentSegment->IsAccelerating()) ? iB + LimISqrt64(iA + iCds)
- : iB - LimISqrt64(iA + iCds);
- //if (currentSegment->IsLinear()) { iA = dsK; } //DEBUG
-#endif
}
break;
@@ -1106,9 +789,7 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0)
}
#endif
-#if MS_USE_FPU
uint32_t iNextCalcStepTime = (uint32_t)nextCalcStepTime;
-#endif
if (iNextCalcStepTime > dda.clocksNeeded)
{
diff --git a/src/Movement/DriveMovement.h b/src/Movement/DriveMovement.h
index 18e2eb38..814fde86 100644
--- a/src/Movement/DriveMovement.h
+++ b/src/Movement/DriveMovement.h
@@ -103,16 +103,9 @@ private:
uint32_t nextStepTime; // how many clocks after the start of this move the next step is due
uint32_t stepInterval; // how many clocks between steps
-#if MS_USE_FPU
float distanceSoFar;
float timeSoFar;
float pA, pB, pC;
-#else
- uint32_t iDistanceSoFar;
- uint32_t iTimeSoFar;
- int64_t iA;
- int32_t iB, iC;
-#endif
// Parameters unique to a style of move (Cartesian, delta or extruder). Currently, extruders and Cartesian moves use the same parameters.
union
@@ -123,32 +116,18 @@ private:
float fTwoA;
float fTwoB;
float h0MinusZ0; // the height subtended by the rod at the start of the move
-#if MS_USE_FPU
float fDSquaredMinusAsquaredMinusBsquaredTimesSsquared;
float fHmz0s; // the starting height less the starting Z height, multiplied by the Z movement fraction (can go negative)
float fMinusAaPlusBbTimesS;
float reverseStartDistance; // the overall move distance at which movement reversal occurs
-#else
- int64_t dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared;
- int32_t hmz0sK; // the starting step position less the starting Z height, multiplied by the Z movement fraction and K (can go negative)
- int32_t minusAaPlusBbTimesKs;
- int32_t iReverseStartDistance; // the overall move distance at which movement reversal occurs
-#endif
} delta;
struct CartesianParameters
{
-#if MS_USE_FPU
float pressureAdvanceK; // how much pressure advance is applied to this move
float effectiveStepsPerMm; // the steps/mm multiplied by the movement fraction
float effectiveMmPerStep; // reciprocal of [the steps/mm multiplied by the movement fraction]
float extraExtrusionDistance; // the extra extrusion distance in the acceleration phase
-#else
- uint32_t iPressureAdvanceK; // how much pressure advance is applied to this move
- uint32_t iEffectiveStepsPerMmTimesK; // the steps/mm multiplied by the movement fraction
- uint32_t iEffectiveMmPerStepTimesK; // reciprocal of [the steps/mm multiplied by the movement fraction]
- uint32_t iExtraExtrusionDistance; // the extra extrusion distance in the acceleration phase
-#endif
float extrusionBroughtForwards; // the amount of extrusion brought forwards from previous moves. Only needed for debug output.
} cart;
} mp;
diff --git a/src/Movement/ExtruderShaper.h b/src/Movement/ExtruderShaper.h
index 52a0431f..d0cd82cf 100644
--- a/src/Movement/ExtruderShaper.h
+++ b/src/Movement/ExtruderShaper.h
@@ -21,36 +21,20 @@ class ExtruderShaper
{
public:
ExtruderShaper()
-#if MS_USE_FPU
: k(0.0),
-#else
- : ik(0),
-#endif
extrusionPending(0.0) /*, lastSpeed(0.0)*/
{ }
// Temporary functions until we support more sophisticated pressure advance
-#if MS_USE_FPU
float GetKclocks() const noexcept { return k; } // get pressure advance in step clocks
float GetKseconds() const noexcept { return k * (1.0/StepClockRate); }
void SetKseconds(float val) noexcept { k = val * StepClockRate; } // set pressure advance in seconds
-#else
- uint32_t GetKclocks() const noexcept { return ik; } // get pressure advance in step clocks
- float GetKseconds() const noexcept { return (float)ik * (1.0/StepClockRate); }
- void SetKseconds(float val) noexcept { ik = lrintf(val * StepClockRate); } // set pressure advance in seconds
-#endif
float GetExtrusionPending() const noexcept { return extrusionPending; }
void SetExtrusionPending(float ep) noexcept { extrusionPending = ep; }
-#
-private:
-#if MS_USE_FPU
+private:
float k; // the pressure advance constant in step clocks
-#else
- uint32_t ik; // the pressure advance constant in step clocks
-#endif
float extrusionPending; // extrusion we have been asked to do but haven't because it is less than one microstep, in mm
-// float lastSpeed; // the speed we were moving at at the end of the last extrusion, needed to implement pressure advance
};
#endif /* SRC_MOVEMENT_EXTRUDERSHAPER_H_ */
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index 403f0a63..754f141e 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -1138,6 +1138,46 @@ GCodeResult Move::EutSetRemotePressureAdvance(const CanMessageMultipleDrivesRequ
return rslt;
}
+void Move::RevertPosition(const CanMessageRevertPosition& msg) noexcept
+{
+ // Construct a MovementLinear message to revert the position. The move must be shorter than clocksAllowed.
+ // When writing this, clocksAllowed was equivalent to 40ms.
+ // We allow 10ms delay time to allow the motor to stop and reverse direction, 10ms acceleration time, 5ms steady time and 10ms deceleration time.
+ CanMessageMovementLinear msg2;
+ msg2.accelerationClocks = msg2.decelClocks = msg.clocksAllowed/4;
+ msg2.steadyClocks = msg.clocksAllowed/8;
+ msg2.whenToExecute = StepTimer::GetMasterTime() + msg.clocksAllowed/4;
+ msg2.numDrivers = NumDirectDrivers;
+ msg2.pressureAdvanceDrives = 0;
+ msg2.seq = 0;
+ msg2.initialSpeedFraction = msg2.finalSpeedFraction = 0.0;
+
+ size_t index = 0;
+ bool needSteps = false;
+ const volatile int32_t * const lastMoveStepsTaken = rings[0].GetLastMoveStepsTaken();
+ constexpr size_t numDrivers = min<size_t>(NumDirectDrivers, MaxLinearDriversPerCanSlave);
+ for (size_t driver = 0; driver < numDrivers; ++driver)
+ {
+ int32_t steps = 0;
+ if (msg.whichDrives & (1u << driver))
+ {
+ const int32_t stepsWanted = msg.finalStepCounts[index++];
+ const int32_t stepsTaken = lastMoveStepsTaken[driver];
+ if (((stepsWanted >= 0 && stepsTaken > stepsWanted) || (stepsWanted <= 0 && stepsTaken < stepsWanted)))
+ {
+ steps = stepsWanted - stepsTaken;
+ needSteps = true;
+ }
+ }
+ msg2.perDrive[driver].steps = steps;
+ }
+
+ if (needSteps)
+ {
+ AddMoveFromRemote(msg2);
+ }
+}
+
#endif
// Return the current live XYZ and extruder coordinates
diff --git a/src/Movement/Move.h b/src/Movement/Move.h
index 6007f9d1..d16b3e7e 100644
--- a/src/Movement/Move.h
+++ b/src/Movement/Move.h
@@ -214,6 +214,13 @@ public:
MoveAvailable();
}
# endif
+
+ void StopDrivers(uint16_t whichDrives) noexcept
+ {
+ rings[0].StopDrivers(whichDrives);
+ }
+
+ void RevertPosition(const CanMessageRevertPosition& msg) noexcept;
#endif
protected:
diff --git a/src/Movement/MoveSegment.cpp b/src/Movement/MoveSegment.cpp
index ff8cf83b..11144801 100644
--- a/src/Movement/MoveSegment.cpp
+++ b/src/Movement/MoveSegment.cpp
@@ -50,7 +50,6 @@ void MoveSegment::AddToTail(MoveSegment *tail) noexcept
void MoveSegment::DebugPrint(char ch) const noexcept
{
-#if MS_USE_FPU
debugPrintf("%c d=%.4e t=%.1f ", ch, (double)segLength, (double)segTime);
if (IsLinear())
{
@@ -60,17 +59,6 @@ void MoveSegment::DebugPrint(char ch) const noexcept
{
debugPrintf("b=%.4e c=%.4e\n", (double)b, (double)c);
}
-#else
- debugPrintf("%c d=%" PRIu32 " t=%" PRIu32 " ", ch, iSegLength, iSegTime);
- if (IsLinear())
- {
- debugPrintf("c=%" PRIi32 "\n", ic);
- }
- else
- {
- debugPrintf("b=%" PRIi32 " c=%" PRIi32 "\n", ib, ic);
- }
-#endif
}
// End
diff --git a/src/Movement/MoveSegment.h b/src/Movement/MoveSegment.h
index a8ab7928..de089fab 100644
--- a/src/Movement/MoveSegment.h
+++ b/src/Movement/MoveSegment.h
@@ -134,9 +134,6 @@
#include <RepRapFirmware.h>
#include <Platform/Tasks.h>
-//#define MS_USE_FPU (__FPU_USED)
-#define MS_USE_FPU (1) // Try using floating point maths for processors without FPU too. We have implemented fastSqrtf on those processors.
-
class MoveSegment
{
public:
@@ -147,7 +144,6 @@ public:
MoveSegment(MoveSegment *p_next) noexcept;
-#if MS_USE_FPU
float GetSegmentLength() const noexcept { return segLength; }
float GetSegmentTime() const noexcept { return segTime; }
float CalcNonlinearA(float startDistance) const noexcept;
@@ -160,20 +156,6 @@ public:
void SetLinear(float pSegmentLength, float p_segTime, float p_c) noexcept;
void SetNonLinear(float pSegmentLength, float p_segTime, float p_b, float p_c) noexcept;
-#else
- uint32_t GetSegmentLength() const noexcept { return iSegLength; }
- uint32_t GetSegmentTime() const noexcept { return iSegTime; }
- int64_t CalcNonlinearA(uint32_t startDistance) const noexcept;
- int64_t CalcNonlinearA(uint32_t startDistance, uint32_t pressureAdvanceK) const noexcept;
- int32_t CalcNonlinearB(uint32_t startTime) const noexcept;
- int32_t CalcNonlinearB(uint32_t startTime, uint32_t pressureAdvanceK) const noexcept;
- int32_t CalcLinearB(uint32_t startDistance, uint32_t startTime) const noexcept;
- int32_t CalcC(uint32_t mmPerStepTimesK) const noexcept;
- int32_t GetC() const noexcept { return ic; }
-
- void SetLinear(uint32_t pSegmentLength, uint32_t p_segTime, int32_t p_c) noexcept;
- void SetNonLinear(uint32_t pSegmentLength, uint32_t p_segTime, int32_t p_b, int32_t p_c) noexcept;
-#endif
void SetReverse() noexcept;
MoveSegment *GetNext() const noexcept;
@@ -217,16 +199,9 @@ private:
// The 'next' field is a MoveSegment pointer with two flag bits in the bottom two bits
uint32_t nextAndFlags; // pointer to the next segment, plus flag bits
-#if MS_USE_FPU
float segLength; // the length of this segment before applying the movement fraction
float segTime; // the time in step clocks at which this move ends
float b, c; // the move parameters (b is not needed for linear moves)
-#else
- uint32_t iSegLength; // the length of this segment before applying the movement fraction
- uint32_t iSegTime; // the time in step clocks at which this move ends
- int32_t ib, ic; // the move parameters (b is not needed for linear moves)
-#endif
-
};
// Create a new one, leaving the flags clear
@@ -257,7 +232,6 @@ inline bool MoveSegment::IsLast() const noexcept
return GetNext() == nullptr;
}
-#if MS_USE_FPU
inline float MoveSegment::CalcNonlinearA(float startDistance) const noexcept
{
@@ -313,64 +287,6 @@ inline bool MoveSegment::IsAccelerating() const noexcept
return c > 0.0;
}
-#else
-
-inline int64_t MoveSegment::CalcNonlinearA(uint32_t startDistance) const noexcept
-{
- return isquare64(ib) - (int64_t)startDistance * ic;
-}
-
-inline int64_t MoveSegment::CalcNonlinearA(uint32_t startDistance, uint32_t pressureAdvanceK) const noexcept
-{
- return isquare64(ib - pressureAdvanceK) - (int64_t)startDistance * ic;
-}
-
-inline int32_t MoveSegment::CalcNonlinearB(uint32_t startTime) const noexcept
-{
- return ib + (int32_t)startTime;
-}
-
-inline int32_t MoveSegment::CalcNonlinearB(uint32_t startTime, uint32_t pressureAdvanceK) const noexcept
-{
- return (ib - (int32_t)pressureAdvanceK) + (int32_t)startTime;
-}
-
-inline int32_t MoveSegment::CalcLinearB(uint32_t startDistance, uint32_t startTime) const noexcept
-{
- return (int32_t)startTime - (((int64_t)startDistance * ic) >> SFdistance);
-}
-
-inline int32_t MoveSegment::CalcC(uint32_t mmPerStepTimesK) const noexcept
-{
- return (int32_t)((ic * (int64_t)mmPerStepTimesK) >> SFmmPerStep);
-}
-
-inline void MoveSegment::SetLinear(uint32_t pSegmentLength, uint32_t p_segTime, int32_t p_c) noexcept
-{
- iSegLength = pSegmentLength;
- iSegTime = p_segTime;
- ib = 0;
- ic = p_c;
- nextAndFlags |= LinearFlag;
-}
-
-// Set up an accelerating or decelerating move. We assume that the 'linear' flag is already clear.
-inline void MoveSegment::SetNonLinear(uint32_t pSegmentLength, uint32_t p_segTime, int32_t p_b, int32_t p_c) noexcept
-{
- iSegLength = pSegmentLength;
- iSegTime = p_segTime;
- ib = p_b;
- ic = p_c;
-}
-
-// Given that this is an accelerating or decelerating move, return true if it is accelerating
-inline bool MoveSegment::IsAccelerating() const noexcept
-{
- return ic > 0;
-}
-
-#endif
-
// Release a single MoveSegment. Not thread-safe.
inline void MoveSegment::Release(MoveSegment *item) noexcept
{
diff --git a/src/Platform/RepRap.cpp b/src/Platform/RepRap.cpp
index ae951908..43dafec1 100644
--- a/src/Platform/RepRap.cpp
+++ b/src/Platform/RepRap.cpp
@@ -792,8 +792,30 @@ void RepRap::Spin() noexcept
diagnosticsDestination = MessageType::NoDestinationMessage;
}
- // Check if we need to display a cold extrusion warning
const uint32_t now = millis();
+
+#if SUPPORT_REMOTE_COMMANDS
+ const DeferredCommand defCom = deferredCommand; // capture volatile variable
+ if (defCom != DeferredCommand::none && now - whenDeferredCommandScheduled >= 250)
+ {
+ switch (defCom)
+ {
+ case DeferredCommand::reboot:
+ SoftwareReset(SoftwareResetReason::user);
+ break;
+
+ case DeferredCommand::updateFirmware:
+ UpdateFirmware(IAP_CAN_LOADER_FILE, "");
+ break;
+
+ default:
+ deferredCommand = DeferredCommand::none;
+ break;
+ }
+ }
+#endif
+
+ // Check if we need to display a cold extrusion warning
if (now - lastWarningMillis >= MinimumWarningInterval)
{
ReadLocker lock(toolListLock);
@@ -958,44 +980,58 @@ void RepRap::Diagnostics(MessageType mtype) noexcept
justSentDiagnostics = true;
}
-// Turn off the heaters, disable the motors, and deactivate the Heat and Move classes. Leave everything else working.
+// Turn off the heaters, disable the motors, and deactivate the Heat, Move and GCodes classes. Leave everything else working.
void RepRap::EmergencyStop() noexcept
{
#ifdef DUET3_ATE
Duet3Ate::PowerOffEUT();
#endif
- stopped = true; // a useful side effect of setting this is that it prevents Platform::Tick being called, which is needed when loading IAP into RAM
+ stopped = true; // a useful side effect of setting this is that it prevents Platform::Tick being called, which is needed when loading IAP into RAM
// Do not turn off ATX power here. If the nozzles are still hot, don't risk melting any surrounding parts by turning fans off.
//platform->SetAtxPower(false);
- platform->DisableAllDrivers(); // need to do this to ensure that any motor brakes are re-engaged
-
- switch (gCodes->GetMachineType())
+#if SUPPORT_REMOTE_COMMANDS
+ if (CanInterface::InExpansionMode())
{
- case MachineType::cnc:
- for (size_t i = 0; i < MaxSpindles; i++)
+ platform->EmergencyDisableDrivers(); // disable all local drivers - need to do this to ensure that any motor brakes are re-engaged
+ }
+ else
+#endif
+ {
+ platform->DisableAllDrivers(); // disable all local and remote drivers - need to do this to ensure that any motor brakes are re-engaged
+
+ switch (gCodes->GetMachineType())
{
- platform->AccessSpindle(i).SetState(SpindleState::stopped);
- }
- break;
+ case MachineType::cnc:
+ for (size_t i = 0; i < MaxSpindles; i++)
+ {
+ platform->AccessSpindle(i).SetState(SpindleState::stopped);
+ }
+ break;
#if SUPPORT_LASER
- case MachineType::laser:
- platform->SetLaserPwm(0);
- break;
+ case MachineType::laser:
+ platform->SetLaserPwm(0);
+ break;
#endif
- default:
- break;
+ default:
+ break;
+ }
}
- heat->Exit(); // this also turns off all heaters
- move->Exit(); // this stops the motors stepping
+ heat->Exit(); // this also turns off all heaters
+ move->Exit(); // this stops the motors stepping
#if SUPPORT_CAN_EXPANSION
- expansion->EmergencyStop();
+# if SUPPORT_REMOTE_COMMANDS
+ if (!CanInterface::InExpansionMode())
+# endif
+ {
+ expansion->EmergencyStop();
+ }
#endif
gCodes->EmergencyStop();
@@ -2916,13 +2952,13 @@ bool RepRap::CheckFirmwareUpdatePrerequisites(const StringRef& reply, const Stri
}
// Update the firmware. Prerequisites should be checked before calling this.
-void RepRap::UpdateFirmware(const StringRef& filenameRef) noexcept
+void RepRap::UpdateFirmware(const char *iapFilename, const char *iapParam) noexcept
{
#if HAS_MASS_STORAGE
- FileStore * iapFile = platform->OpenFile(FIRMWARE_DIRECTORY, IAP_UPDATE_FILE, OpenMode::read);
+ FileStore * iapFile = platform->OpenFile(FIRMWARE_DIRECTORY, iapFilename, OpenMode::read);
if (iapFile == nullptr)
{
- iapFile = platform->OpenFile(DEFAULT_SYS_DIR, IAP_UPDATE_FILE, OpenMode::read);
+ iapFile = platform->OpenFile(DEFAULT_SYS_DIR, iapFilename, OpenMode::read);
if (iapFile == nullptr)
{
// This should not happen because we already checked that the file exists, so use a simplified error message
@@ -2936,7 +2972,7 @@ void RepRap::UpdateFirmware(const StringRef& filenameRef) noexcept
// Use RAM-based IAP
iapFile->Read(reinterpret_cast<char *>(IAP_IMAGE_START), iapFile->Length());
iapFile->Close();
- StartIap(filenameRef.c_str());
+ StartIap(iapParam);
#endif
}
diff --git a/src/Platform/RepRap.h b/src/Platform/RepRap.h
index b380bb51..49c6dfd6 100644
--- a/src/Platform/RepRap.h
+++ b/src/Platform/RepRap.h
@@ -61,7 +61,7 @@ public:
RepRap(const RepRap&) = delete;
void EmergencyStop() noexcept;
- void Init() noexcept;
+ void Init() noexcept;
void Spin() noexcept;
void Exit() noexcept;
void Diagnostics(MessageType mtype) noexcept;
@@ -134,6 +134,11 @@ public:
ExpansionManager& GetExpansion() const noexcept { return *expansion; }
#endif
+#if SUPPORT_REMOTE_COMMANDS
+ void ScheduleReset() noexcept { whenDeferredCommandScheduled = millis(); deferredCommand = DeferredCommand::reboot; }
+ void ScheduleFirmwareUpdateOverCan() noexcept { whenDeferredCommandScheduled = millis(); deferredCommand = DeferredCommand::updateFirmware; }
+#endif
+
void Tick() noexcept;
bool SpinTimeoutImminent() const noexcept;
bool IsStopped() const noexcept;
@@ -171,7 +176,7 @@ public:
// Firmware update operations
bool CheckFirmwareUpdatePrerequisites(const StringRef& reply, const StringRef& filenameRef) noexcept;
- void UpdateFirmware(const StringRef& filenameRef) noexcept;
+ void UpdateFirmware(const char *iapFilename, const char *iapParam) noexcept;
void PrepareToLoadIap() noexcept;
[[noreturn]] void StartIap(const char *filename) noexcept;
@@ -280,6 +285,12 @@ private:
uint16_t heatTaskIdleTicks;
uint32_t fastLoop, slowLoop;
+#if SUPPORT_REMOTE_COMMANDS
+ enum class DeferredCommand : uint8_t { none, reboot, updateFirmware };
+ volatile uint32_t whenDeferredCommandScheduled;
+ volatile DeferredCommand deferredCommand;
+#endif
+
DebugFlags debugMaps[Module::numModules];
String<RepRapPasswordLength> password;