diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CAN/CommandProcessor.cpp | 55 | ||||
-rw-r--r-- | src/Config/Pins_Duet3Mini.h | 1 | ||||
-rw-r--r-- | src/Config/Pins_Duet3_MB6HC.h | 1 | ||||
-rw-r--r-- | src/Config/Pins_Duet3_MB6XD.h | 1 | ||||
-rw-r--r-- | src/GCodes/GCodes4.cpp | 4 | ||||
-rw-r--r-- | src/Movement/DDA.cpp | 136 | ||||
-rw-r--r-- | src/Movement/DDA.h | 5 | ||||
-rw-r--r-- | src/Movement/DDARing.cpp | 23 | ||||
-rw-r--r-- | src/Movement/DDARing.h | 8 | ||||
-rw-r--r-- | src/Movement/DriveMovement.cpp | 389 | ||||
-rw-r--r-- | src/Movement/DriveMovement.h | 21 | ||||
-rw-r--r-- | src/Movement/ExtruderShaper.h | 18 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 40 | ||||
-rw-r--r-- | src/Movement/Move.h | 7 | ||||
-rw-r--r-- | src/Movement/MoveSegment.cpp | 12 | ||||
-rw-r--r-- | src/Movement/MoveSegment.h | 84 | ||||
-rw-r--r-- | src/Platform/RepRap.cpp | 82 | ||||
-rw-r--r-- | src/Platform/RepRap.h | 15 |
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; |