Repetier-Firmware  0.91
src/ArduinoAVR/Repetier/motion.h
Go to the documentation of this file.
00001 /*
00002     This file is part of Repetier-Firmware.
00003 
00004     Repetier-Firmware is free software: you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation, either version 3 of the License, or
00007     (at your option) any later version.
00008 
00009     Repetier-Firmware is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with Repetier-Firmware.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017     This firmware is a nearly complete rewrite of the sprinter firmware
00018     by kliment (https://github.com/kliment/Sprinter)
00019     which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
00020 #
00021   Functions in this file are used to communicate using ascii or repetier protocol.
00022 */
00023 
00024 #ifndef MOTION_H_INCLUDED
00025 #define MOTION_H_INCLUDED
00026 
00028 #define FLAG_WARMUP 1
00029 #define FLAG_NOMINAL 2
00030 #define FLAG_DECELERATING 4
00031 #define FLAG_ACCELERATION_ENABLED 8
00032 #define FLAG_CHECK_ENDSTOPS 16
00033 #define FLAG_SKIP_ACCELERATING 32
00034 #define FLAG_SKIP_DEACCELERATING 64
00035 #define FLAG_BLOCKED 128
00036 
00038 #define FLAG_JOIN_STEPPARAMS_COMPUTED 1
00039 
00040 #define FLAG_JOIN_END_FIXED 2
00041 
00042 #define FLAG_JOIN_START_FIXED 4
00043 
00044 #define FLAG_JOIN_START_RETRACT 8
00045 
00046 #define FLAG_JOIN_END_RETRACT 16
00047 
00048 #define FLAG_JOIN_NO_RETRACT 32
00049 
00050 #define FLAG_JOIN_WAIT_EXTRUDER_UP 64
00051 
00052 #define FLAG_JOIN_WAIT_EXTRUDER_DOWN 128
00053 // Printing related data
00054 #if NONLINEAR_SYSTEM
00055 // Allow the delta cache to store segments for every line in line cache. Beware this gets big ... fast.
00056 // MAX_DELTA_SEGMENTS_PER_LINE *
00057 #define DELTA_CACHE_SIZE (MAX_DELTA_SEGMENTS_PER_LINE * MOVE_CACHE_SIZE)
00058 
00059 class PrintLine;
00060 typedef struct
00061 {
00062     uint8_t dir;                                                                        
00063     uint16_t deltaSteps[3];                                 
00064     inline void checkEndstops(PrintLine *cur,bool checkall);
00065     inline void setXMoveFinished()
00066     {
00067         dir&=~16;
00068     }
00069     inline void setYMoveFinished()
00070     {
00071         dir&=~32;
00072     }
00073     inline void setZMoveFinished()
00074     {
00075         dir&=~64;
00076     }
00077     inline void setXYMoveFinished()
00078     {
00079         dir&=~48;
00080     }
00081     inline bool isXPositiveMove()
00082     {
00083         return (dir & 17)==17;
00084     }
00085     inline bool isXNegativeMove()
00086     {
00087         return (dir & 17)==16;
00088     }
00089     inline bool isYPositiveMove()
00090     {
00091         return (dir & 34)==34;
00092     }
00093     inline bool isYNegativeMove()
00094     {
00095         return (dir & 34)==32;
00096     }
00097     inline bool isZPositiveMove()
00098     {
00099         return (dir & 68)==68;
00100     }
00101     inline bool isZNegativeMove()
00102     {
00103         return (dir & 68)==64;
00104     }
00105     inline bool isEPositiveMove()
00106     {
00107         return (dir & 136)==136;
00108     }
00109     inline bool isENegativeMove()
00110     {
00111         return (dir & 136)==128;
00112     }
00113     inline bool isXMove()
00114     {
00115         return (dir & 16);
00116     }
00117     inline bool isYMove()
00118     {
00119         return (dir & 32);
00120     }
00121     inline bool isXOrYMove()
00122     {
00123         return dir & 48;
00124     }
00125     inline bool isZMove()
00126     {
00127         return (dir & 64);
00128     }
00129     inline bool isEMove()
00130     {
00131         return (dir & 128);
00132     }
00133     inline bool isEOnlyMove()
00134     {
00135         return (dir & 240)==128;
00136     }
00137     inline bool isNoMove()
00138     {
00139         return (dir & 240)==0;
00140     }
00141     inline bool isXYZMove()
00142     {
00143         return dir & 112;
00144     }
00145     inline bool isMoveOfAxis(uint8_t axis)
00146     {
00147         return (dir & (16<<axis));
00148     }
00149     inline void setMoveOfAxis(uint8_t axis)
00150     {
00151         dir |= 16<<axis;
00152     }
00153     inline void setPositiveDirectionForAxis(uint8_t axis)
00154     {
00155         dir |= 1<<axis;
00156     }
00157 } DeltaSegment;
00158 extern uint8_t lastMoveID;
00159 #endif
00160 class UIDisplay;
00161 class PrintLine   // RAM usage: 24*4+15 = 113 Byte
00162 {
00163     friend class UIDisplay;
00164 #if CPU_ARCH==ARCH_ARM
00165     static volatile bool nlFlag;
00166 #endif
00167     static uint8_t linesPos; // Position for executing line movement
00168     static PrintLine lines[];
00169     static uint8_t linesWritePos; // Position where we write the next cached line move
00170     uint8_t primaryAxis;
00171     volatile uint8_t flags;
00172     long timeInTicks;
00173     uint8_t joinFlags;
00174     uint8_t halfStep;                  
00175     uint8_t dir;                       
00176     long delta[4];                  
00177     long error[4];                  
00178     float speedX;                   
00179     float speedY;                   
00180     float speedZ;                   
00181     float speedE;                   
00182     float fullSpeed;                
00183     float invFullSpeed;             
00184     float accelerationDistance2;             
00185     float maxJunctionSpeed;         
00186     float startSpeed;               
00187     float endSpeed;                 
00188     float minSpeed;
00189     float distance;
00190 #if NONLINEAR_SYSTEM
00191     uint8_t numDeltaSegments;           
00192     uint8_t moveID;                                     
00193     long numPrimaryStepPerSegment;      
00194     DeltaSegment segments[MAX_DELTA_SEGMENTS_PER_LINE];
00195 #endif
00196     ticks_t fullInterval;     
00197     unsigned int accelSteps;        
00198     unsigned int decelSteps;        
00199     unsigned long accelerationPrim; 
00200     unsigned long fAcceleration;    
00201     speed_t vMax;              
00202     speed_t vStart;            
00203     speed_t vEnd;              
00204 #ifdef USE_ADVANCE
00205 #ifdef ENABLE_QUADRATIC_ADVANCE
00206     long advanceRate;               
00207     long advanceFull;               
00208     long advanceStart;
00209     long advanceEnd;
00210 #endif
00211     unsigned int advanceL;         
00212 #endif
00213 #ifdef DEBUG_STEPCOUNT
00214     long totalStepsRemaining;
00215 #endif
00216 public:
00217     long stepsRemaining;            
00218     static PrintLine *cur;
00219     static volatile uint8_t linesCount; // Number of lines cached 0 = nothing to do
00220     inline bool areParameterUpToDate()
00221     {
00222         return joinFlags & FLAG_JOIN_STEPPARAMS_COMPUTED;
00223     }
00224     inline void invalidateParameter()
00225     {
00226         joinFlags &= ~FLAG_JOIN_STEPPARAMS_COMPUTED;
00227     }
00228     inline void setParameterUpToDate()
00229     {
00230         joinFlags |= FLAG_JOIN_STEPPARAMS_COMPUTED;
00231     }
00232     inline bool isStartSpeedFixed()
00233     {
00234         return joinFlags & FLAG_JOIN_START_FIXED;
00235     }
00236     inline void setStartSpeedFixed(bool newState)
00237     {
00238         joinFlags = (newState ? joinFlags | FLAG_JOIN_START_FIXED : joinFlags & ~FLAG_JOIN_START_FIXED);
00239     }
00240     inline void fixStartAndEndSpeed()
00241     {
00242         joinFlags |= FLAG_JOIN_END_FIXED | FLAG_JOIN_START_FIXED;
00243     }
00244     inline bool isEndSpeedFixed()
00245     {
00246         return joinFlags & FLAG_JOIN_END_FIXED;
00247     }
00248     inline void setEndSpeedFixed(bool newState)
00249     {
00250         joinFlags = (newState ? joinFlags | FLAG_JOIN_END_FIXED : joinFlags & ~FLAG_JOIN_END_FIXED);
00251     }
00252     inline bool isWarmUp()
00253     {
00254         return flags & FLAG_WARMUP;
00255     }
00256     inline uint8_t getWaitForXLinesFilled()
00257     {
00258         return primaryAxis;
00259     }
00260     inline void setWaitForXLinesFilled(uint8_t b)
00261     {
00262         primaryAxis = b;
00263     }
00264     inline bool isExtruderForwardMove()
00265     {
00266         return (dir & 136)==136;
00267     }
00268     inline void block()
00269     {
00270         flags |= FLAG_BLOCKED;
00271     }
00272     inline void unblock()
00273     {
00274         flags &= ~FLAG_BLOCKED;
00275     }
00276     inline bool isBlocked()
00277     {
00278         return flags & FLAG_BLOCKED;
00279     }
00280     inline bool isCheckEndstops()
00281     {
00282         return flags & FLAG_CHECK_ENDSTOPS;
00283     }
00284     inline bool isNominalMove()
00285     {
00286         return flags & FLAG_NOMINAL;
00287     }
00288     inline bool setNominalMove()
00289     {
00290         flags |= FLAG_NOMINAL;
00291     }
00292     inline void checkEndstops()
00293     {
00294         if(isCheckEndstops())
00295         {
00296             if(isXNegativeMove() && Printer::isXMinEndstopHit())
00297                 setXMoveFinished();
00298             if(isYNegativeMove() && Printer::isYMinEndstopHit())
00299                 setYMoveFinished();
00300             if(isXPositiveMove() && Printer::isXMaxEndstopHit())
00301                 setXMoveFinished();
00302             if(isYPositiveMove() && Printer::isYMaxEndstopHit())
00303                 setYMoveFinished();
00304         }
00305 #if FEATURE_Z_PROBE
00306         if(Printer::isZProbingActive() && isZNegativeMove() && Printer::isZProbeHit())
00307         {
00308             setZMoveFinished();
00309             Printer::stepsRemainingAtZHit = stepsRemaining;
00310         }
00311         else
00312 #endif
00313             // Test Z-Axis every step if necessary, otherwise it could easyly ruin your printer!
00314             if(isZNegativeMove() && Printer::isZMinEndstopHit())
00315                 setZMoveFinished();
00316         if(isZPositiveMove() && Printer::isZMaxEndstopHit())
00317         {
00318 #if MAX_HARDWARE_ENDSTOP_Z
00319             Printer::stepsRemainingAtZHit = stepsRemaining;
00320 #endif
00321             setZMoveFinished();
00322         }
00323         if(isZPositiveMove() && Printer::isZMaxEndstopHit())
00324             setZMoveFinished();
00325     }
00326     inline void setXMoveFinished()
00327     {
00328 #if DRIVE_SYSTEM==0 || NONLINEAR_SYSTEM
00329         dir&=~16;
00330 #else
00331         dir&=~48;
00332 #endif
00333     }
00334     inline void setYMoveFinished()
00335     {
00336 #if DRIVE_SYSTEM==0 || NONLINEAR_SYSTEM
00337         dir&=~32;
00338 #else
00339         dir&=~48;
00340 #endif
00341     }
00342     inline void setZMoveFinished()
00343     {
00344         dir&=~64;
00345     }
00346     inline void setXYMoveFinished()
00347     {
00348         dir&=~48;
00349     }
00350     inline bool isXPositiveMove()
00351     {
00352         return (dir & 17)==17;
00353     }
00354     inline bool isXNegativeMove()
00355     {
00356         return (dir & 17)==16;
00357     }
00358     inline bool isYPositiveMove()
00359     {
00360         return (dir & 34)==34;
00361     }
00362     inline bool isYNegativeMove()
00363     {
00364         return (dir & 34)==32;
00365     }
00366     inline bool isZPositiveMove()
00367     {
00368         return (dir & 68)==68;
00369     }
00370     inline bool isZNegativeMove()
00371     {
00372         return (dir & 68)==64;
00373     }
00374     inline bool isEPositiveMove()
00375     {
00376         return (dir & 136)==136;
00377     }
00378     inline bool isENegativeMove()
00379     {
00380         return (dir & 136)==128;
00381     }
00382     inline bool isXMove()
00383     {
00384         return (dir & 16);
00385     }
00386     inline bool isYMove()
00387     {
00388         return (dir & 32);
00389     }
00390     inline bool isXOrYMove()
00391     {
00392         return dir & 48;
00393     }
00394     inline bool isZMove()
00395     {
00396         return (dir & 64);
00397     }
00398     inline bool isEMove()
00399     {
00400         return (dir & 128);
00401     }
00402     inline bool isEOnlyMove()
00403     {
00404         return (dir & 240)==128;
00405     }
00406     inline bool isNoMove()
00407     {
00408         return (dir & 240)==0;
00409     }
00410     inline bool isXYZMove()
00411     {
00412         return dir & 112;
00413     }
00414     inline bool isMoveOfAxis(uint8_t axis)
00415     {
00416         return (dir & (16<<axis));
00417     }
00418     inline void setMoveOfAxis(uint8_t axis)
00419     {
00420         dir |= 16<<axis;
00421     }
00422     inline void setPositiveDirectionForAxis(uint8_t axis)
00423     {
00424         dir |= 1<<axis;
00425     }
00426     inline static void resetPathPlanner()
00427     {
00428         linesCount = 0;
00429         linesPos = linesWritePos;
00430     }
00431     inline void updateAdvanceSteps(unsigned int v,uint8_t max_loops,bool accelerate)
00432     {
00433 #ifdef USE_ADVANCE
00434         if(!Printer::isAdvanceActivated()) return;
00435 #ifdef ENABLE_QUADRATIC_ADVANCE
00436         long advanceTarget = Printer::advanceExecuted;
00437         if(accelerate)
00438         {
00439             for(uint8_t loop = 0; loop<max_loops; loop++) advanceTarget += advanceRate;
00440             if(advanceTarget>advanceFull)
00441                 advanceTarget = advanceFull;
00442         }
00443         else
00444         {
00445             for(uint8_t loop = 0; loop<max_loops; loop++) advanceTarget -= advanceRate;
00446             if(advanceTarget<advanceEnd)
00447                 advanceTarget = advanceEnd;
00448         }
00449         long h = HAL::mulu16xu16to32(v,advanceL);
00450         int tred = ((advanceTarget + h) >> 16);
00451         HAL::forbidInterrupts();
00452         Printer::extruderStepsNeeded += tred-Printer::advanceStepsSet;
00453         if(tred>0 && Printer::advanceStepsSet<=0)
00454             Printer::extruderStepsNeeded += Extruder::current->advanceBacklash;
00455         else if(tred<0 && Printer::advanceStepsSet>=0)
00456             Printer::extruderStepsNeeded -= Extruder::current->advanceBacklash;
00457         Printer::advanceStepsSet = tred;
00458         HAL::allowInterrupts();
00459         Printer::advanceExecuted = advanceTarget;
00460 #else
00461         int tred = HAL::mulu6xu16shift16(v,advanceL);
00462         HAL::forbidInterrupts();
00463         Printer::extruderStepsNeeded += tred - Printer::advanceStepsSet;
00464         if(tred>0 && Printer::advanceStepsSet<=0)
00465             Printer::extruderStepsNeeded += (Extruder::current->advanceBacklash << 1);
00466         else if(tred<0 && Printer::advanceStepsSet>=0)
00467             Printer::extruderStepsNeeded -= (Extruder::current->advanceBacklash << 1);
00468         Printer::advanceStepsSet = tred;
00469         HAL::allowInterrupts();
00470 #endif
00471 #endif
00472     }
00473     inline bool moveDecelerating()
00474     {
00475         if(stepsRemaining <= decelSteps)
00476         {
00477             if (!(flags & FLAG_DECELERATING))
00478             {
00479                 Printer::timer = 0;
00480                 flags |= FLAG_DECELERATING;
00481             }
00482             return true;
00483         }
00484         else return false;
00485     }
00486     inline bool moveAccelerating()
00487     {
00488         return Printer::stepNumber <= accelSteps;
00489     }
00490     inline bool isFullstepping()
00491     {
00492         return halfStep == 4;
00493     }
00494     inline bool startXStep()
00495     {
00496         ANALYZER_ON(ANALYZER_CH6);
00497 #if DRIVE_SYSTEM==0 || !defined(XY_GANTRY)
00498         ANALYZER_ON(ANALYZER_CH2);
00499         WRITE(X_STEP_PIN,HIGH);
00500 #if FEATURE_TWO_XSTEPPER
00501         WRITE(X2_STEP_PIN,HIGH);
00502 #endif
00503 #else
00504 #if DRIVE_SYSTEM==1
00505         if(isXPositiveMove())
00506         {
00507             Printer::motorX++;
00508             Printer::motorY++;
00509         }
00510         else
00511         {
00512             Printer::motorX--;
00513             Printer::motorY--;
00514         }
00515 #endif
00516 #if DRIVE_SYSTEM==2
00517         if(isXPositiveMove())
00518         {
00519             Printer::motorX++;
00520             Printer::motorY--;
00521         }
00522         else
00523         {
00524             Printer::motorX--;
00525             Printer::motorY++;
00526         }
00527 #endif
00528 #endif
00529 #ifdef DEBUG_STEPCOUNT
00530         totalStepsRemaining--;
00531 #endif
00532 
00533     }
00534     inline bool startYStep()
00535     {
00536         ANALYZER_ON(ANALYZER_CH7);
00537 #if DRIVE_SYSTEM==0 || !defined(XY_GANTRY)
00538         ANALYZER_ON(ANALYZER_CH3);
00539         WRITE(Y_STEP_PIN,HIGH);
00540 #if FEATURE_TWO_YSTEPPER
00541         WRITE(Y2_STEP_PIN,HIGH);
00542 #endif
00543 #else
00544 #if DRIVE_SYSTEM==1
00545         if(isYPositiveMove())
00546         {
00547             Printer::motorX++;
00548             Printer::motorY--;
00549         }
00550         else
00551         {
00552             Printer::motorX--;
00553             Printer::motorY++;
00554         }
00555 #endif
00556 #if DRIVE_SYSTEM==2
00557         if(isYPositiveMove())
00558         {
00559             Printer::motorX++;
00560             Printer::motorY++;
00561         }
00562         else
00563         {
00564             Printer::motorX--;
00565             Printer::motorY--;
00566         }
00567 #endif
00568 #endif // XY_GANTRY
00569 #ifdef DEBUG_STEPCOUNT
00570         totalStepsRemaining--;
00571 #endif
00572     }
00573     inline void startZStep()
00574     {
00575         WRITE(Z_STEP_PIN,HIGH);
00576 #if FEATURE_TWO_ZSTEPPER
00577         WRITE(Z2_STEP_PIN,HIGH);
00578 #endif
00579     }
00580     void updateStepsParameter();
00581     inline float safeSpeed();
00582     void calculateMove(float axis_diff[],uint8_t pathOptimize);
00583     void logLine();
00584     inline long getWaitTicks()
00585     {
00586         return timeInTicks;
00587     }
00588     inline void setWaitTicks(long wait)
00589     {
00590         timeInTicks = wait;
00591     }
00592 
00593     static inline bool hasLines()
00594     {
00595         return linesCount;
00596     }
00597     static inline void setCurrentLine()
00598     {
00599         cur = &lines[linesPos];
00600 #if CPU_ARCH==ARCH_ARM
00601         PrintLine::nlFlag = true;
00602 #endif
00603     }
00604     static inline void removeCurrentLineForbidInterrupt()
00605     {
00606         linesPos++;
00607         if(linesPos>=MOVE_CACHE_SIZE) linesPos=0;
00608         cur = NULL;
00609 #if CPU_ARCH==ARCH_ARM
00610         nlFlag = false;
00611 #endif
00612         HAL::forbidInterrupts();
00613         --linesCount;
00614     }
00615     static inline void pushLine()
00616     {
00617         linesWritePos++;
00618         if(linesWritePos>=MOVE_CACHE_SIZE) linesWritePos = 0;
00619         BEGIN_INTERRUPT_PROTECTED
00620         linesCount++;
00621         END_INTERRUPT_PROTECTED
00622     }
00623     static PrintLine *getNextWriteLine()
00624     {
00625         return &lines[linesWritePos];
00626     }
00627     static inline void computeMaxJunctionSpeed(PrintLine *previous,PrintLine *current);
00628     static long bresenhamStep();
00629     static void waitForXFreeLines(uint8_t b=1);
00630     static inline void forwardPlanner(uint8_t p);
00631     static inline void backwardPlanner(uint8_t p,uint8_t last);
00632     static void updateTrapezoids();
00633     static uint8_t insertWaitMovesIfNeeded(uint8_t pathOptimize, uint8_t waitExtraLines);
00634     static void queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize);
00635     static void moveRelativeDistanceInSteps(long x,long y,long z,long e,float feedrate,bool waitEnd,bool check_endstop);
00636 #if ARC_SUPPORT
00637     static void arc(float *position, float *target, float *offset, float radius, uint8_t isclockwise);
00638 #endif
00639     static inline void previousPlannerIndex(uint8_t &p)
00640     {
00641         p = (p ? p-1 : MOVE_CACHE_SIZE-1);
00642     }
00643     static inline void nextPlannerIndex(uint8_t& p)
00644     {
00645         p = (p==MOVE_CACHE_SIZE-1?0:p+1);
00646     }
00647 #if NONLINEAR_SYSTEM
00648     static void queueDeltaMove(uint8_t check_endstops,uint8_t pathOptimize, uint8_t softEndstop);
00649     static inline void queueEMove(long e_diff,uint8_t check_endstops,uint8_t pathOptimize);
00650     inline uint16_t calculateDeltaSubSegments(uint8_t softEndstop);
00651     static inline void calculateDirectionAndDelta(long difference[], uint8_t *dir, long delta[]);
00652     static inline uint8_t calculateDistance(float axis_diff[], uint8_t dir, float *distance);
00653 #ifdef SOFTWARE_LEVELING && DRIVE_SYSTEM==3
00654     static void calculatePlane(long factors[], long p1[], long p2[], long p3[]);
00655     static float calcZOffset(long factors[], long pointX, long pointY);
00656 #endif
00657 #endif
00658 };
00659 
00660 
00661 
00662 #endif // MOTION_H_INCLUDED
 All Data Structures Namespaces Files Functions Variables Typedefs Friends Defines