/* This file is part of Repetier-Firmware. Repetier-Firmware is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Repetier-Firmware is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Repetier-Firmware. If not, see . This firmware is a nearly complete rewrite of the sprinter firmware by kliment (https://github.com/kliment/Sprinter) which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. # Functions in this file are used to communicate using ascii or repetier protocol. */ #ifndef MOTION_H_INCLUDED #define MOTION_H_INCLUDED /** Marks the first step of a new move */ #define FLAG_WARMUP 1 #define FLAG_NOMINAL 2 #define FLAG_DECELERATING 4 #define FLAG_ACCELERATION_ENABLED 8 #define FLAG_CHECK_ENDSTOPS 16 #define FLAG_SKIP_ACCELERATING 32 #define FLAG_SKIP_DEACCELERATING 64 #define FLAG_BLOCKED 128 /** Are the step parameter computed */ #define FLAG_JOIN_STEPPARAMS_COMPUTED 1 /** The right speed is fixed. Don't check this block or any block to the left. */ #define FLAG_JOIN_END_FIXED 2 /** The left speed is fixed. Don't check left block. */ #define FLAG_JOIN_START_FIXED 4 /** Start filament retraction at move start */ #define FLAG_JOIN_START_RETRACT 8 /** Wait for filament pushback, before ending move */ #define FLAG_JOIN_END_RETRACT 16 /** Disable retract for this line */ #define FLAG_JOIN_NO_RETRACT 32 /** Wait for the extruder to finish it's up movement */ #define FLAG_JOIN_WAIT_EXTRUDER_UP 64 /** Wait for the extruder to finish it's down movement */ #define FLAG_JOIN_WAIT_EXTRUDER_DOWN 128 // Printing related data #if NONLINEAR_SYSTEM // Allow the delta cache to store segments for every line in line cache. Beware this gets big ... fast. // DELTASEGMENTS_PER_PRINTLINE * #define DELTA_CACHE_SIZE (DELTASEGMENTS_PER_PRINTLINE * PRINTLINE_CACHE_SIZE) class PrintLine; typedef struct { flag8_t dir; ///< Direction of delta movement. uint16_t deltaSteps[TOWER_ARRAY]; ///< Number of steps in move. inline void checkEndstops(PrintLine *cur,bool checkall); inline void setXMoveFinished() { dir &= ~XSTEP; } inline void setYMoveFinished() { dir &= ~YSTEP; } inline void setZMoveFinished() { dir &= ~ZSTEP; } inline void setXYMoveFinished() { dir &= ~XY_STEP; } inline bool isXPositiveMove() { return (dir & X_STEP_DIRPOS) == X_STEP_DIRPOS; } inline bool isXNegativeMove() { return (dir & X_STEP_DIRPOS) == XSTEP; } inline bool isYPositiveMove() { return (dir & Y_STEP_DIRPOS) == Y_STEP_DIRPOS; } inline bool isYNegativeMove() { return (dir & Y_STEP_DIRPOS) == YSTEP; } inline bool isZPositiveMove() { return (dir & Z_STEP_DIRPOS) == Z_STEP_DIRPOS; } inline bool isZNegativeMove() { return (dir & Z_STEP_DIRPOS) == ZSTEP; } inline bool isEPositiveMove() { return (dir & E_STEP_DIRPOS) == E_STEP_DIRPOS; } inline bool isENegativeMove() { return (dir & E_STEP_DIRPOS) == ESTEP; } inline bool isXMove() { return (dir & XSTEP); } inline bool isYMove() { return (dir & YSTEP); } inline bool isXOrYMove() { return dir & XY_STEP; } inline bool isZMove() { return (dir & ZSTEP); } inline bool isEMove() { return (dir & ESTEP); } inline bool isEOnlyMove() { return (dir & XYZE_STEP)==ESTEP; } inline bool isNoMove() { return (dir & XYZE_STEP)==0; } inline bool isXYZMove() { return dir & XYZ_STEP; } inline bool isMoveOfAxis(uint8_t axis) { return (dir & (XSTEP< inside interrupt handle inline void updateAdvanceSteps(speed_t v,uint8_t max_loops,bool accelerate) { #if USE_ADVANCE if(!Printer::isAdvanceActivated()) return; #if ENABLE_QUADRATIC_ADVANCE long advanceTarget = Printer::advanceExecuted; if(accelerate) { for(uint8_t loop = 0; loopadvanceFull) advanceTarget = advanceFull; } else { for(uint8_t loop = 0; loop> 16); HAL::forbidInterrupts(); Printer::extruderStepsNeeded += tred-Printer::advanceStepsSet; if(tred > 0 && Printer::advanceStepsSet <= 0) Printer::extruderStepsNeeded += Extruder::current->advanceBacklash; else if(tred < 0 && Printer::advanceStepsSet >= 0) Printer::extruderStepsNeeded -= Extruder::current->advanceBacklash; Printer::advanceStepsSet = tred; HAL::allowInterrupts(); Printer::advanceExecuted = advanceTarget; #else int tred = HAL::mulu6xu16shift16(v, advanceL); HAL::forbidInterrupts(); Printer::extruderStepsNeeded += tred - Printer::advanceStepsSet; if(tred > 0 && Printer::advanceStepsSet <= 0) Printer::extruderStepsNeeded += (Extruder::current->advanceBacklash << 1); else if(tred < 0 && Printer::advanceStepsSet >= 0) Printer::extruderStepsNeeded -= (Extruder::current->advanceBacklash << 1); Printer::advanceStepsSet = tred; HAL::allowInterrupts(); #endif #endif } inline bool moveDecelerating() { if(stepsRemaining <= decelSteps) { if (!(flags & FLAG_DECELERATING)) { Printer::timer = 0; flags |= FLAG_DECELERATING; } return true; } else return false; } inline bool moveAccelerating() { return Printer::stepNumber <= accelSteps; } inline bool isFullstepping() { return halfStep == 4; } inline void startXStep() { #if !(GANTRY) WRITE(X_STEP_PIN,HIGH); #if FEATURE_TWO_XSTEPPER WRITE(X2_STEP_PIN,HIGH); #endif #else #if DRIVE_SYSTEM == XY_GANTRY || DRIVE_SYSTEM == XZ_GANTRY if(isXPositiveMove()) { Printer::motorX++; Printer::motorYorZ++; } else { Printer::motorX--; Printer::motorYorZ--; } #endif #if DRIVE_SYSTEM == YX_GANTRY || DRIVE_SYSTEM == ZX_GANTRY if(isXPositiveMove()) { Printer::motorX++; Printer::motorYorZ--; } else { Printer::motorX--; Printer::motorYorZ++; } #endif #endif #ifdef DEBUG_STEPCOUNT totalStepsRemaining--; #endif } inline void startYStep() { #if !(GANTRY) || DRIVE_SYSTEM == ZX_GANTRY || DRIVE_SYSTEM == XZ_GANTRY WRITE(Y_STEP_PIN,HIGH); #if FEATURE_TWO_YSTEPPER WRITE(Y2_STEP_PIN,HIGH); #endif #else #if DRIVE_SYSTEM==XY_GANTRY if(isYPositiveMove()) { Printer::motorX++; Printer::motorYorZ--; } else { Printer::motorX--; Printer::motorYorZ++; } #endif #if DRIVE_SYSTEM==YX_GANTRY if(isYPositiveMove()) { Printer::motorX++; Printer::motorYorZ++; } else { Printer::motorX--; Printer::motorYorZ--; } #endif #endif // GANTRY #ifdef DEBUG_STEPCOUNT totalStepsRemaining--; #endif } inline void startZStep() { #if !(GANTRY) || DRIVE_SYSTEM == YX_GANTRY || DRIVE_SYSTEM == XY_GANTRY WRITE(Z_STEP_PIN,HIGH); #if FEATURE_TWO_ZSTEPPER WRITE(Z2_STEP_PIN,HIGH); #endif #else #if DRIVE_SYSTEM==XZ_GANTRY if(isYPositiveMove()) { Printer::motorX++; Printer::motorYorZ--; } else { Printer::motorX--; Printer::motorYorZ++; } #endif #if DRIVE_SYSTEM==ZX_GANTRY if(isYPositiveMove()) { Printer::motorX++; Printer::motorYorZ++; } else { Printer::motorX--; Printer::motorYorZ--; } #endif #endif } void updateStepsParameter(); inline float safeSpeed(); void calculateMove(float axis_diff[],uint8_t pathOptimize); void logLine(); inline long getWaitTicks() { return timeInTicks; } inline void setWaitTicks(long wait) { timeInTicks = wait; } static inline bool hasLines() { return linesCount; } static inline void setCurrentLine() { cur = &lines[linesPos]; #if CPU_ARCH==ARCH_ARM PrintLine::nlFlag = true; #endif } // Only called from within interrupts static inline void removeCurrentLineForbidInterrupt() { linesPos++; if(linesPos >= PRINTLINE_CACHE_SIZE) linesPos=0; cur = NULL; #if CPU_ARCH==ARCH_ARM nlFlag = false; #endif HAL::forbidInterrupts(); --linesCount; if(!linesCount) Printer::setMenuMode(MENU_MODE_PRINTING,false); } static inline void pushLine() { linesWritePos++; if(linesWritePos >= PRINTLINE_CACHE_SIZE) linesWritePos = 0; Printer::setMenuMode(MENU_MODE_PRINTING,true); InterruptProtectedBlock noInts; linesCount++; } static uint8_t getLinesCount() { InterruptProtectedBlock noInts; return linesCount; } static PrintLine *getNextWriteLine() { return &lines[linesWritePos]; } static inline void computeMaxJunctionSpeed(PrintLine *previous,PrintLine *current); static int32_t bresenhamStep(); static void waitForXFreeLines(uint8_t b=1, bool allowMoves = false); static inline void forwardPlanner(uint8_t p); static inline void backwardPlanner(uint8_t p,uint8_t last); static void updateTrapezoids(); static uint8_t insertWaitMovesIfNeeded(uint8_t pathOptimize, uint8_t waitExtraLines); static void queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize); static void moveRelativeDistanceInSteps(int32_t x,int32_t y,int32_t z,int32_t e,float feedrate,bool waitEnd,bool check_endstop); static void moveRelativeDistanceInStepsReal(int32_t x,int32_t y,int32_t z,int32_t e,float feedrate,bool waitEnd); #if ARC_SUPPORT static void arc(float *position, float *target, float *offset, float radius, uint8_t isclockwise); #endif static inline void previousPlannerIndex(uint8_t &p) { p = (p ? p-1 : PRINTLINE_CACHE_SIZE-1); } static inline void nextPlannerIndex(uint8_t& p) { p = (p == PRINTLINE_CACHE_SIZE - 1 ? 0 : p + 1); } #if NONLINEAR_SYSTEM static uint8_t queueDeltaMove(uint8_t check_endstops,uint8_t pathOptimize, uint8_t softEndstop); static inline void queueEMove(int32_t e_diff,uint8_t check_endstops,uint8_t pathOptimize); inline uint16_t calculateDeltaSubSegments(uint8_t softEndstop); static inline void calculateDirectionAndDelta(int32_t difference[], flag8_t *dir, int32_t delta[]); static inline uint8_t calculateDistance(float axis_diff[], uint8_t dir, float *distance); #if SOFTWARE_LEVELING && DRIVE_SYSTEM == DELTA static void calculatePlane(int32_t factors[], int32_t p1[], int32_t p2[], int32_t p3[]); static float calcZOffset(int32_t factors[], int32_t pointX, int32_t pointY); #endif #endif }; #endif // MOTION_H_INCLUDED