diff options
author | David Crocker <dcrocker@eschertech.com> | 2021-09-24 20:04:56 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2021-09-24 20:04:56 +0300 |
commit | 1f96a9d2963e90e62211b7708885bf8757cbca10 (patch) | |
tree | 46b4a43578032d40b2aa5476420b9183248fba83 /src/Movement | |
parent | c006deccbb21f48c7ece8c496dfd492c2ba739a2 (diff) |
Fixed wonky delta prints, also added a new simulation mode
Diffstat (limited to 'src/Movement')
-rw-r--r-- | src/Movement/DDA.cpp | 64 | ||||
-rw-r--r-- | src/Movement/DDA.h | 3 | ||||
-rw-r--r-- | src/Movement/DDARing.cpp | 26 | ||||
-rw-r--r-- | src/Movement/DDARing.h | 4 | ||||
-rw-r--r-- | src/Movement/DriveMovement.cpp | 134 | ||||
-rw-r--r-- | src/Movement/DriveMovement.h | 5 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 10 | ||||
-rw-r--r-- | src/Movement/Move.h | 6 |
8 files changed, 195 insertions, 57 deletions
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index e743de84..96e05715 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -1279,7 +1279,7 @@ void DDA::EnsureUnshapedSegments(const PrepParams& params) noexcept // Prepare this DDA for execution. // This must not be called with interrupts disabled, because it calls Platform::EnableDrive. -void DDA::Prepare(uint8_t simMode) noexcept +void DDA::Prepare(SimulationMode simMode) noexcept { flags.wasAccelOnlyMove = IsAccelerationMove(); // save this for the next move to look at @@ -1311,7 +1311,7 @@ void DDA::Prepare(uint8_t simMode) noexcept acceleration = params.unshaped.acceleration; deceleration = params.unshaped.deceleration; - if (simMode == 0) + if (simMode < SimulationMode::normal) { if (flags.isDeltaMovement) { @@ -1611,7 +1611,7 @@ void DDA::Prepare(uint8_t simMode) noexcept } #if SUPPORT_CAN_EXPANSION - const uint32_t canClocksNeeded = CanMotion::FinishMovement(afterPrepare.moveStartTime); + const uint32_t canClocksNeeded = CanMotion::FinishMovement(afterPrepare.moveStartTime, simMode != SimulationMode::off); if (canClocksNeeded > clocksNeeded) { // Due to rounding error in the calculations, we quite often calculate the CAN move as being longer than our previously-calculated value, normally by just one clock. @@ -2116,6 +2116,64 @@ void DDA::StepDrivers(Platform& p, uint32_t now) noexcept } } +// Simulate stepping the drivers, for debugging. +// This is basically a copy of DDA::SetDrivers except that instead of being called from the timer ISR and generating steps, +// it is called from the Move task and outputs info on the step timings. It ignores endstops. +void DDA::SimulateSteppingDrivers(Platform& p) noexcept +{ + static uint32_t lastStepTime; + static bool checkTiming = false; + + DriveMovement* dm = activeDMs; + if (dm != nullptr) + { + const uint32_t dueTime = dm->nextStepTime; + while (dm != nullptr && dueTime >= dm->nextStepTime) // if the next step is due + { + const uint32_t timeDiff = dm->nextStepTime - lastStepTime; + const bool badTiming = checkTiming && (timeDiff < 10 || timeDiff > 100000000); + debugPrintf("%10" PRIu32 " D%u %c%s", dm->nextStepTime, dm->drive, (dm->direction) ? 'F' : 'B', (badTiming) ? " *\n" : "\n"); + dm = dm->nextDM; + } + lastStepTime = dueTime; + checkTiming = true; + + for (DriveMovement *dm2 = activeDMs; dm2 != dm; dm2 = dm2->nextDM) + { + (void)dm2->CalcNextStepTime(*this); // calculate next step times + } + + // Remove those drives from the list, update the direction pins where necessary, and re-insert them so as to keep the list in step-time order. + DriveMovement *dmToInsert = activeDMs; // head of the chain we need to re-insert + activeDMs = dm; // remove the chain from the list + while (dmToInsert != dm) // note that both of these may be nullptr + { + DriveMovement * const nextToInsert = dmToInsert->nextDM; + if (dmToInsert->state >= DMState::firstMotionState) + { + InsertDM(dmToInsert); + if (dmToInsert->directionChanged) + { + dmToInsert->directionChanged = false; + } + } + else + { + dmToInsert->nextDM = completedDMs; + completedDMs = dmToInsert; + } + dmToInsert = nextToInsert; + } + } + + // If there are no more steps to do and the time for the move has nearly expired, flag the move as complete + if (activeDMs == nullptr) + { + checkTiming = false; // don't check the timing of the first step in the next move + state = completed; + } +} + // Stop a drive and re-calculate the corresponding endpoint. // For extruder drivers, we need to be able to calculate how much of the extrusion was completed after calling this. void DDA::StopDrive(size_t drive) noexcept diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h index 66019a35..2c693d98 100644 --- a/src/Movement/DDA.h +++ b/src/Movement/DDA.h @@ -98,13 +98,14 @@ public: void Start(Platform& p, uint32_t tim) noexcept SPEED_CRITICAL; // Start executing the DDA, i.e. move the move. void StepDrivers(Platform& p, uint32_t now) noexcept SPEED_CRITICAL; // Take one step of the DDA, called by timer interrupt. + void SimulateSteppingDrivers(Platform& p) noexcept; // For debugging use bool ScheduleNextStepInterrupt(StepTimer& timer) const noexcept SPEED_CRITICAL; // Schedule the next interrupt, returning true if we can't because it is already due void SetNext(DDA *n) noexcept { next = n; } void SetPrevious(DDA *p) noexcept { prev = p; } void Complete() noexcept { state = completed; } bool Free() noexcept; - void Prepare(uint8_t simMode) noexcept SPEED_CRITICAL; // Calculate all the values and freeze this DDA + void Prepare(SimulationMode simMode) noexcept SPEED_CRITICAL; // Calculate all the values and freeze this DDA bool HasStepError() const noexcept; bool CanPauseAfter() const noexcept; bool IsPrintingMove() const noexcept { return flags.isPrintingMove; } // Return true if this involves both XY movement and extrusion diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp index e8de24e4..cc8af5b0 100644 --- a/src/Movement/DDARing.cpp +++ b/src/Movement/DDARing.cpp @@ -262,16 +262,26 @@ bool DDARing::AddAsyncMove(const AsyncMove& nextMove) noexcept // Try to process moves in the ring. Called by the Move task. // Return the maximum time in milliseconds that should elapse before we prepare further unprepared moves that are already in the ring, or TaskBase::TimeoutUnlimited if there are no unprepared moves left. -uint32_t DDARing::Spin(uint8_t simulationMode, bool waitingForSpace, bool shouldStartMove) noexcept +uint32_t DDARing::Spin(SimulationMode simulationMode, bool waitingForSpace, bool shouldStartMove) noexcept { DDA *cdda = currentDda; // capture volatile variable // If we are simulating, simulate completion of the current move. // Do this here rather than at the end, so that when simulating, currentDda is non-null for most of the time and IsExtruding() returns the correct value - if (simulationMode != 0 && cdda != nullptr) + if (simulationMode != SimulationMode::off && cdda != nullptr) { simulationTime += (float)cdda->GetClocksNeeded() * (1.0/StepClockRate); - cdda->Complete(); + if (simulationMode == SimulationMode::debug && reprap.Debug(moduleDda)) + { + do + { + cdda->SimulateSteppingDrivers(reprap.GetPlatform()); + } while (cdda->GetState() != DDA::completed); + } + else + { + cdda->Complete(); + } CurrentMoveCompleted(); // this sets currentDda to nullptr and advances getPointer DDA * const gp = getPointer; // capture volatile variable if (gp->GetState() == DDA::frozen) @@ -300,14 +310,14 @@ uint32_t DDARing::Spin(uint8_t simulationMode, bool waitingForSpace, bool should cdda = cdda->GetNext(); if (cdda == addPointer) { - return (simulationMode == 0) + return (simulationMode == SimulationMode::off) ? TaskBase::TimeoutUnlimited // all the moves we have are already prepared, so nothing to do until new moves arrive : 0; } } uint32_t ret = PrepareMoves(cdda, preparedTime, preparedCount, simulationMode); - if (simulationMode != 0) + if (simulationMode >= SimulationMode::normal) { return 0; } @@ -345,7 +355,7 @@ uint32_t DDARing::Spin(uint8_t simulationMode, bool waitingForSpace, bool should } else if (dda->GetState() == DDA::frozen) { - if (simulationMode != 0) + if (simulationMode != SimulationMode::off) { currentDda = dda; // pretend we are executing this move return 0; // we don't want any delay because we want Spin() to be called again soon to complete this move @@ -392,7 +402,7 @@ uint32_t DDARing::Spin(uint8_t simulationMode, bool waitingForSpace, bool should // Prepare some moves. moveTimeLeft is the total length remaining of moves that are already executing or prepared. // Return the maximum time in milliseconds that should elapse before we prepare further unprepared moves that are already in the ring, or TaskBase::TimeoutUnlimited if there are no unprepared moves left. -uint32_t DDARing::PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, unsigned int alreadyPrepared, uint8_t simulationMode) noexcept +uint32_t DDARing::PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, unsigned int alreadyPrepared, SimulationMode simulationMode) noexcept { // If the number of prepared moves will execute in less than the minimum time, prepare another move. // Try to avoid preparing deceleration-only moves too early @@ -415,7 +425,7 @@ uint32_t DDARing::PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, u if (firstUnpreparedMove->GetState() == DDA::provisional) { // There are more moves waiting to be prepared, so ask to be woken up early - if (simulationMode != 0) + if (simulationMode != SimulationMode::off) { return 1; } diff --git a/src/Movement/DDARing.h b/src/Movement/DDARing.h index 9183db40..1bae00c8 100644 --- a/src/Movement/DDARing.h +++ b/src/Movement/DDARing.h @@ -29,7 +29,7 @@ public: bool AddAsyncMove(const AsyncMove& nextMove) noexcept; #endif - uint32_t Spin(uint8_t simulationMode, bool waitingForSpace, bool shouldStartMove) noexcept SPEED_CRITICAL; // Try to process moves in the ring + uint32_t Spin(SimulationMode simulationMode, bool waitingForSpace, bool shouldStartMove) noexcept SPEED_CRITICAL; // Try to process moves in the ring bool IsIdle() const noexcept; // Return true if this DDA ring is idle uint32_t GetGracePeriod() const noexcept { return gracePeriod; } // Return the minimum idle time, before we should start a move. Better to have a few moves in the queue so that we can do lookahead @@ -99,7 +99,7 @@ protected: private: bool StartNextMove(Platform& p, uint32_t startTime) noexcept SPEED_CRITICAL; // Start the next move, returning true if laser or IObits need to be controlled - uint32_t PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, unsigned int alreadyPrepared, uint8_t simulationMode) noexcept; + uint32_t PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, unsigned int alreadyPrepared, SimulationMode simulationMode) noexcept; static void TimerCallback(CallbackParameter p) noexcept; diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp index f00c1624..0b316ef0 100644 --- a/src/Movement/DriveMovement.cpp +++ b/src/Movement/DriveMovement.cpp @@ -197,40 +197,60 @@ bool DriveMovement::NewDeltaSegment(const DDA& dda) noexcept pB = currentSegment->CalcNonlinearB(timeSoFar); } - const float startDistance = distanceSoFar; distanceSoFar += currentSegment->GetSegmentLength(); timeSoFar += currentSegment->GetSegmentTime(); - // Work out whether we reverse in this segment and the movement limit in steps - const float sDx = distanceSoFar * dda.directionVector[0]; - const float sDy = distanceSoFar * dda.directionVector[1]; - const int32_t netStepsAtEnd = (int32_t)(fastSqrtf(mp.delta.fDSquaredMinusAsquaredMinusBsquaredTimesSsquared - fsquare(stepsPerMm) * (sDx * (sDx + mp.delta.fTwoA) + sDy * (sDy + mp.delta.fTwoB))) - + (distanceSoFar * dda.directionVector[2] - mp.delta.h0MinusZ0) * stepsPerMm); - - if (mp.delta.reverseStartDistance <= startDistance) + // Work out whether we reverse in this segment and the movement limit in steps. + // First check whether the first step in this segment is the previously-calculated reverse start step, and if so then do the reversal. + if (nextStep == reverseStartStep) { - // 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; - phaseStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 - : (reverseStartStep <= totalSteps) ? (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd) - : 1 - netStepsAtEnd; + direction = false; // we must have been going up, so now we are going down + directionChanged = true; } - else if (distanceSoFar <= mp.delta.reverseStartDistance) + + if (currentSegment->GetNext() == nullptr) { - // This segment is purely upwards motion of the tower and we want the lower quadratic solution - state = DMState::deltaForwardsNoReverse; - phaseStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)(netStepsAtEnd + 1); + // This is the last segment, so the phase step limit is the number of total steps, and we can avoid some calculation + phaseStepLimit = totalSteps + 1; + state = (reverseStartStep <= totalSteps && nextStep < reverseStartStep) ? DMState::deltaForwardsReversing : DMState::deltaNormal; } else { - // This segment ends with reverse motion. We want the lower quadratic solution initially. - phaseStepLimit = (currentSegment->GetNext() == nullptr) ? totalSteps + 1 : (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd); - state = DMState::deltaForwardsReversing; + // Work out how many whole steps we have moved up or down at the end of this segment + const float sDx = distanceSoFar * dda.directionVector[0]; + const float sDy = distanceSoFar * dda.directionVector[1]; + int32_t netStepsAtEnd = (int32_t)floor(fastSqrtf(mp.delta.fDSquaredMinusAsquaredMinusBsquaredTimesSsquared - fsquare(stepsPerMm) * (sDx * (sDx + mp.delta.fTwoA) + sDy * (sDy + mp.delta.fTwoB))) + + (distanceSoFar * dda.directionVector[2] - mp.delta.h0MinusZ0) * stepsPerMm); + + if (nextStep >= reverseStartStep) + { + // We have already reversed, so this segment is purely downwards motion + state = DMState::deltaNormal; + phaseStepLimit = (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd); + } + else + { + // If there is a reversal then we only ever move up by (reverseStartStep - 1) steps, so netStepsAtEnd should be less than reverseStartStep. + // However, because of rounding error, it might possibly be equal. + // If there is no reversal then reverseStartStep is set to totalSteps + 1, so netStepsAtEnd must again be less than reverseStartStep. + if (netStepsAtEnd >= (int32_t)reverseStartStep) + { + netStepsAtEnd = (int32_t)(reverseStartStep - 1); // correct the rounding error - we know that reverseStartStep cannot be 0 so subtracting 1 is safe + } + + if (distanceSoFar <= mp.delta.reverseStartDistance) + { + // This segment is purely upwards motion of the tower + state = DMState::deltaNormal; + phaseStepLimit = (uint32_t)(netStepsAtEnd + 1); + } + else + { + // This segment ends with reverse motion + phaseStepLimit = (uint32_t)((int32_t)(2 * reverseStartStep) - netStepsAtEnd); + state = DMState::deltaForwardsReversing; + } + } } #else iC = currentSegment->GetC()/stepsPerMm; //TODO store the reciprocal to avoid the division? Use a scaling factor for C @@ -306,7 +326,6 @@ bool DriveMovement::NewExtruderSegment() noexcept const float startDistance = distanceSoFar; const float startTime = timeSoFar; - // Work out the movement limit in steps distanceSoFar += currentSegment->GetSegmentLength(); timeSoFar += currentSegment->GetSegmentTime(); @@ -331,10 +350,11 @@ bool DriveMovement::NewExtruderSegment() noexcept 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 + state = (reverseStartStep <= totalSteps) ? DMState::cartDecelForwardsReversing : DMState::cartDecelNoReverse; } } + // Work out the movement limit in steps phaseStepLimit = ((currentSegment->GetNext() == nullptr) ? totalSteps : (uint32_t)(distanceSoFar * mp.cart.effectiveStepsPerMm)) + 1; #else const uint32_t startDistance = iDistanceSoFar; @@ -464,6 +484,15 @@ bool DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) n reverseStartStep = totalSteps + 1; direction = false; } + else if (direction && (uint32_t)numStepsUp <= totalSteps) + { + // If numStepsUp == totalSteps then the reverse segment is too small to do. + // If numStepsUp < totalDteps then there has been a rounding error, because we are supposed to move up more than the calculated number of steps we move up. + // This can happen if the calculated reversal is very close to the end of the move, because we round the final step positions to the nearest step, which may be up. + // Either way, don't do a reverse segment. + reverseStartStep = totalSteps + 1; + mp.delta.reverseStartDistance = dda.totalDistance + 1.0; + } else { reverseStartStep = (uint32_t)numStepsUp + 1; @@ -472,13 +501,13 @@ bool DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params) n if (direction) { // Net movement is up, so we will go up first and then down by a lesser amount - totalSteps = (2 * numStepsUp) - totalSteps; + totalSteps = (2 * (uint32_t)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; + totalSteps = (2 * (uint32_t)numStepsUp) + totalSteps; } } } @@ -601,6 +630,47 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no mp.cart.extraExtrusionDistance = mp.cart.pressureAdvanceK * (dda.topSpeed - dda.startSpeed); forwardDistance += mp.cart.extraExtrusionDistance; +# if 0 //SHAPE_EXTRUSION + forwardDistance += params.shaped.decelStartDistance; + reverseDistance = 0.0; + + // Find the deceleration segments + const MoveSegment *decelSeg = dda.unshapedSegments; + while (decelSeg != nullptr && (decelSeg->IsLinear() || decelSeg->IsAccelerating())) + { + decelSeg = decelSeg->GetNext(); + } + + float lastUncorrectedSpeed = dda.topSpeed; + float lastDistance = forwardDistance; + while (decelSeg != nullptr) + { + const float initialDecelSpeed = lastUncorrectedSpeed - mp.cart.pressureAdvanceK * decelSeg->deceleration; + if (initialDecelSpeed <= 0.0) + { + // This entire deceleration segment is in reverse + 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 - (mp.cart.pressureAdvanceK * params.unshaped.deceleration * params.unshaped.decelClocks); + reverseDistance = 0.0; + } + } + + } +# else // 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; @@ -641,6 +711,7 @@ bool DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params) no } } } +# endif } else { @@ -914,11 +985,10 @@ pre(nextStep <= totalSteps; stepsTillRecalc == 0) { direction = false; directionChanged = true; - state = DMState::deltaReverse; + state = DMState::deltaNormal; } // no break - case DMState::deltaForwardsNoReverse: - case DMState::deltaReverse: // reversing on this and subsequent steps + case DMState::deltaNormal: // Calculate d*s where d = distance the head has travelled, s = steps/mm for this drive { #if MS_USE_FPU diff --git a/src/Movement/DriveMovement.h b/src/Movement/DriveMovement.h index 8b24ecc1..5e4084ba 100644 --- a/src/Movement/DriveMovement.h +++ b/src/Movement/DriveMovement.h @@ -31,9 +31,8 @@ enum class DMState : uint8_t cartDecelForwardsReversing, // linear decelerating motion, expect reversal cartDecelReverse, // linear decelerating motion, reversed - deltaForwardsNoReverse, // moving forwards, no reversal in this segment - deltaForwardsReversing, // moving forwards but reversing in this segment - deltaReverse, // moving in reverse + deltaNormal, // moving forwards without reversing in this segment, or in reverse + deltaForwardsReversing, // moving forwards to start with, reversing before the end of this segment }; // This class describes a single movement of one drive diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index d034b61e..72ef43fa 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -200,7 +200,7 @@ void Move::Init() noexcept moveState = MoveState::idle; whenLastMoveAdded = whenIdleTimerStarted = millis(); - simulationMode = 0; + simulationMode = SimulationMode::off; longestGcodeWaitInterval = 0; bedLevellingMoveAvailable = false; @@ -240,7 +240,7 @@ void Move::Exit() noexcept if (bedLevellingMoveAvailable) { moveRead = true; - if (simulationMode < 2) + if (simulationMode < SimulationMode::partial) { if (mainDDARing.AddSpecialMove(reprap.GetPlatform().MaxFeedrate(Z_AXIS), specialMoveCoords)) { @@ -263,7 +263,7 @@ void Move::Exit() noexcept if (reprap.GetGCodes().ReadMove(nextMove)) // if we have a new move { moveRead = true; - if (simulationMode < 2) // in simulation mode 2 and higher, we don't process incoming moves beyond this point + if (simulationMode < SimulationMode::partial) // in simulation mode partial, we don't process incoming moves beyond this point { if (nextMove.moveType == 0) { @@ -916,10 +916,10 @@ float Move::GetProbeCoordinates(int count, float& x, float& y, bool wantNozzlePo } // Enter or leave simulation mode -void Move::Simulate(uint8_t simMode) noexcept +void Move::Simulate(SimulationMode simMode) noexcept { simulationMode = simMode; - if (simMode != 0) + if (simMode != SimulationMode::off) { mainDDARing.ResetSimulationTime(); } diff --git a/src/Movement/Move.h b/src/Movement/Move.h index b5583bb0..6eee76f2 100644 --- a/src/Movement/Move.h +++ b/src/Movement/Move.h @@ -129,7 +129,7 @@ public: float IdleTimeout() const noexcept; // Returns the idle timeout in seconds void SetIdleTimeout(float timeout) noexcept; // Set the idle timeout in seconds - void Simulate(uint8_t simMode) noexcept; // Enter or leave simulation mode + void Simulate(SimulationMode simMode) noexcept; // Enter or leave simulation mode float GetSimulationTime() const noexcept { return mainDDARing.GetSimulationTime(); } // Get the accumulated simulation time bool PausePrint(RestorePoint& rp) noexcept; // Pause the print as soon as we can, returning true if we were able to @@ -257,7 +257,7 @@ private: DDARing& mainDDARing = rings[0]; // The DDA ring used for regular moves - uint8_t simulationMode; // Are we simulating, or really printing? + SimulationMode simulationMode; // Are we simulating, or really printing? MoveState moveState; // whether the idle timer is active float maxPrintingAcceleration; @@ -345,7 +345,7 @@ inline float Move::GetPressureAdvanceClocks(size_t extruder) const noexcept // This is called from the stepper drivers SPI interface ISR inline __attribute__((always_inline)) uint32_t Move::GetStepInterval(size_t axis, uint32_t microstepShift) const noexcept { - return (simulationMode == 0) ? mainDDARing.GetStepInterval(axis, microstepShift) : 0; + return (simulationMode == SimulationMode::off) ? mainDDARing.GetStepInterval(axis, microstepShift) : 0; } #endif |