diff options
author | David Crocker <dcrocker@eschertech.com> | 2019-11-29 17:04:18 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2019-11-29 17:04:18 +0300 |
commit | 847fcb466e678dafa7aa7cd70a10d3cff64b29c5 (patch) | |
tree | 1184d0603ae438a3b889510190c2290758e6b043 | |
parent | 20fa72e37b36bcd124f037361d01616b78896e92 (diff) |
Minor tidy-up
-rw-r--r-- | src/Movement/Move.cpp | 282 |
1 files changed, 70 insertions, 212 deletions
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index 705fb87a..b421e3e2 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -36,13 +36,11 @@ #include "Move.h" #include "StepTimer.h" #include "Platform.h" -#include "GCodes/GCodeBuffer/GCodeBuffer.h" +#include "GCodes/GCodeBuffer.h" #include "Tools/Tool.h" -#include "Endstops/ZProbe.h" -#include <TaskPriorities.h> #if SUPPORT_CAN_EXPANSION -# include "CAN/CanMotion.h" +# include "CAN/CanInterface.h" #endif #if SUPPORT_OBJECT_MODEL @@ -79,9 +77,6 @@ Move::Move() // Kinematics must be set up here because GCodes::Init asks the kinematics for the assumed initial position kinematics = Kinematics::Create(KinematicsType::cartesian); // default to Cartesian mainDDARing.Init1(DdaRingLength); -#if SUPPORT_ASYNC_MOVES - auxDDARing.Init1(AuxDdaRingLength); -#endif DriveMovement::InitialAllocate(NumDms); } @@ -89,12 +84,6 @@ void Move::Init() { mainDDARing.Init2(); -#if SUPPORT_ASYNC_MOVES - auxDDARing.Init2(); - auxMoveAvailable = false; - auxMoveLocked = false; -#endif - // Clear the transforms SetIdentityTransform(); tanXY = tanYZ = tanXZ = 0.0; @@ -110,6 +99,7 @@ void Move::Init() simulationMode = 0; longestGcodeWaitInterval = 0; + numHiccups = 0; bedLevellingMoveAvailable = false; active = true; @@ -117,7 +107,7 @@ void Move::Init() void Move::Exit() { - StepTimer::DisableTimerInterrupt(); + StepTimer::DisableStepInterrupt(); mainDDARing.Exit(); active = false; // don't accept any more moves } @@ -126,7 +116,7 @@ void Move::Spin() { if (!active) { - RawMove nextMove; + GCodes::RawMove nextMove; (void) reprap.GetGCodes().ReadMove(nextMove); // throw away any move that GCodes tries to pass us return; } @@ -138,9 +128,6 @@ void Move::Spin() // Recycle the DDAs for completed moves, checking for DDA errors to print if Move debug is enabled mainDDARing.RecycleDDAs(); -#if SUPPORT_ASYNC_MOVES - auxDDARing.RecycleDDAs(); -#endif // See if we can add another move to the ring bool canAddMove = ( @@ -177,7 +164,7 @@ void Move::Spin() else { // If there's a G Code move available, add it to the DDA ring for processing. - RawMove nextMove; + GCodes::RawMove nextMove; if (reprap.GetGCodes().ReadMove(nextMove)) // if we have a new move { if (simulationMode < 2) // in simulation mode 2 and higher, we don't process incoming moves beyond this point @@ -209,24 +196,8 @@ void Move::Spin() mainDDARing.Spin(simulationMode, idleCount > 10); // let the DDA ring process moves. Better to have a few moves in the queue so that we can do lookahead, hence the test on idleCount. -#if SUPPORT_ASYNC_MOVES - if (auxMoveAvailable && auxDDARing.CanAddMove()) - { - if (auxDDARing.AddAsyncMove(auxMove)) - { - moveState = MoveState::collecting; - } - auxMoveAvailable = false; - } - auxDDARing.Spin(simulationMode, true); // let the DDA ring process moves -#endif - // Reduce motor current to standby if the rings have been idle for long enough - if ( mainDDARing.IsIdle() -#if SUPPORT_ASYNC_MOVES - && auxDDARing.IsIdle() -#endif - ) + if (mainDDARing.IsIdle()) { if (moveState == MoveState::executing && !reprap.GetGCodes().IsPaused()) { @@ -251,12 +222,6 @@ unsigned int Move::GetNumProbePoints() const return probePoints.GetNumBedCompensationPoints(); } -// Return the number of actually probed probe points -unsigned int Move::GetNumProbedProbePoints() const -{ - return probePoints.NumberOfProbePoints(); -} - // Try to push some babystepping through the lookahead queue, returning the amount pushed float Move::PushBabyStepping(size_t axis, float amount) { @@ -291,8 +256,8 @@ bool Move::IsRawMotorMove(uint8_t moveType) const // Return true if the specified point is accessible to the Z probe bool Move::IsAccessibleProbePoint(float x, float y) const { - const ZProbe& params = reprap.GetPlatform().GetCurrentZProbe(); - return kinematics->IsReachable(x - params.GetXOffset(), y - params.GetYOffset(), false); + const ZProbe& params = reprap.GetPlatform().GetCurrentZProbeParameters(); + return kinematics->IsReachable(x - params.xOffset, y - params.yOffset, false); } // Pause the print as soon as we can, returning true if we are able to skip any moves and updating 'rp' to the first move we skipped. @@ -314,16 +279,9 @@ bool Move::LowPowerOrStallPause(RestorePoint& rp) void Move::Diagnostics(MessageType mtype) { Platform& p = reprap.GetPlatform(); - p.MessageF(mtype, "=== Move ===\nHiccups: %" PRIu32 -#if SUPPORT_ASYNC_MOVES - "(%" PRIu32 ")" -#endif - ", FreeDm: %d, MinFreeDm: %d, MaxWait: %" PRIu32 "ms\n", - mainDDARing.GetClearNumHiccups(), -#if SUPPORT_ASYNC_MOVES - auxDDARing.GetClearNumHiccups(), -#endif - DriveMovement::NumFree(), DriveMovement::MinFree(), longestGcodeWaitInterval); + p.MessageF(mtype, "=== Move ===\nHiccups: %" PRIu32 ", FreeDm: %d, MinFreeDm: %d, MaxWait: %" PRIu32 "ms\n", + numHiccups, DriveMovement::NumFree(), DriveMovement::MinFree(), longestGcodeWaitInterval); + numHiccups = 0; longestGcodeWaitInterval = 0; DriveMovement::ResetMinFree(); @@ -333,7 +291,7 @@ void Move::Diagnostics(MessageType mtype) #endif // Show the current probe position heights and type of bed compensation in use - String<StringLength50> bedCompString; + String<StringLength40> bedCompString; if (usingMesh) { bedCompString.copy("mesh"); @@ -374,18 +332,13 @@ void Move::Diagnostics(MessageType mtype) p.Message(mtype, "\n"); #endif -#if SUPPORT_ASYNC_MOVES - mainDDARing.Diagnostics(mtype, "Main"); - auxDDARing.Diagnostics(mtype, "Aux"); -#else mainDDARing.Diagnostics(mtype, ""); -#endif } // Set the current position to be this -void Move::SetNewPosition(const float positionNow[MaxAxesPlusExtruders], bool doBedCompensation) +void Move::SetNewPosition(const float positionNow[MaxTotalDrivers], bool doBedCompensation) { - float newPos[MaxAxesPlusExtruders]; + float newPos[MaxTotalDrivers]; memcpy(newPos, positionNow, sizeof(newPos)); // copy to local storage because Transform modifies it AxisAndBedTransform(newPos, reprap.GetCurrentTool(), doBedCompensation); SetLiveCoordinates(newPos); @@ -478,12 +431,12 @@ void Move::AxisTransform(float xyzPoint[MaxAxes], const Tool *tool) const { // Identify the lowest Y axis const size_t numVisibleAxes = reprap.GetGCodes().GetVisibleAxes(); - const AxesBitmap xAxes = Tool::GetXAxes(tool); const AxesBitmap yAxes = Tool::GetYAxes(tool); const size_t lowestYAxis = LowestSetBit(yAxes); if (lowestYAxis < numVisibleAxes) { // Found a Y axis. Use this one when correcting the X coordinate. + const AxesBitmap xAxes = Tool::GetXAxes(tool); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { if (IsBitSet(xAxes, axis)) @@ -509,12 +462,12 @@ void Move::InverseAxisTransform(float xyzPoint[MaxAxes], const Tool *tool) const { // Identify the lowest Y axis const size_t numVisibleAxes = reprap.GetGCodes().GetVisibleAxes(); - const AxesBitmap xAxes = Tool::GetXAxes(tool); const AxesBitmap yAxes = Tool::GetYAxes(tool); const size_t lowestYAxis = LowestSetBit(yAxes); if (lowestYAxis < numVisibleAxes) { // Found a Y axis. Use this one when correcting the X coordinate. + const AxesBitmap xAxes = Tool::GetXAxes(tool); for (size_t axis = 0; axis < numVisibleAxes; ++axis) { if (IsBitSet(yAxes, axis)) @@ -540,7 +493,7 @@ void Move::BedTransform(float xyzPoint[MaxAxes], const Tool *tool) const const AxesBitmap yAxes = Tool::GetYAxes(tool); unsigned int numCorrections = 0; - // Transform the Z coordinate based on the average correction for each axis used as an X or Y axis. + // Transform the Z coordinate based on the average correction for each axis used as an X axis. for (uint32_t xAxis = 0; xAxis < numAxes; ++xAxis) { if (IsBitSet(xAxes, xAxis)) @@ -587,7 +540,7 @@ void Move::InverseBedTransform(float xyzPoint[MaxAxes], const Tool *tool) const { if (IsBitSet(yAxes, yAxis)) { - const float yCoord = xyzPoint[yAxis] + Tool::GetOffset(tool, yAxis); + const float yCoord = xyzPoint[yAxis]+ Tool::GetOffset(tool, yAxis); zCorrection += GetInterpolatedHeightError(xCoord, yCoord); ++numCorrections; } @@ -634,8 +587,6 @@ void Move::SetIdentityTransform() zShift = 0.0; } -#if HAS_MASS_STORAGE - // Load the height map from file, returning true if an error occurred with the error reason appended to the buffer bool Move::LoadHeightMapFromFile(FileStore *f, const StringRef& r) { @@ -657,18 +608,6 @@ bool Move::SaveHeightMapToFile(FileStore *f) const return heightMap.SaveToFile(f, zShift); } -#endif - -#if HAS_LINUX_INTERFACE - -// Save the height map Z coordinates to an array -void Move::SaveHeightMapToArray(float *arr) const -{ - return heightMap.SaveToArray(arr, zShift); -} - -#endif - void Move::SetTaperHeight(float h) { useTaper = (h > 1.0); @@ -750,6 +689,41 @@ bool Move::FinishedBedProbing(int sParam, const StringRef& reply) return error; } +// This is the function that is called by the timer interrupt to step the motors. +// This may occasionally get called prematurely. +void Move::Interrupt() +{ + const uint32_t isrStartTime = StepTimer::GetInterruptClocksInterruptsDisabled(); + Platform& p = reprap.GetPlatform(); + bool repeat; + do + { + mainDDARing.Interrupt(p); + std::optional<uint32_t> nextStepTime = mainDDARing.GetNextInterruptTime(); + if (!nextStepTime.has_value()) + { + break; + } + + // Check whether we have been in this ISR for too long already and need to take a break + const uint16_t clocksTaken = StepTimer::GetInterruptClocks16() - (uint16_t)isrStartTime; + if (clocksTaken >= DDA::MaxStepInterruptTime && (nextStepTime.value() - isrStartTime) < (clocksTaken + DDA::MinInterruptInterval)) + { + // Force a break by updating the move start time + mainDDARing.InsertHiccup(DDA::HiccupTime); + nextStepTime = nextStepTime.value() + DDA::HiccupTime; +#if SUPPORT_CAN_EXPANSION + CanInterface::InsertHiccup(DDA::HiccupTime); +#endif + ++numHiccups; + } + + // 8. Schedule next interrupt, or if it would be too soon, generate more steps immediately + // If we have already spent too much time in the ISR, delay the interrupt + repeat = StepTimer::ScheduleStepInterrupt(nextStepTime.value()); + } while (repeat); +} + /*static*/ float Move::MotorStepsToMovement(size_t drive, int32_t endpoint) { return ((float)(endpoint))/reprap.GetPlatform().DriveStepsPerUnit(drive); @@ -769,9 +743,10 @@ void Move::GetCurrentUserPosition(float m[MaxAxes], uint8_t moveType, const Tool // Returns the number of motor steps moves since the last call, and isPrinting is true unless we are currently executing an extruding but non-printing move int32_t Move::GetAccumulatedExtrusion(size_t extruder, bool& isPrinting) { - if (extruder < reprap.GetGCodes().GetNumExtruders()) + const size_t drive = extruder + reprap.GetGCodes().GetTotalAxes(); + if (drive < MaxTotalDrivers) { - return mainDDARing.GetAccumulatedExtrusion(extruder, ExtruderToLogicalDrive(extruder), isPrinting); + return mainDDARing.GetAccumulatedExtrusion(extruder, drive, isPrinting); } isPrinting = false; @@ -811,9 +786,9 @@ float Move::GetProbeCoordinates(int count, float& x, float& y, bool wantNozzlePo y = probePoints.GetYCoord(count); if (wantNozzlePosition) { - const ZProbe& rp = reprap.GetPlatform().GetCurrentZProbe(); - x -= rp.GetXOffset(); - y -= rp.GetYOffset(); + const ZProbe& rp = reprap.GetPlatform().GetCurrentZProbeParameters(); + x -= rp.xOffset; + y -= rp.yOffset; } return probePoints.GetZHeight(count); } @@ -832,10 +807,17 @@ void Move::Simulate(uint8_t simMode) // This is only ever called after bed probing, so we can assume that no such move is already pending. void Move::AdjustLeadscrews(const floatc_t corrections[]) { - const size_t numZdrivers = reprap.GetPlatform().GetAxisDriversConfig(Z_AXIS).numDrivers; - for (size_t i = 0; i < MaxDriversPerAxis; ++i) + for (float& smc : specialMoveCoords) { - specialMoveCoords[i] = (i < numZdrivers) ? (float)corrections[i] : 0.0; + smc = 0.0; + } + const AxisDriversConfig& config = reprap.GetPlatform().GetAxisDriversConfig(Z_AXIS); + for (size_t i = 0; i < config.numDrivers; ++i) + { + if (config.driverNumbers[i] < MaxTotalDrivers) + { + specialMoveCoords[config.driverNumbers[i]] = corrections[i]; + } } bedLevellingMoveAvailable = true; } @@ -852,8 +834,6 @@ void Move::SetIdleTimeout(float timeout) idleTimeout = (uint32_t)lrintf(timeout * 1000.0); } -#if HAS_MASS_STORAGE - // Write settings for resuming the print // The GCodes module deals with the head position so all we need worry about is the bed compensation // We don't handle random probe point bed compensation, and we assume that if a height map is being used it is the default one. @@ -862,8 +842,6 @@ bool Move::WriteResumeSettings(FileStore *f) const return kinematics->WriteResumeSettings(f) && (!usingMesh || f->Write("G29 S1\n")); } -#endif - // Process M204 GCodeResult Move::ConfigureAccelerations(GCodeBuffer&gb, const StringRef& reply) { @@ -929,124 +907,4 @@ GCodeResult Move::ConfigureDynamicAcceleration(GCodeBuffer& gb, const StringRef& return GCodeResult::ok; } -#if SUPPORT_LASER || SUPPORT_IOBITS - -// Laser and IOBits support - -Task<Move::LaserTaskStackWords> *Move::laserTask = nullptr; // the task used to manage laser power or IOBits - -extern "C" void LaserTaskStart(void * pvParameters) -{ - reprap.GetMove().LaserTaskRun(); -} - -// This is called when laser mode is selected or IOBits is enabled -void Move::CreateLaserTask() -{ - TaskCriticalSectionLocker lock; - if (laserTask == nullptr) - { - laserTask = new Task<LaserTaskStackWords>; - laserTask->Create(LaserTaskStart, "LASER", nullptr, TaskPriority::LaserPriority); - } -} - -// Wake up the laser task, if there is one (must check!). Call this at the start of a new move from standstill (not from an ISR) -void Move::WakeLaserTask() -{ - if (laserTask != nullptr) - { - laserTask->Give(); - } -} - -// Wake up the laser task if there is one (must check!) from an ISR -void Move::WakeLaserTaskFromISR() -{ - if (laserTask != nullptr) - { - laserTask->GiveFromISR(); - } -} - -void Move::LaserTaskRun() -{ - for (;;) - { - // Sleep until we are woken up by the start of a move - TaskBase::Take(); - - if (reprap.GetGCodes().GetMachineType() == MachineType::laser) - { -# if SUPPORT_LASER - // Manage the laser power - uint32_t ticks; - while ((ticks = mainDDARing.ManageLaserPower()) != 0) - { - delay(ticks); - } -# endif - } - else - { -# if SUPPORT_IOBITS - // Manage the IOBits - uint32_t ticks; - while ((ticks = reprap.GetPortControl().UpdatePorts()) != 0) - { - delay(ticks); - } -# endif - } - } -} - -#endif - -#if SUPPORT_ASYNC_MOVES - -// Get and lock the aux move buffer. If successful, return a pointer to the buffer. -// The caller must not attempt to lock the aux buffer more than once, and must call ReleaseAuxMove to release the buffer. -AsyncMove *Move::LockAuxMove() -{ - InterruptCriticalSectionLocker lock; - if (!auxMoveLocked && !auxMoveAvailable) - { - auxMoveLocked = true; - return &auxMove; - } - return nullptr; -} - -// Release the aux move buffer and optionally signal that it contains a move -// The caller must have locked the buffer before calling this. If it calls with hasNewMove true, it must have populated the move buffer with the move details -void Move::ReleaseAuxMove(bool hasNewMove) -{ - auxMoveAvailable = hasNewMove; - auxMoveLocked = false; -} - -// Configure height following -GCodeResult Move::ConfigureHeightFollowing(GCodeBuffer& gb, const StringRef& reply) -{ - if (heightController == nullptr) - { - heightController = new HeightController; - } - return heightController->Configure(gb, reply); -} - -// Start/stop height following -GCodeResult Move::StartHeightFollowing(GCodeBuffer& gb, const StringRef& reply) -{ - if (heightController == nullptr) - { - reply.copy("Height following has not been configured"); - return GCodeResult::error; - } - return heightController->StartHeightFollowing(gb, reply); -} - -#endif - // End |