/ Repetier / Repetier.ino
Repetier.ino
   1  /*
   2      This file is part of Repetier-Firmware.
   3  
   4      Repetier-Firmware is free software: you can redistribute it and/or modify
   5      it under the terms of the GNU General Public License as published by
   6      the Free Software Foundation, either version 3 of the License, or
   7      (at your option) any later version.
   8  
   9      Repetier-Firmware is distributed in the hope that it will be useful,
  10      but WITHOUT ANY WARRANTY; without even the implied warranty of
  11      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12      GNU General Public License for more details.
  13  
  14      You should have received a copy of the GNU General Public License
  15      along with Repetier-Firmware.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17      This firmware is a nearly complete rewrite of the sprinter firmware
  18      by kliment (https://github.com/kliment/Sprinter)
  19      which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
  20  
  21      Main author: repetier
  22  
  23  */
  24  /**
  25  \mainpage Repetier-Firmware for Arduino based RepRaps
  26  <CENTER>Copyright &copy; 2011-2013 by repetier
  27  </CENTER>
  28  
  29  \section Intro Introduction
  30  
  31  
  32  \section GCodes Implemented GCodes
  33  
  34   look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html
  35   and http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
  36  
  37  Implemented Codes
  38  
  39  - G0  -> G1
  40  - G1  - Coordinated Movement X Y Z E
  41  - G4  - Dwell S<seconds> or P<milliseconds>
  42  - G20 - Units for G0/G1 are inches.
  43  - G21 - Units for G0/G1 are mm.
  44  - G28 - Home all axis or named axis.
  45  - G90 - Use absolute coordinates
  46  - G91 - Use relative coordinates
  47  - G92 - Set current position to cordinates given
  48  
  49  RepRap M Codes
  50  
  51  - M104 - Set extruder target temp
  52  - M105 - Read current temp
  53  - M106 - Fan on
  54  - M107 - Fan off
  55  - M109 - Wait for extruder current temp to reach target temp.
  56  - M114 - Display current position
  57  
  58  Custom M Codes
  59  
  60  - M80  - Turn on Power Supply
  61  - M20  - List SD card
  62  - M21  - Init SD card
  63  - M22  - Release SD card
  64  - M23  - Select SD file (M23 filename.g)
  65  - M24  - Start/resume SD print
  66  - M25  - Pause SD print
  67  - M26  - Set SD position in bytes (M26 S12345)
  68  - M27  - Report SD print status
  69  - M28  - Start SD write (M28 filename.g)
  70  - M29  - Stop SD write
  71  - M30 <filename> - Delete file on sd card
  72  - M32 <dirname> create subdirectory
  73  - M42 P<pin number> S<value 0..255> - Change output of pin P to S. Does not work on most important pins.
  74  - M80  - Turn on power supply
  75  - M81  - Turn off power supply
  76  - M82  - Set E codes absolute (default)
  77  - M83  - Set E codes relative while in Absolute Coordinates (G90) mode
  78  - M84  - Disable steppers until next move,
  79          or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.
  80  - M85  - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
  81  - M92  - Set axis_steps_per_unit - same syntax as G92
  82  - M112 - Emergency kill
  83  - M115- Capabilities string
  84  - M117 <message> - Write message in status row on lcd
  85  - M119 - Report endstop status
  86  - M140 - Set bed target temp
  87  - M190 - Wait for bed current temp to reach target temp.
  88  - M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
  89  - M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000)
  90  - M203 - Set temperture monitor to Sx
  91  - M204 - Set PID parameter X => Kp Y => Ki Z => Kd S<extruder> Default is current extruder. NUM_EXTRUDER=Heated bed
  92  - M205 - Output EEPROM settings
  93  - M206 - Set EEPROM value
  94  - M220 S<Feedrate multiplier in percent> - Increase/decrease given feedrate
  95  - M221 S<Extrusion flow multiplier in percent> - Increase/decrease given flow rate
  96  - M231 S<OPS_MODE> X<Min_Distance> Y<Retract> Z<Backlash> F<ReatrctMove> - Set OPS parameter
  97  - M232 - Read and reset max. advance values
  98  - M233 X<AdvanceK> Y<AdvanceL> - Set temporary advance K-value to X and linear term advanceL to Y
  99  - M251 Measure Z steps from homing stop (Delta printers). S0 - Reset, S1 - Print, S2 - Store to Z length (also EEPROM if enabled)
 100  - M303 P<extruder/bed> S<drucktermeratur> Autodetect pid values. Use P<NUM_EXTRUDER> for heated bed.
 101  - M350 S<mstepsAll> X<mstepsX> Y<mstepsY> Z<mstepsZ> E<mstepsE0> P<mstespE1> : Set microstepping on RAMBO board
 102  - M400 - Wait until move buffers empty.
 103  - M401 - Store x, y and z position.
 104  - M402 - Go to stored position. If X, Y or Z is specified, only these coordinates are used. F changes feedrate fo rthat move.
 105  - M500 Store settings to EEPROM
 106  - M501 Load settings from EEPROM
 107  - M502 Reset settings to the one in configuration.h. Does not store values in EEPROM!
 108  - M908 P<address> S<value> : Set stepper current for digipot (RAMBO board)
 109  */
 110  
 111  #include "Reptier.h"
 112  #include "Eeprom.h"
 113  #include "pins_arduino.h"
 114  #include "fastio.h"
 115  #include "ui.h"
 116  #include <util/delay.h>
 117  #include <SPI.h>
 118  
 119  #if UI_DISPLAY_TYPE==4
 120  //#include <LiquidCrystal.h> // Uncomment this if you are using liquid crystal library
 121  #endif
 122  
 123  // ================ Sanity checks ================
 124  #ifndef STEP_DOUBLER_FREQUENCY
 125  #error Please add new parameter STEP_DOUBLER_FREQUENCY to your configuration.
 126  #else
 127  #if STEP_DOUBLER_FREQUENCY<10000 || STEP_DOUBLER_FREQUENCY>20000
 128  #error STEP_DOUBLER_FREQUENCY should be in range 10000-16000.
 129  #endif
 130  #endif
 131  #ifdef EXTRUDER_SPEED
 132  #error EXTRUDER_SPEED is not used any more. Values are now taken from extruder definition.
 133  #endif
 134  #if MAX_HALFSTEP_INTERVAL<=1900
 135  #error MAX_HALFSTEP_INTERVAL must be greater then 1900
 136  #endif
 137  #ifdef ENDSTOPPULLUPS
 138  #error ENDSTOPPULLUPS is now replaced by individual pullup configuration!
 139  #endif
 140  #ifdef EXT0_PID_PGAIN
 141  #error The PID system has changed. Please use the new float number options!
 142  #endif
 143  // ####################################################################################
 144  // #          No configuration below this line - just some errorchecking              #
 145  // ####################################################################################
 146  #ifdef SUPPORT_MAX6675
 147  #if !defined SCK_PIN || !defined MOSI_PIN || !defined MISO_PIN
 148  #error For MAX6675 support, you need to define SCK_PIN, MISO_PIN and MOSI_PIN in pins.h
 149  #endif
 150  #endif
 151  #if X_STEP_PIN<0 || Y_STEP_PIN<0 || Z_STEP_PIN<0
 152  #error One of the following pins is not assigned: X_STEP_PIN,Y_STEP_PIN,Z_STEP_PIN
 153  #endif
 154  #if EXT0_STEP_PIN<0 && NUM_EXTRUDER>0
 155  #error EXT0_STEP_PIN not set to a pin number.
 156  #endif
 157  #if EXT0_DIR_PIN<0 && NUM_EXTRUDER>0
 158  #error EXT0_DIR_PIN not set to a pin number.
 159  #endif
 160  #if MOVE_CACHE_SIZE<4
 161  #error MOVE_CACHE_SIZE must be at least 5
 162  #endif
 163  
 164  #if DRIVE_SYSTEM==3
 165  #define SIN_60 0.8660254037844386
 166  #define COS_60 0.5
 167  #define DELTA_DIAGONAL_ROD_STEPS (AXIS_STEPS_PER_MM * DELTA_DIAGONAL_ROD)
 168  #define DELTA_DIAGONAL_ROD_STEPS_SQUARED (DELTA_DIAGONAL_ROD_STEPS * DELTA_DIAGONAL_ROD_STEPS)
 169  #define DELTA_ZERO_OFFSET_STEPS (AXIS_STEPS_PER_MM * DELTA_ZERO_OFFSET)
 170  #define DELTA_RADIUS_STEPS (AXIS_STEPS_PER_MM * DELTA_RADIUS)
 171  
 172  #define DELTA_TOWER1_X_STEPS -SIN_60*DELTA_RADIUS_STEPS
 173  #define DELTA_TOWER1_Y_STEPS -COS_60*DELTA_RADIUS_STEPS
 174  #define DELTA_TOWER2_X_STEPS SIN_60*DELTA_RADIUS_STEPS
 175  #define DELTA_TOWER2_Y_STEPS -COS_60*DELTA_RADIUS_STEPS
 176  #define DELTA_TOWER3_X_STEPS 0.0
 177  #define DELTA_TOWER3_Y_STEPS DELTA_RADIUS_STEPS
 178  
 179  #define NUM_AXIS 4
 180  #define X_AXIS 0
 181  #define Y_AXIS 1
 182  #define Z_AXIS 2
 183  #define E_AXIS 3
 184  
 185  #endif
 186  
 187  #define OVERFLOW_PERIODICAL  (int)(F_CPU/(TIMER0_PRESCALE*40))
 188  // RAM usage of variables: Non RAMPS 114+MOVE_CACHE_SIZE*59+printer_state(32) = 382 Byte with MOVE_CACHE_SIZE=4
 189  // RAM usage RAMPS adds: 96
 190  // RAM usage SD Card:
 191  byte unit_inches = 0; ///< 0 = Units are mm, 1 = units are inches.
 192  //Stepper Movement Variables
 193  float axis_steps_per_unit[4] = {XAXIS_STEPS_PER_MM,YAXIS_STEPS_PER_MM,ZAXIS_STEPS_PER_MM,1}; ///< Number of steps per mm needed.
 194  float inv_axis_steps_per_unit[4]; ///< Inverse of axis_steps_per_unit for faster conversion
 195  float max_feedrate[4] = {MAX_FEEDRATE_X, MAX_FEEDRATE_Y, MAX_FEEDRATE_Z}; ///< Maximum allowed feedrate.
 196  float homing_feedrate[3] = {HOMING_FEEDRATE_X, HOMING_FEEDRATE_Y, HOMING_FEEDRATE_Z};
 197  byte STEP_PIN[3] = {X_STEP_PIN, Y_STEP_PIN, Z_STEP_PIN};
 198  #ifdef RAMP_ACCELERATION
 199  //  float max_start_speed_units_per_second[4] = MAX_START_SPEED_UNITS_PER_SECOND; ///< Speed we can use, without acceleration.
 200    long max_acceleration_units_per_sq_second[4] = {MAX_ACCELERATION_UNITS_PER_SQ_SECOND_X,MAX_ACCELERATION_UNITS_PER_SQ_SECOND_Y,MAX_ACCELERATION_UNITS_PER_SQ_SECOND_Z}; ///< X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts
 201    long max_travel_acceleration_units_per_sq_second[4] = {MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_X,MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_Y,MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_Z}; ///< X, Y, Z max acceleration in mm/s^2 for travel moves
 202    /** Acceleration in steps/s^3 in printing mode.*/
 203    unsigned long axis_steps_per_sqr_second[4];
 204    /** Acceleration in steps/s^2 in movement mode.*/
 205    unsigned long axis_travel_steps_per_sqr_second[4];
 206  #endif
 207  #if DRIVE_SYSTEM==3
 208  DeltaSegment segments[DELTA_CACHE_SIZE];
 209  unsigned int delta_segment_write_pos = 0; // Position where we write the next cached delta move
 210  volatile unsigned int  delta_segment_count = 0; // Number of delta moves cached 0 = nothing in cache
 211  byte lastMoveID = 0; // Last move ID
 212  #endif
 213  PrinterState printer_state;
 214  byte relative_mode = false;  ///< Determines absolute (false) or relative Coordinates (true).
 215  byte relative_mode_e = false;  ///< Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode.
 216  byte debug_level = 6; ///< Bitfield defining debug output. 1 = echo, 2 = info, 4 = error, 8 = dry run., 16 = Only communication, 32 = No moves
 217  
 218  //Inactivity shutdown variables
 219  unsigned long previous_millis_cmd = 0;
 220  unsigned long max_inactive_time = MAX_INACTIVE_TIME*1000L;
 221  unsigned long stepper_inactive_time = STEPPER_INACTIVE_TIME*1000L;
 222  PrintLine lines[MOVE_CACHE_SIZE]; ///< Cache for print moves.
 223  PrintLine *cur = 0;               ///< Current printing line
 224  byte lines_write_pos=0;           ///< Position where we write the next cached line move.
 225  volatile byte lines_count=0;      ///< Number of lines cached 0 = nothing to do.
 226  byte lines_pos=0;                 ///< Position for executing line movement.
 227  long baudrate = BAUDRATE;         ///< Communication speed rate.
 228  #ifdef USE_ADVANCE
 229  #ifdef ENABLE_QUADRATIC_ADVANCE
 230  int maxadv=0;
 231  #endif
 232  int maxadv2=0;
 233  float maxadvspeed=0;
 234  #endif
 235  byte pwm_pos[NUM_EXTRUDER+3]; // 0-NUM_EXTRUDER = Heater 0-NUM_EXTRUDER of extruder, NUM_EXTRUDER = Heated bed, NUM_EXTRUDER+1 Board fan, NUM_EXTRUDER+2 = Fan
 236  
 237  int waitRelax=0; // Delay filament relax at the end of print, could be a simple timeout
 238  #ifdef USE_OPS
 239  byte printmoveSeen=0;
 240  #endif
 241  #ifdef DEBUG_FREE_MEMORY
 242  int lowest_ram=16384;
 243  int lowest_send=16384;
 244  
 245  void check_mem() {
 246  BEGIN_INTERRUPT_PROTECTED
 247    uint8_t * heapptr, * stackptr;
 248    heapptr = (uint8_t *)malloc(4);          // get heap pointer
 249    free(heapptr);      // free up the memory again (sets heapptr to 0)
 250    stackptr =  (uint8_t *)(SP);           // save value of stack pointer
 251    int newfree = (int)stackptr-(int)heapptr;
 252    if(newfree<lowest_ram) {
 253       lowest_ram = newfree;
 254    }
 255  END_INTERRUPT_PROTECTED
 256  }
 257  void send_mem() {
 258    if(lowest_send>lowest_ram) {
 259      lowest_send = lowest_ram;
 260      out.println_int_P(PSTR("Free RAM:"),lowest_ram);
 261    }
 262  }
 263  #endif
 264  
 265  
 266  void update_extruder_flags() {
 267    printer_state.flag0 &= ~PRINTER_FLAG0_SEPERATE_EXTRUDER_INT;
 268  #if USE_OPS==1
 269    if(printer_state.opsMode!=0) {
 270      printer_state.flag0 |= PRINTER_FLAG0_SEPERATE_EXTRUDER_INT;
 271    }
 272  #endif
 273  #if defined(USE_ADVANCE)
 274    for(byte i=0;i<NUM_EXTRUDER;i++) {
 275      if(extruder[i].advanceL!=0) {
 276        printer_state.flag0 |= PRINTER_FLAG0_SEPERATE_EXTRUDER_INT;
 277      }
 278  #ifdef ENABLE_QUADRATIC_ADVANCE
 279      if(extruder[i].advanceK!=0) printer_state.flag0 |= PRINTER_FLAG0_SEPERATE_EXTRUDER_INT;
 280  #endif
 281    }
 282  #endif
 283  }
 284  
 285  void update_ramps_parameter() {
 286  #if DRIVE_SYSTEM==3
 287    printer_state.zMaxSteps = axis_steps_per_unit[0]*(printer_state.zLength - printer_state.zMin);
 288    long cart[3], delta[3];
 289    cart[0] = cart[1] = 0;
 290    cart[2] = printer_state.zMaxSteps;
 291    calculate_delta(cart, delta);
 292    printer_state.maxDeltaPositionSteps = delta[0];
 293    printer_state.xMaxSteps = (long)(axis_steps_per_unit[0]*(printer_state.xMin+printer_state.xLength));
 294    printer_state.yMaxSteps = (long)(axis_steps_per_unit[1]*(printer_state.yMin+printer_state.yLength));
 295    printer_state.xMinSteps = (long)(axis_steps_per_unit[0]*printer_state.xMin);
 296    printer_state.yMinSteps = (long)(axis_steps_per_unit[1]*printer_state.yMin);
 297    printer_state.zMinSteps = 0;
 298  #else
 299    printer_state.xMaxSteps = (long)(axis_steps_per_unit[0]*(printer_state.xMin+printer_state.xLength));
 300    printer_state.yMaxSteps = (long)(axis_steps_per_unit[1]*(printer_state.yMin+printer_state.yLength));
 301    printer_state.zMaxSteps = (long)(axis_steps_per_unit[2]*(printer_state.zMin+printer_state.zLength));
 302    printer_state.xMinSteps = (long)(axis_steps_per_unit[0]*printer_state.xMin);
 303    printer_state.yMinSteps = (long)(axis_steps_per_unit[1]*printer_state.yMin);
 304    printer_state.zMinSteps = (long)(axis_steps_per_unit[2]*printer_state.zMin);
 305    // For which directions do we need backlash compensation
 306  #if ENABLE_BACKLASH_COMPENSATION
 307    printer_state.backlashDir &= 7;
 308    if(printer_state.backlashX!=0) printer_state.backlashDir |= 8;
 309    if(printer_state.backlashY!=0) printer_state.backlashDir |= 16;
 310    if(printer_state.backlashZ!=0) printer_state.backlashDir |= 32;
 311    /*if(printer_state.backlashDir & 56)
 312      OUT_P_LN("Backlash compensation enabled");
 313    else
 314      OUT_P_LN("Backlash compensation disabled");*/
 315  #endif
 316  #endif
 317    for(byte i=0;i<4;i++) {
 318      inv_axis_steps_per_unit[i] = 1.0f/axis_steps_per_unit[i];
 319  #ifdef RAMP_ACCELERATION
 320      /** Acceleration in steps/s^3 in printing mode.*/
 321      axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
 322      /** Acceleration in steps/s^2 in movement mode.*/
 323      axis_travel_steps_per_sqr_second[i] = max_travel_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
 324  #endif
 325    }
 326    update_extruder_flags();
 327  }
 328  
 329  /** \brief Setup of the hardware
 330  
 331  Sets the output and input pins in accordance to your configuration. Initializes the serial interface.
 332  Interrupt routines to measure analog values and for the stepper timerloop are started.
 333  */
 334  void setup()
 335  {
 336  #ifdef ANALYZER
 337  // Channel->pin assignments
 338  #if ANALYZER_CH0>=0
 339  SET_OUTPUT(ANALYZER_CH0);
 340  #endif
 341  #if ANALYZER_CH1>=0
 342  SET_OUTPUT(ANALYZER_CH1);
 343  #endif
 344  #if ANALYZER_CH2>=0
 345  SET_OUTPUT(ANALYZER_CH2);
 346  #endif
 347  #if ANALYZER_CH3>=0
 348  SET_OUTPUT(ANALYZER_CH3);
 349  #endif
 350  #if ANALYZER_CH4>=0
 351  SET_OUTPUT(ANALYZER_CH4);
 352  #endif
 353  #if ANALYZER_CH5>=0
 354  SET_OUTPUT(ANALYZER_CH5);
 355  #endif
 356  #if ANALYZER_CH6>=0
 357  SET_OUTPUT(ANALYZER_CH6);
 358  #endif
 359  #if ANALYZER_CH7>=0
 360  SET_OUTPUT(ANALYZER_CH7);
 361  #endif
 362  #endif
 363  
 364  #if defined(ENABLE_POWER_ON_STARTUP) && PS_ON_PIN>-1
 365    SET_OUTPUT(PS_ON_PIN); //GND
 366    WRITE(PS_ON_PIN, LOW);
 367  #endif
 368  
 369    //Initialize Step Pins
 370    SET_OUTPUT(X_STEP_PIN);
 371    SET_OUTPUT(Y_STEP_PIN);
 372    SET_OUTPUT(Z_STEP_PIN);
 373    
 374  
 375    //Initialize Dir Pins
 376  #if X_DIR_PIN>-1
 377    SET_OUTPUT(X_DIR_PIN);
 378  #endif
 379  #if Y_DIR_PIN>-1
 380    SET_OUTPUT(Y_DIR_PIN);
 381  #endif
 382  #if Z_DIR_PIN>-1
 383    SET_OUTPUT(Z_DIR_PIN);
 384  #endif
 385  
 386    //Steppers default to disabled.
 387  #if X_ENABLE_PIN > -1
 388    if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH);
 389    SET_OUTPUT(X_ENABLE_PIN);
 390  #endif
 391  #if Y_ENABLE_PIN > -1
 392    if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH);
 393    SET_OUTPUT(Y_ENABLE_PIN);
 394  #endif
 395  #if Z_ENABLE_PIN > -1
 396    if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH);
 397    SET_OUTPUT(Z_ENABLE_PIN);
 398  #endif
 399  
 400    //endstop pullups
 401  #if X_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_X
 402    SET_INPUT(X_MIN_PIN);
 403  #if ENDSTOP_PULLUP_X_MIN
 404    WRITE(X_MIN_PIN,HIGH);
 405  #endif
 406  #endif
 407  #if Y_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_Y
 408    SET_INPUT(Y_MIN_PIN);
 409  #if ENDSTOP_PULLUP_Y_MIN
 410    WRITE(Y_MIN_PIN,HIGH);
 411  #endif
 412  #endif
 413  #if Z_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_Z
 414    SET_INPUT(Z_MIN_PIN);
 415  #if ENDSTOP_PULLUP_Z_MIN
 416    WRITE(Z_MIN_PIN,HIGH);
 417  #endif
 418  #endif
 419  #if X_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_X
 420    SET_INPUT(X_MAX_PIN);
 421  #if ENDSTOP_PULLUP_X_MAX
 422    WRITE(X_MAX_PIN,HIGH);
 423  #endif
 424  #endif
 425  #if Y_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Y
 426    SET_INPUT(Y_MAX_PIN);
 427  #if ENDSTOP_PULLUP_Y_MAX
 428    WRITE(Y_MAX_PIN,HIGH);
 429  #endif
 430  #endif
 431  #if Z_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Z
 432    SET_INPUT(Z_MAX_PIN);
 433  #if ENDSTOP_PULLUP_Z_MAX
 434    WRITE(Z_MAX_PIN,HIGH);
 435  #endif
 436  #endif
 437  #if FAN_PIN>-1
 438    SET_OUTPUT(FAN_PIN);
 439    WRITE(FAN_PIN,LOW);
 440  #endif
 441  #if FAN_BOARD_PIN>-1
 442    SET_OUTPUT(FAN_BOARD_PIN);
 443    WRITE(FAN_BOARD_PIN,LOW);
 444  #endif
 445  #if EXT0_HEATER_PIN>-1
 446    SET_OUTPUT(EXT0_HEATER_PIN);
 447    WRITE(EXT0_HEATER_PIN,LOW);
 448  #endif
 449  #if defined(EXT1_HEATER_PIN) && EXT1_HEATER_PIN>-1
 450    SET_OUTPUT(EXT1_HEATER_PIN);
 451    WRITE(EXT1_HEATER_PIN,LOW);
 452  #endif
 453  #if defined(EXT2_HEATER_PIN) && EXT2_HEATER_PIN>-1
 454    SET_OUTPUT(EXT2_HEATER_PIN);
 455    WRITE(EXT2_HEATER_PIN,LOW);
 456  #endif
 457  #if defined(EXT3_HEATER_PIN) && EXT3_HEATER_PIN>-1
 458    SET_OUTPUT(EXT3_HEATER_PIN);
 459    WRITE(EXT3_HEATER_PIN,LOW);
 460  #endif
 461  #if defined(EXT4_HEATER_PIN) && EXT4_HEATER_PIN>-1
 462    SET_OUTPUT(EXT4_HEATER_PIN);
 463    WRITE(EXT4_HEATER_PIN,LOW);
 464  #endif
 465  #if defined(EXT5_HEATER_PIN) && EXT5_HEATER_PIN>-1
 466    SET_OUTPUT(EXT5_HEATER_PIN);
 467    WRITE(EXT5_HEATER_PIN,LOW);
 468  #endif
 469  
 470  #ifdef XY_GANTRY
 471    printer_state.motorX = 0;
 472    printer_state.motorY = 0;
 473  #endif
 474  
 475  #if STEPPER_CURRENT_CONTROL!=CURRENT_CONTROL_MANUAL
 476    current_control_init(); // Set current if it is firmware controlled
 477  #endif
 478    microstep_init();
 479  
 480  #if USE_OPS==1
 481    printer_state.opsMode = OPS_MODE;
 482    printer_state.opsMinDistance = OPS_MIN_DISTANCE;
 483    printer_state.opsRetractDistance = OPS_RETRACT_DISTANCE;
 484    printer_state.opsRetractBacklash = OPS_RETRACT_BACKLASH;
 485    printer_state.filamentRetracted = false;
 486  #endif
 487    printer_state.feedrate = 50; ///< Current feedrate in mm/s.
 488    printer_state.feedrateMultiply = 100;
 489    printer_state.extrudeMultiply = 100; 
 490  #ifdef USE_ADVANCE
 491  #ifdef ENABLE_QUADRATIC_ADVANCE
 492    printer_state.advance_executed = 0;
 493  #endif
 494    printer_state.advance_steps_set = 0;
 495    printer_state.advance_lin_set = 0;
 496  #endif
 497    for(byte i=0;i<NUM_EXTRUDER+3;i++) pwm_pos[i]=0;
 498    printer_state.currentPositionSteps[0] = printer_state.currentPositionSteps[1] = printer_state.currentPositionSteps[2] = printer_state.currentPositionSteps[3] = 0;
 499  #if DRIVE_SYSTEM==3
 500    calculate_delta(printer_state.currentPositionSteps, printer_state.currentDeltaPositionSteps);
 501  #endif
 502    printer_state.maxJerk = MAX_JERK;
 503    printer_state.maxZJerk = MAX_ZJERK;
 504    printer_state.interval = 5000;
 505    printer_state.stepper_loops = 1;
 506    printer_state.msecondsPrinting = 0;
 507    printer_state.filamentPrinted = 0;
 508    printer_state.flag0 = PRINTER_FLAG0_STEPPER_DISABLED;
 509    printer_state.xLength = X_MAX_LENGTH;
 510    printer_state.yLength = Y_MAX_LENGTH;
 511    printer_state.zLength = Z_MAX_LENGTH;
 512    printer_state.xMin = X_MIN_POS;
 513    printer_state.yMin = Y_MIN_POS;
 514    printer_state.zMin = Z_MIN_POS;
 515    printer_state.waslasthalfstepping = 0;
 516  #if ENABLE_BACKLASH_COMPENSATION
 517    printer_state.backlashX = X_BACKLASH;
 518    printer_state.backlashY = Y_BACKLASH;
 519    printer_state.backlashZ = Z_BACKLASH;
 520    printer_state.backlashDir = 0;
 521  #endif  
 522    epr_init_baudrate();
 523    RFSERIAL.begin(baudrate);
 524    out.println_P(PSTR("start"));
 525    UI_INITIALIZE;
 526    
 527    // Check startup - does nothing if bootloader sets MCUSR to 0
 528    byte mcu = MCUSR;
 529    if(mcu & 1) out.println_P(PSTR("PowerUp"));
 530    if(mcu & 2) out.println_P(PSTR("External Reset"));
 531    if(mcu & 4) out.println_P(PSTR("Brown out Reset"));
 532    if(mcu & 8) out.println_P(PSTR("Watchdog Reset"));
 533    if(mcu & 32) out.println_P(PSTR("Software Reset"));
 534    MCUSR=0;
 535    
 536    initExtruder();
 537    epr_init(); // Read settings from eeprom if wanted
 538    update_ramps_parameter();
 539  
 540  #if SDSUPPORT
 541  
 542    sd.initsd();
 543  
 544  #endif
 545  #if USE_OPS==1 || defined(USE_ADVANCE)
 546    EXTRUDER_TCCR = 0; // need Normal not fastPWM set by arduino init
 547    EXTRUDER_TIMSK |= (1<<EXTRUDER_OCIE); // Activate compa interrupt on timer 0
 548  #endif
 549    PWM_TCCR = 0;  // Setup PWM interrupt
 550    PWM_OCR = 64;
 551    PWM_TIMSK |= (1<<PWM_OCIE);
 552  
 553    TCCR1A = 0;  // Steup timer 1 interrupt to no prescale CTC mode
 554    TCCR1C = 0;
 555    TIMSK1 = 0;
 556    TCCR1B =  (_BV(WGM12) | _BV(CS10)); // no prescaler == 0.0625 usec tick | 001 = clk/1
 557    OCR1A=65500; //start off with a slow frequency.
 558    TIMSK1 |= (1<<OCIE1A); // Enable interrupt
 559  }
 560  
 561  void defaultLoopActions() {
 562    //check heater every n milliseconds
 563    check_periodical();
 564    UI_MEDIUM; // do check encoder
 565    unsigned long curtime = millis();
 566    if(lines_count)
 567      previous_millis_cmd = curtime;
 568    if(max_inactive_time!=0 && (curtime-previous_millis_cmd) >  max_inactive_time ) kill(false);
 569    if(stepper_inactive_time!=0 && (curtime-previous_millis_cmd) >  stepper_inactive_time ) { kill(true); }
 570  #if defined(SDCARDDETECT) && SDCARDDETECT>-1 && defined(SDSUPPORT) && SDSUPPORT
 571    sd.automount();
 572  #endif
 573    //void finishNextSegment();
 574    DEBUG_MEMORY;
 575  }
 576  /**
 577    Main processing loop. It checks perodically for new commands, checks temperatures
 578    and executes new incoming commands.
 579  */
 580  void loop()
 581  {
 582    gcode_read_serial();
 583    GCode *code = gcode_next_command();
 584    //UI_SLOW; // do longer timed user interface action
 585    UI_MEDIUM; // do check encoder
 586    if(code){
 587  #if SDSUPPORT
 588      if(sd.savetosd){
 589          if(!(GCODE_HAS_M(code) && code->M==29)) { // still writing to file
 590              sd.write_command(code);
 591          } else {
 592              sd.finishWrite();
 593          }
 594  #ifdef ECHO_ON_EXECUTE
 595          if(DEBUG_ECHO) {
 596             OUT_P("Echo:");
 597             gcode_print_command(code);
 598             out.println();
 599          }
 600  #endif
 601          gcode_command_finished(code);
 602      } else {
 603          process_command(code,true);
 604      }
 605  #else
 606      process_command(code,true);
 607  #endif
 608    }
 609    defaultLoopActions();
 610  }
 611  
 612  
 613  /** \brief Optimized division
 614  
 615  Normally the C compiler will compute a long/long division, which takes ~670 Ticks.
 616  This version is optimized for a 16 bit dividend and recognises the special cases
 617  of a 24 bit and 16 bit dividend, which offen, but not always occur in updating the
 618  interval.
 619  */
 620  inline long Div4U2U(unsigned long a,unsigned int b) {
 621  #if CPU_ARCH==ARCH_AVR
 622    // r14/r15 remainder
 623    // r16 counter
 624    __asm__ __volatile__ (
 625    "clr r14 \n\t"
 626    "sub r15,r15 \n\t"
 627    "tst %D0 \n\t"
 628    "brne do32%= \n\t"
 629    "tst %C0 \n\t"
 630    "breq donot24%= \n\t"
 631    "rjmp do24%= \n\t"
 632    "donot24%=:" "ldi r16,17 \n\t" // 16 Bit divide
 633    "d16u_1%=:" "rol %A0 \n\t"
 634    "rol %B0 \n\t"
 635    "dec r16 \n\t"
 636    "brne	d16u_2%= \n\t"
 637    "rjmp end%= \n\t"
 638    "d16u_2%=:" "rol r14 \n\t"
 639    "rol r15 \n\t"
 640    "sub r14,%A2 \n\t"
 641    "sbc r15,%B2 \n\t"
 642    "brcc	d16u_3%= \n\t"
 643    "add r14,%A2 \n\t"
 644    "adc r15,%B2 \n\t"
 645    "clc \n\t"
 646    "rjmp d16u_1%= \n\t"
 647    "d16u_3%=:" "sec \n\t"
 648    "rjmp d16u_1%= \n\t"
 649    "do32%=:" // divide full 32 bit
 650    "rjmp do32B%= \n\t"
 651    "do24%=:" // divide 24 bit
 652  
 653    "ldi r16,25 \n\t" // 24 Bit divide
 654    "d24u_1%=:" "rol %A0 \n\t"
 655    "rol %B0 \n\t"
 656    "rol %C0 \n\t"
 657    "dec r16 \n\t"
 658    "brne	d24u_2%= \n\t"
 659    "rjmp end%= \n\t"
 660    "d24u_2%=:" "rol r14 \n\t"
 661    "rol r15 \n\t"
 662    "sub r14,%A2 \n\t"
 663    "sbc r15,%B2 \n\t"
 664    "brcc	d24u_3%= \n\t"
 665    "add r14,%A2 \n\t"
 666    "adc r15,%B2 \n\t"
 667    "clc \n\t"
 668    "rjmp d24u_1%= \n\t"
 669    "d24u_3%=:" "sec \n\t"
 670    "rjmp d24u_1%= \n\t"
 671  
 672    "do32B%=:" // divide full 32 bit
 673  
 674    "ldi r16,33 \n\t" // 32 Bit divide
 675    "d32u_1%=:" "rol %A0 \n\t"
 676    "rol %B0 \n\t"
 677    "rol %C0 \n\t"
 678    "rol %D0 \n\t"
 679    "dec r16 \n\t"
 680    "brne	d32u_2%= \n\t"
 681    "rjmp end%= \n\t"
 682    "d32u_2%=:" "rol r14 \n\t"
 683    "rol r15 \n\t"
 684    "sub r14,%A2 \n\t"
 685    "sbc r15,%B2 \n\t"
 686    "brcc	d32u_3%= \n\t"
 687    "add r14,%A2 \n\t"
 688    "adc r15,%B2 \n\t"
 689    "clc \n\t"
 690    "rjmp d32u_1%= \n\t"
 691    "d32u_3%=:" "sec \n\t"
 692    "rjmp d32u_1%= \n\t"
 693  
 694    "end%=:" // end
 695    :"=&r"(a)
 696    :"0"(a),"r"(b)
 697    :"r14","r15","r16"
 698    );
 699   return a;
 700  #else
 701    return a/b;
 702  #endif
 703  }
 704  
 705  const uint16_t fast_div_lut[17] PROGMEM = {0,F_CPU/4096,F_CPU/8192,F_CPU/12288,F_CPU/16384,F_CPU/20480,F_CPU/24576,F_CPU/28672,F_CPU/32768,F_CPU/36864
 706    ,F_CPU/40960,F_CPU/45056,F_CPU/49152,F_CPU/53248,F_CPU/57344,F_CPU/61440,F_CPU/65536};
 707  
 708  const uint16_t slow_div_lut[257] PROGMEM = {0,F_CPU/32,F_CPU/64,F_CPU/96,F_CPU/128,F_CPU/160,F_CPU/192,F_CPU/224,F_CPU/256,F_CPU/288,F_CPU/320,F_CPU/352
 709   ,F_CPU/384,F_CPU/416,F_CPU/448,F_CPU/480,F_CPU/512,F_CPU/544,F_CPU/576,F_CPU/608,F_CPU/640,F_CPU/672,F_CPU/704,F_CPU/736,F_CPU/768,F_CPU/800,F_CPU/832
 710   ,F_CPU/864,F_CPU/896,F_CPU/928,F_CPU/960,F_CPU/992,F_CPU/1024,F_CPU/1056,F_CPU/1088,F_CPU/1120,F_CPU/1152,F_CPU/1184,F_CPU/1216,F_CPU/1248,F_CPU/1280,F_CPU/1312
 711   ,F_CPU/1344,F_CPU/1376,F_CPU/1408,F_CPU/1440,F_CPU/1472,F_CPU/1504,F_CPU/1536,F_CPU/1568,F_CPU/1600,F_CPU/1632,F_CPU/1664,F_CPU/1696,F_CPU/1728,F_CPU/1760,F_CPU/1792
 712   ,F_CPU/1824,F_CPU/1856,F_CPU/1888,F_CPU/1920,F_CPU/1952,F_CPU/1984,F_CPU/2016
 713   ,F_CPU/2048,F_CPU/2080,F_CPU/2112,F_CPU/2144,F_CPU/2176,F_CPU/2208,F_CPU/2240,F_CPU/2272,F_CPU/2304,F_CPU/2336,F_CPU/2368,F_CPU/2400
 714   ,F_CPU/2432,F_CPU/2464,F_CPU/2496,F_CPU/2528,F_CPU/2560,F_CPU/2592,F_CPU/2624,F_CPU/2656,F_CPU/2688,F_CPU/2720,F_CPU/2752,F_CPU/2784,F_CPU/2816,F_CPU/2848,F_CPU/2880
 715   ,F_CPU/2912,F_CPU/2944,F_CPU/2976,F_CPU/3008,F_CPU/3040,F_CPU/3072,F_CPU/3104,F_CPU/3136,F_CPU/3168,F_CPU/3200,F_CPU/3232,F_CPU/3264,F_CPU/3296,F_CPU/3328,F_CPU/3360
 716   ,F_CPU/3392,F_CPU/3424,F_CPU/3456,F_CPU/3488,F_CPU/3520,F_CPU/3552,F_CPU/3584,F_CPU/3616,F_CPU/3648,F_CPU/3680,F_CPU/3712,F_CPU/3744,F_CPU/3776,F_CPU/3808,F_CPU/3840
 717   ,F_CPU/3872,F_CPU/3904,F_CPU/3936,F_CPU/3968,F_CPU/4000,F_CPU/4032,F_CPU/4064
 718   ,F_CPU/4096,F_CPU/4128,F_CPU/4160,F_CPU/4192,F_CPU/4224,F_CPU/4256,F_CPU/4288,F_CPU/4320,F_CPU/4352,F_CPU/4384,F_CPU/4416,F_CPU/4448,F_CPU/4480,F_CPU/4512,F_CPU/4544
 719   ,F_CPU/4576,F_CPU/4608,F_CPU/4640,F_CPU/4672,F_CPU/4704,F_CPU/4736,F_CPU/4768,F_CPU/4800,F_CPU/4832,F_CPU/4864,F_CPU/4896,F_CPU/4928,F_CPU/4960,F_CPU/4992,F_CPU/5024
 720   ,F_CPU/5056,F_CPU/5088,F_CPU/5120,F_CPU/5152,F_CPU/5184,F_CPU/5216,F_CPU/5248,F_CPU/5280,F_CPU/5312,F_CPU/5344,F_CPU/5376,F_CPU/5408,F_CPU/5440,F_CPU/5472,F_CPU/5504
 721   ,F_CPU/5536,F_CPU/5568,F_CPU/5600,F_CPU/5632,F_CPU/5664,F_CPU/5696,F_CPU/5728,F_CPU/5760,F_CPU/5792,F_CPU/5824,F_CPU/5856,F_CPU/5888,F_CPU/5920,F_CPU/5952,F_CPU/5984
 722   ,F_CPU/6016,F_CPU/6048,F_CPU/6080,F_CPU/6112,F_CPU/6144,F_CPU/6176,F_CPU/6208,F_CPU/6240,F_CPU/6272,F_CPU/6304,F_CPU/6336,F_CPU/6368,F_CPU/6400,F_CPU/6432,F_CPU/6464
 723   ,F_CPU/6496,F_CPU/6528,F_CPU/6560,F_CPU/6592,F_CPU/6624,F_CPU/6656,F_CPU/6688,F_CPU/6720,F_CPU/6752,F_CPU/6784,F_CPU/6816,F_CPU/6848,F_CPU/6880,F_CPU/6912,F_CPU/6944
 724   ,F_CPU/6976,F_CPU/7008,F_CPU/7040,F_CPU/7072,F_CPU/7104,F_CPU/7136,F_CPU/7168,F_CPU/7200,F_CPU/7232,F_CPU/7264,F_CPU/7296,F_CPU/7328,F_CPU/7360,F_CPU/7392,F_CPU/7424
 725   ,F_CPU/7456,F_CPU/7488,F_CPU/7520,F_CPU/7552,F_CPU/7584,F_CPU/7616,F_CPU/7648,F_CPU/7680,F_CPU/7712,F_CPU/7744,F_CPU/7776,F_CPU/7808,F_CPU/7840,F_CPU/7872,F_CPU/7904
 726   ,F_CPU/7936,F_CPU/7968,F_CPU/8000,F_CPU/8032,F_CPU/8064,F_CPU/8096,F_CPU/8128,F_CPU/8160,F_CPU/8192
 727   };
 728  /** \brief approximates division of F_CPU/divisor
 729  
 730  In the stepper interrupt a division is needed, which is a slow operation.
 731  The result is used for timer calculation where small errors are ok. This
 732  function uses lookup tables to find a fast approximation of the result.
 733  
 734  */
 735  long CPUDivU2(unsigned int divisor) {
 736  #if CPU_ARCH==ARCH_AVR
 737    long res;
 738    unsigned short table;
 739    if(divisor<8192) {
 740      if(divisor<512) {
 741        if(divisor<10) divisor = 10;
 742        return Div4U2U(F_CPU,divisor); // These entries have overflows in lookuptable!
 743      }
 744      table = (unsigned short)&slow_div_lut[0];
 745      __asm__ __volatile__( // needs 64 ticks neu 49 Ticks
 746      "mov r18,%A1 \n\t"
 747      "andi r18,31 \n\t"  // divisor & 31 in r18
 748      "lsr %B1 \n\t" // divisor >> 4
 749      "ror %A1 \n\t"
 750      "lsr %B1 \n\t"
 751      "ror %A1 \n\t"
 752      "lsr %B1 \n\t"
 753      "ror %A1 \n\t"
 754      "lsr %B1 \n\t"
 755      "ror %A1 \n\t"
 756      "andi %A1,254 \n\t"
 757      "add %A2,%A1 \n\t" // table+divisor>>3
 758      "adc %B2,%B1 \n\t"
 759      "lpm %A0,Z+ \n\t" // y0 in res
 760      "lpm %B0,Z+ \n\t"  // %C0,%D0 are 0
 761      "movw r4,%A0 \n\t" // y0 nach gain (r4-r5)
 762      "lpm r0,Z+ \n\t" // gain = gain-y1
 763      "sub r4,r0 \n\t"
 764      "lpm r0,Z+ \n\t"
 765      "sbc r5,r0 \n\t"
 766      "mul r18,r4 \n\t" // gain*(divisor & 31)
 767      "movw %A1,r0 \n\t" // divisor not needed any more, use for byte 0,1 of result
 768      "mul r18,r5 \n\t"
 769      "add %B1,r0 \n\t"
 770      "mov %A2,r1 \n\t"
 771      "lsl %A1 \n\t"
 772      "rol %B1 \n\t"
 773      "rol %A2 \n\t"
 774      "lsl %A1 \n\t"
 775      "rol %B1 \n\t"
 776      "rol %A2 \n\t"
 777      "lsl %A1 \n\t"
 778      "rol %B1 \n\t"
 779      "rol %A2 \n\t"
 780      "sub %A0,%B1 \n\t"
 781      "sbc %B0,%A2 \n\t"
 782      "clr %C0 \n\t"
 783      "clr %D0 \n\t"
 784      "clr r1 \n\t"
 785      : "=&r" (res),"=&d"(divisor),"=&z"(table) : "1"(divisor),"2"(table) : "r18","r4","r5");
 786      return res;
 787      /*unsigned short adr0 = (unsigned short)&slow_div_lut+(divisor>>4)&1022;
 788      long y0=	pgm_read_dword_near(adr0);
 789      long gain = y0-pgm_read_dword_near(adr0+2);
 790      return y0-((gain*(divisor & 31))>>5);*/
 791    } else {
 792      table = (unsigned short)&fast_div_lut[0];
 793      __asm__ __volatile__( // needs 49 ticks
 794      "movw r18,%A1 \n\t"
 795      "andi r19,15 \n\t"  // divisor & 4095 in r18,r19
 796      "lsr %B1 \n\t" // divisor >> 3, then %B1 is 2*(divisor >> 12)
 797      "lsr %B1 \n\t"
 798      "lsr %B1 \n\t"
 799      "andi %B1,254 \n\t"
 800      "add %A2,%B1 \n\t" // table+divisor>>11
 801      "adc %B2,r1 \n\t" //
 802      "lpm %A0,Z+ \n\t" // y0 in res
 803      "lpm %B0,Z+ \n\t"
 804      "movw r4,%A0 \n\t" // y0 to gain (r4-r5)
 805      "lpm r0,Z+ \n\t" // gain = gain-y1
 806      "sub r4,r0 \n\t"
 807      "lpm r0,Z+ \n\t"
 808      "sbc r5,r0 \n\t" // finished - result has max. 16 bit
 809      "mul r18,r4 \n\t" // gain*(divisor & 4095)
 810      "movw %A1,r0 \n\t" // divisor not needed any more, use for byte 0,1 of result
 811      "mul r19,r5 \n\t"
 812      "mov %A2,r0 \n\t" // %A2 = byte 3 of result
 813      "mul r18,r5 \n\t"
 814      "add %B1,r0 \n\t"
 815      "adc %A2,r1 \n\t"
 816      "mul r19,r4 \n\t"
 817      "add %B1,r0 \n\t"
 818      "adc %A2,r1 \n\t"
 819      "andi %B1,240 \n\t" // >> 12
 820      "swap %B1 \n\t"
 821      "swap %A2 \r\n"
 822      "mov %A1,%A2 \r\n"
 823      "andi %A1,240 \r\n"
 824      "or %B1,%A1 \r\n"
 825      "andi %A2,15 \r\n"
 826      "sub %A0,%B1 \n\t"
 827      "sbc %B0,%A2 \n\t"
 828      "clr %C0 \n\t"
 829      "clr %D0 \n\t"
 830      "clr r1 \n\t"
 831      : "=&r" (res),"=&d"(divisor),"=&z"(table) : "1"(divisor),"2"(table) : "r18","r19","r4","r5");
 832      return res;
 833      /*
 834      // The asm mimics the following code
 835      unsigned short adr0 = (unsigned short)&fast_div_lut+(divisor>>11)&254;
 836      unsigned short y0=	pgm_read_word_near(adr0);
 837      unsigned short gain = y0-pgm_read_word_near(adr0+2);
 838      return y0-(((long)gain*(divisor & 4095))>>12);*/
 839  #else
 840    return F_CPU/divisor;
 841  #endif
 842    }
 843  }
 844  
 845  /**
 846    \brief Sets the destination coordinates to values stored in com.
 847  
 848    For the computation of the destination, the following facts are considered:
 849    - Are units inches or mm.
 850    - Reltive or absolute positioning with special case only extruder relative.
 851    - Offset in x and y direction for multiple extruder support.
 852  */
 853  byte get_coordinates(GCode *com)
 854  {
 855    register long p;
 856    register byte r=0;
 857    if(lines_count==0) {
 858      UI_STATUS(UI_TEXT_PRINTING);
 859    }
 860    if(GCODE_HAS_X(com)) {
 861      r = 1;
 862      if(unit_inches)
 863        p = com->X*25.4*axis_steps_per_unit[0];
 864      else
 865        p = com->X*axis_steps_per_unit[0];
 866      if(relative_mode)
 867          printer_state.destinationSteps[0] = printer_state.currentPositionSteps[0]+p;
 868      else
 869          printer_state.destinationSteps[0] = p+printer_state.offsetX;
 870    } else printer_state.destinationSteps[0] = printer_state.currentPositionSteps[0];
 871    if(GCODE_HAS_Y(com)) {
 872      r = 1;
 873      if(unit_inches)
 874        p = com->Y*25.4*axis_steps_per_unit[1];
 875      else
 876        p = com->Y*axis_steps_per_unit[1];
 877      if(relative_mode)
 878          printer_state.destinationSteps[1] = printer_state.currentPositionSteps[1]+p;
 879      else
 880          printer_state.destinationSteps[1] = p+printer_state.offsetY;
 881    } else printer_state.destinationSteps[1] = printer_state.currentPositionSteps[1];
 882    if(GCODE_HAS_Z(com)) {
 883      r = 1;
 884      if(unit_inches)
 885        p = com->Z*25.4*axis_steps_per_unit[2];
 886      else
 887        p = com->Z*axis_steps_per_unit[2];
 888      if(relative_mode) {
 889          printer_state.destinationSteps[2] = printer_state.currentPositionSteps[2]+p;
 890      } else {
 891          printer_state.destinationSteps[2] = p;
 892      }
 893    } else printer_state.destinationSteps[2] = printer_state.currentPositionSteps[2];
 894    if(GCODE_HAS_E(com) && !DEBUG_DRYRUN) {
 895      if(unit_inches)
 896        p = com->E*25.4*axis_steps_per_unit[3];
 897      else
 898        p = com->E*axis_steps_per_unit[3];
 899      if(relative_mode || relative_mode_e)
 900          printer_state.destinationSteps[3] = printer_state.currentPositionSteps[3]+p;
 901      else
 902          printer_state.destinationSteps[3] = p;
 903    } else printer_state.destinationSteps[3] = printer_state.currentPositionSteps[3];
 904    if(GCODE_HAS_F(com)) {
 905      if(com->F < 1)
 906        printer_state.feedrate = 1;
 907      else
 908        if(unit_inches)
 909          printer_state.feedrate = com->F*0.0042333f*(float)printer_state.feedrateMultiply;  // Factor is 25.5/60/100
 910        else
 911          printer_state.feedrate = com->F*(float)printer_state.feedrateMultiply*0.00016666666f;
 912    }
 913    return r || (GCODE_HAS_E(com) && printer_state.destinationSteps[3]!=printer_state.currentPositionSteps[3]); // ignore unproductive moves
 914  }
 915  inline unsigned int ComputeV(long timer,long accel) {
 916  #if CPU_ARCH==ARCH_AVR
 917    unsigned int res;
 918    // 38 Ticks
 919    __asm__ __volatile__ ( // 0 = res, 1 = timer, 2 = accel %D2=0 ,%A1 are unused is free  
 920       // Result LSB first: %A0, %B0, %A1
 921       "mul %B1,%A2 \n\t"
 922       "mov %A0,r1 \n\t"
 923       "mul %B1,%C2 \n\t"
 924       "mov %B0,r0 \n\t"
 925       "mov %A1,r1 \n\t"
 926       "mul %B1,%B2 \n\t"
 927       "add %A0,r0 \n\t"
 928       "adc %B0,r1 \n\t"
 929       "adc %A1,%D2 \n\t"
 930       "mul %C1,%A2 \n\t"
 931       "add %A0,r0 \n\t"
 932       "adc %B0,r1 \n\t"
 933       "adc %A1,%D2 \n\t"
 934       "mul %C1,%B2 \n\t"
 935       "add %B0,r0 \n\t"
 936       "adc %A1,r1 \n\t"
 937       "mul %D1,%A2 \n\t"
 938       "add %B0,r0 \n\t"
 939       "adc %A1,r1 \n\t"
 940       "mul %C1,%C2 \n\t"
 941       "add %A1,r0 \n\t"
 942       "mul %D1,%B2 \n\t"
 943       "add %A1,r0 \n\t"
 944       "lsr %A1 \n\t"
 945       "ror %B0 \n\t"
 946       "ror %A0 \n\t"
 947       "lsr %A1 \n\t"
 948       "ror %B0 \n\t"
 949       "ror %A0 \n\t"
 950       "clr r1 \n\t"
 951    :"=&r"(res),"=r"(timer),"=r"(accel)
 952    :"1"(timer),"2"(accel)
 953    : );
 954    // unsigned int v = ((timer>>8)*cur->accel)>>10;
 955    return res;
 956  #else
 957    return ((timer>>8)*accel)>>10;
 958  #endif
 959  }
 960  // Multiply two 16 bit values and return 32 bit result
 961  inline unsigned long mulu6xu16to32(unsigned int a,unsigned int b) {
 962    unsigned long res;
 963    // 18 Ticks = 1.125 us
 964    __asm__ __volatile__ ( // 0 = res, 1 = timer, 2 = accel %D2=0 ,%A1 are unused is free  
 965       // Result LSB first: %A0, %B0, %A1
 966       "clr r18 \n\t"
 967       "mul %B2,%B1 \n\t" // mul hig bytes
 968       "movw %C0,r0 \n\t"
 969       "mul %A1,%A2 \n\t" // mul low bytes
 970       "movw %A0,r0 \n\t"
 971       "mul %A1,%B2 \n\t"
 972       "add %B0,r0 \n\t"
 973       "adc %C0,r1 \n\t"
 974       "adc %D0,r18 \n\t"
 975       "mul %B1,%A2 \n\t"
 976       "add %B0,r0 \n\t"
 977       "adc %C0,r1 \n\t"
 978       "adc %D0,r18 \n\t"
 979       "clr r1 \n\t"
 980    :"=&r"(res),"=r"(a),"=r"(b)
 981    :"1"(a),"2"(b)
 982    :"r18" );
 983    // return (long)a*b;
 984    return res;
 985  }
 986  // Multiply two 16 bit values and return 32 bit result
 987  inline unsigned int mulu6xu16shift16(unsigned int a,unsigned int b) {
 988  #if CPU_ARCH==ARCH_AVR
 989    unsigned int res;
 990    // 18 Ticks = 1.125 us
 991    __asm__ __volatile__ ( // 0 = res, 1 = timer, 2 = accel %D2=0 ,%A1 are unused is free  
 992       // Result LSB first: %A0, %B0, %A1
 993       "clr r18 \n\t"
 994       "mul %B2,%B1 \n\t" // mul hig bytes
 995       "movw %A0,r0 \n\t"
 996       "mul %A1,%A2 \n\t" // mul low bytes
 997       "mov r19,r1 \n\t"
 998       "mul %A1,%B2 \n\t"
 999       "add r19,r0 \n\t"
1000       "adc %A0,r1 \n\t"
1001       "adc %B0,r18 \n\t"
1002       "mul %B1,%A2 \n\t"
1003       "add r19,r0 \n\t"
1004       "adc %A0,r1 \n\t"
1005       "adc %B0,r18 \n\t"
1006       "clr r1 \n\t"
1007    :"=&r"(res),"=r"(a),"=r"(b)
1008    :"1"(a),"2"(b)
1009    :"r18","r19" );
1010    return res;
1011  #else
1012    return ((long)a*b)>>16;
1013  #endif
1014  }
1015  
1016  /**
1017    Moves the stepper motors one step. If the last step is reached, the next movement is started.
1018    The function must be called from a timer loop. It returns the time for the next call.
1019    This is a modified version that implements a bresenham 'multi-step' algorithm where the dominant
1020    cartesian axis steps may be less than the changing dominant delta axis.
1021  */
1022  #if DRIVE_SYSTEM==3
1023  int lastblk=-1;
1024  long cur_errupd;
1025  //#define DEBUG_DELTA_TIMER
1026  // Current delta segment
1027  DeltaSegment *curd;
1028  // Current delta segment primary error increment
1029  long curd_errupd, stepsPerSegRemaining;
1030  inline long bresenham_step() {
1031  	if(cur == 0) {
1032  		sei();
1033  		cur = &lines[lines_pos];
1034  		if(cur->flags & FLAG_BLOCKED) { // This step is in computation - shouldn't happen
1035  			if(lastblk!=(int)cur) {
1036  				lastblk = (int)cur;
1037  				out.println_int_P(PSTR("BLK "),(unsigned int)lines_count);
1038  			}
1039  			cur = 0;
1040  			return 2000;
1041  		}
1042  		lastblk = -1;
1043  	#ifdef INCLUDE_DEBUG_NO_MOVE
1044  		if(DEBUG_NO_MOVES) { // simulate a move, but do nothing in reality
1045  			lines_pos++;
1046  			if(lines_pos>=MOVE_CACHE_SIZE) lines_pos=0;
1047  			cur = 0;
1048  			cli();
1049  			--lines_count;
1050  			return 1000;
1051  		}
1052  	#endif
1053  		if(cur->flags & FLAG_WARMUP) {
1054  		  // This is a warmup move to initalize the path planner correctly. Just waste
1055  		  // a bit of time to get the planning up to date.
1056  	#if USE_OPS==1
1057  			if(cur->joinFlags & FLAG_JOIN_END_RETRACT) { // Make sure filament is pushed back
1058  				if(printer_state.filamentRetracted) {
1059  		#ifdef DEBUG_OPS
1060  					//sei();
1061  					out.println_P(PSTR("DownW"));
1062  					cli();
1063  		#endif
1064  					printer_state.filamentRetracted = false;
1065  					printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1066  				}
1067  				if(printer_state.extruderStepsNeeded) {
1068  					cur = 0;
1069  					return 2000; // wait, work is done in other interrupt
1070  				}
1071  			} else if(cur->joinFlags & FLAG_JOIN_START_RETRACT) {
1072  				if(!printer_state.filamentRetracted) {
1073  		#ifdef DEBUG_OPS
1074  					//sei();
1075  					out.println_P(PSTR("UpW"));
1076  					cli();
1077  		#endif
1078  					printer_state.filamentRetracted = true;
1079  					cli();
1080  					printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1081  					cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1082  				}
1083  				if(printer_state.extruderStepsNeeded) {
1084  					cur = 0;
1085  					return 2000; // wait, work is done in other interrupt
1086  				}
1087  			}
1088  	#endif
1089  			if(lines_count<=cur->primaryAxis) {	cur=0;return 2000;}
1090  			lines_pos++;
1091  			if(lines_pos>=MOVE_CACHE_SIZE) lines_pos=0;
1092  			long wait = cur->accelerationPrim;
1093  			cur = 0;
1094  			--lines_count;
1095  			return(wait); // waste some time for path optimization to fill up
1096  		} // End if WARMUP
1097  		if(cur->dir & 128) extruder_enable();
1098  		cur->joinFlags |= FLAG_JOIN_END_FIXED | FLAG_JOIN_START_FIXED; // don't touch this segment any more, just for safety
1099  	#if USE_OPS==1
1100  		if(printer_state.opsMode) { // Enabled?
1101  			if(cur->joinFlags & FLAG_JOIN_START_RETRACT) {
1102  				if(!printer_state.filamentRetracted) {
1103  		#ifdef DEBUG_OPS
1104  					out.println_P(PSTR("Up"));
1105  		#endif
1106  					printer_state.filamentRetracted = true;
1107  					cli();
1108  					printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1109  					sei();
1110  					cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1111  				}
1112  			}
1113          // If path optimizer ran out of samples, he might miss some retractions. Solve them before printing
1114  			else if((cur->joinFlags & FLAG_JOIN_NO_RETRACT)==0 && printmoveSeen) {
1115  				if((cur->dir & 136)==136) {
1116  					if(printer_state.filamentRetracted) { // Printmove and filament is still up!
1117  		#ifdef DEBUG_OPS
1118  						out.println_P(PSTR("DownA"));
1119  		#endif
1120  						printer_state.filamentRetracted = false;
1121  						cli();
1122  						printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1123  						cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_DOWN;
1124  					}
1125  				} /*else if(!printer_state.filamentRetracted) {
1126  #ifdef DEBUG_OPS
1127              out.println_P(PSTR("UpA"));
1128  #endif
1129              printer_state.filamentRetracted = true;
1130              cli();
1131              printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1132              cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1133            }*/
1134  			}
1135  			if(cur->joinFlags & FLAG_JOIN_WAIT_EXTRUDER_UP) { // Wait for filament pushback
1136  				cli();
1137  				if(printer_state.extruderStepsNeeded<printer_state.opsMoveAfterSteps) {
1138  					cur=0;
1139  					return 4000;
1140  				}
1141  			} else if(cur->joinFlags & FLAG_JOIN_WAIT_EXTRUDER_DOWN) { // Wait for filament pushback
1142  				cli();
1143  				if(printer_state.extruderStepsNeeded) {
1144  					cur=0;
1145  					return 4000;
1146  				}
1147  			}
1148  		} // End if opsMode
1149  	#endif
1150  		sei(); // Allow interrupts
1151  		// Set up delta segments
1152  		if (cur->numDeltaSegments) {
1153  			// If there are delta segments point to them here
1154  			curd = &segments[cur->deltaSegmentReadPos++];
1155  			if (cur->deltaSegmentReadPos >= DELTA_CACHE_SIZE) cur->deltaSegmentReadPos=0;
1156  			// Enable axis - All axis are enabled since they will most probably all be involved in a move
1157  			// Since segments could involve different axis this reduces load when switching segments and
1158  			// makes disabling easier.
1159  			enable_x();enable_y();enable_z();
1160  
1161  			// Copy across movement into main direction flags so that endstops function correctly
1162  			cur->dir |= curd->dir;
1163  			// Initialize bresenham for the first segment
1164  			if (cur->halfstep) {
1165  				cur->error[0] = cur->error[1] = cur->error[2] = cur->numPrimaryStepPerSegment;
1166  				curd_errupd = cur->numPrimaryStepPerSegment = cur->numPrimaryStepPerSegment<<1;
1167  			} else {
1168  				cur->error[0] = cur->error[1] = cur->error[2] = cur->numPrimaryStepPerSegment>>1;
1169  				curd_errupd = cur->numPrimaryStepPerSegment;
1170  			}
1171  			stepsPerSegRemaining = cur->numPrimaryStepPerSegment;
1172  	#ifdef DEBUG_DELTA_TIMER
1173  			out.println_byte_P(PSTR("HS: "),cur->halfstep);
1174  			out.println_long_P(PSTR("Error: "),curd_errupd);
1175  	#endif
1176  		} else curd=0;
1177  		cur_errupd = (cur->halfstep ? cur->stepsRemaining << 1 : cur->stepsRemaining);
1178  
1179  		if(!(cur->joinFlags & FLAG_JOIN_STEPPARAMS_COMPUTED)) {// should never happen, but with bad timings???
1180  			out.println_int_P(PSTR("LATE "),(unsigned int)lines_count);
1181  			updateStepsParameter(cur/*,8*/);
1182  		}
1183  		printer_state.vMaxReached = cur->vStart;
1184  		printer_state.stepNumber=0;
1185  		printer_state.timer = 0;
1186  		cli();
1187  		//Determine direction of movement
1188  		if (curd) {
1189  			if(curd->dir & 1) {
1190  				WRITE(X_DIR_PIN,!INVERT_X_DIR);
1191  			} else {
1192  				WRITE(X_DIR_PIN,INVERT_X_DIR);
1193  			}
1194  			if(curd->dir & 2) {
1195  				WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
1196  			} else {
1197  				WRITE(Y_DIR_PIN,INVERT_Y_DIR);
1198  			}
1199  			if(curd->dir & 4) {
1200  				WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
1201  			} else {
1202  				WRITE(Z_DIR_PIN,INVERT_Z_DIR);
1203  			}
1204  		}
1205  	#if USE_OPS==1 || defined(USE_ADVANCE)
1206        if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)==0) // Set direction if no advance/OPS enabled
1207  	#endif
1208  		if(cur->dir & 8) {
1209  			extruder_set_direction(1);
1210  		} else {
1211  			extruder_set_direction(0);
1212  		}
1213  	#ifdef USE_ADVANCE
1214  		long h = mulu6xu16to32(cur->vStart,cur->advanceL);
1215  		int tred = ((
1216  		#ifdef ENABLE_QUADRATIC_ADVANCE
1217  			(printer_state.advance_executed = cur->advanceStart)+
1218  		#endif
1219  			h)>>16);
1220  		printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1221  		printer_state.advance_steps_set = tred;
1222  	#endif
1223      if(printer_state.waslasthalfstepping && cur->halfstep==0) { // Switch halfstepping -> full stepping
1224        printer_state.waslasthalfstepping = 0;
1225        return printer_state.interval*3; // Wait an other 150% from last half step to make the 100% full
1226      } else if(!printer_state.waslasthalfstepping && cur->halfstep) { // Switch full to half stepping
1227        printer_state.waslasthalfstepping = 1;
1228      } else 
1229        return printer_state.interval; // Wait an other 50% from last step to make the 100% full
1230  	} // End cur=0
1231  	sei();
1232  
1233    /* For halfstepping, we divide the actions into even and odd actions to split
1234       time used per loop. */
1235  	byte do_even;
1236  	byte do_odd;
1237  	if(cur->halfstep) {
1238  		do_odd = cur->halfstep & 1;
1239  		do_even = cur->halfstep & 2;
1240  		cur->halfstep = 3-cur->halfstep;
1241  	} else {
1242  		do_even = 1;
1243  		do_odd = 1;
1244  	}
1245  	cli();
1246  	if(do_even) {
1247  		if((cur->flags & FLAG_CHECK_ENDSTOPS) && (curd != 0)) {
1248  	#if X_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_X
1249  			if((curd->dir & 17)==17) if(READ(X_MAX_PIN) != ENDSTOP_X_MAX_INVERTING) {
1250  				curd->dir&=~16;
1251  				cur->dir&=~16;
1252  			}
1253  	#endif
1254  	#if Y_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Y
1255  			if((curd->dir & 34)==34) if(READ(Y_MAX_PIN) != ENDSTOP_Y_MAX_INVERTING) {
1256  				curd->dir&=~32;
1257  				cur->dir&=~32;
1258  			}
1259  	#endif
1260  	#if Z_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Z
1261  			if((curd->dir & 68)==68) if(READ(Z_MAX_PIN)!= ENDSTOP_Z_MAX_INVERTING) {
1262  				curd->dir&=~64;
1263  				cur->dir&=~64;
1264  			}
1265  	#endif
1266  		}
1267  	}
1268  	byte max_loops = (printer_state.stepper_loops<=cur->stepsRemaining ? printer_state.stepper_loops : cur->stepsRemaining);
1269  	if(cur->stepsRemaining>0) {
1270  		for(byte loop=0;loop<max_loops;loop++) {
1271  			if(loop>0)
1272  	#if STEPPER_HIGH_DELAY>0
1273  				delayMicroseconds(STEPPER_HIGH_DELAY+DOUBLE_STEP_DELAY);
1274  	#else
1275  				delayMicroseconds(DOUBLE_STEP_DELAY);
1276  	#endif
1277  			if(cur->dir & 128) {
1278  				if((cur->error[3] -= cur->delta[3]) < 0) {
1279  	#if USE_OPS==1 || defined(USE_ADVANCE)
1280  					if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)) { // Use interrupt for movement
1281  						if(cur->dir & 8)
1282  							printer_state.extruderStepsNeeded++;
1283  						else
1284  							printer_state.extruderStepsNeeded--;
1285  					} else {
1286  	#endif
1287  						extruder_step();
1288  	#if USE_OPS==1 || defined(USE_ADVANCE)
1289  					}
1290  	#endif
1291  					cur->error[3] += cur_errupd;
1292  				}
1293  			}
1294  			if (curd) {
1295  				// Take delta steps
1296  				if(curd->dir & 16) {
1297  					if((cur->error[0] -= curd->deltaSteps[0]) < 0) {
1298  						WRITE(X_STEP_PIN,HIGH);
1299  						cur->error[0] += curd_errupd;
1300  					#ifdef DEBUG_STEPCOUNT
1301  						cur->totalStepsRemaining--;
1302  					#endif
1303  					}
1304  				}
1305  
1306  				if(curd->dir & 32) {
1307  					if((cur->error[1] -= curd->deltaSteps[1]) < 0) {
1308  						WRITE(Y_STEP_PIN,HIGH);
1309  						cur->error[1] += curd_errupd;
1310  					#ifdef DEBUG_STEPCOUNT
1311  						cur->totalStepsRemaining--;
1312  					#endif
1313  					}
1314  				}
1315  
1316  				if(curd->dir & 64) {
1317  					if((cur->error[2] -= curd->deltaSteps[2]) < 0) {
1318  						WRITE(Z_STEP_PIN,HIGH);
1319  						printer_state.countZSteps += ( cur->dir & 4 ? 1 : -1 );
1320  						cur->error[2] += curd_errupd;
1321  					#ifdef DEBUG_STEPCOUNT
1322  						cur->totalStepsRemaining--;
1323  					#endif
1324  					}
1325  				}
1326  
1327  			#if STEPPER_HIGH_DELAY>0
1328  				delayMicroseconds(STEPPER_HIGH_DELAY);
1329  			#endif
1330  				WRITE(X_STEP_PIN,LOW);
1331  				WRITE(Y_STEP_PIN,LOW);
1332  				WRITE(Z_STEP_PIN,LOW);
1333  				stepsPerSegRemaining--;
1334  				if (!stepsPerSegRemaining) {
1335  					cur->numDeltaSegments--;
1336  					if (cur->numDeltaSegments) {
1337  
1338  						// Get the next delta segment
1339  						curd = &segments[cur->deltaSegmentReadPos++];
1340  						if (cur->deltaSegmentReadPos >= DELTA_CACHE_SIZE) cur->deltaSegmentReadPos=0;
1341  						delta_segment_count--;
1342  
1343  						// Initialize bresenham for this segment (numPrimaryStepPerSegment is already correct for the half step setting)
1344  						cur->error[0] = cur->error[1] = cur->error[2] = cur->numPrimaryStepPerSegment>>1;
1345  
1346  						// Reset the counter of the primary steps. This is initialized in the line
1347  						// generation so don't have to do this the first time.
1348  						stepsPerSegRemaining = cur->numPrimaryStepPerSegment;
1349  
1350  						// Change direction if necessary
1351  						if(curd->dir & 1) {
1352  							WRITE(X_DIR_PIN,!INVERT_X_DIR);
1353  						} else {
1354  							WRITE(X_DIR_PIN,INVERT_X_DIR);
1355  						}
1356  						if(curd->dir & 2) {
1357  							WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
1358  						} else {
1359  							WRITE(Y_DIR_PIN,INVERT_Y_DIR);
1360  						}
1361  						if(curd->dir & 4) {
1362  							WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
1363  						} else {
1364  							WRITE(Z_DIR_PIN,INVERT_Z_DIR);
1365  						}
1366  					} else {
1367  						// Release the last segment
1368  						delta_segment_count--;
1369  						curd=0;
1370  					}
1371  				}
1372  			}
1373  	#if USE_OPS==1 || defined(USE_ADVANCE)
1374  			if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)==0) // Use interrupt for movement
1375  	#endif
1376  			extruder_unstep();
1377  		} // for loop
1378  		if(do_odd) {
1379  			sei(); // Allow interrupts for other types, timer1 is still disabled
1380  	#ifdef RAMP_ACCELERATION
1381  		//If acceleration is enabled on this move and we are in the acceleration segment, calculate the current interval
1382  			if (printer_state.stepNumber <= cur->accelSteps) { // we are accelerating
1383  				printer_state.vMaxReached = ComputeV(printer_state.timer,cur->facceleration)+cur->vStart;
1384  				if(printer_state.vMaxReached>cur->vMax) printer_state.vMaxReached = cur->vMax;
1385  				unsigned int v;
1386  				if(printer_state.vMaxReached>STEP_DOUBLER_FREQUENCY) {
1387  		#if ALLOW_QUADSTEPPING
1388  					if(printer_state.vMaxReached>STEP_DOUBLER_FREQUENCY*2) {
1389  						printer_state.stepper_loops = 4;
1390  						v = printer_state.vMaxReached>>2;
1391  					} else {
1392  						printer_state.stepper_loops = 2;
1393  						v = printer_state.vMaxReached>>1;
1394  					}
1395  		#else
1396  					printer_state.stepper_loops = 2;
1397  					v = printer_state.vMaxReached>>1;
1398  		#endif
1399  				} else {
1400  					printer_state.stepper_loops = 1;
1401  					v = printer_state.vMaxReached;
1402  				}
1403  				printer_state.interval = CPUDivU2(v);
1404  				printer_state.timer+=printer_state.interval;
1405  		#ifdef USE_ADVANCE
1406  			#ifdef ENABLE_QUADRATIC_ADVANCE
1407  				long advance_target =printer_state.advance_executed+cur->advanceRate;
1408  				for(byte loop=1;loop<max_loops;loop++) advance_target+=cur->advanceRate;
1409  				if(advance_target>cur->advanceFull)
1410  					advance_target = cur->advanceFull;
1411  				cli();
1412  				long h = mulu6xu16to32(printer_state.vMaxReached,cur->advanceL);
1413  				int tred = ((advance_target+h)>>16);
1414  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1415  				printer_state.advance_steps_set = tred;
1416  				sei();
1417  				printer_state.advance_executed = advance_target;
1418  			#else
1419  				int tred = mulu6xu16shift16(printer_state.vMaxReached,cur->advanceL);
1420  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1421  				printer_state.advance_steps_set = tred;
1422  				sei();
1423  			#endif
1424  		#endif
1425  			} else if (cur->stepsRemaining <= cur->decelSteps) { // time to slow down
1426  				if (!(cur->flags & FLAG_DECELERATING)) {
1427  					printer_state.timer = 0;
1428  					cur->flags |= FLAG_DECELERATING;
1429  				}
1430  				unsigned int v = ComputeV(printer_state.timer,cur->facceleration);
1431  				if (v > printer_state.vMaxReached)   // if deceleration goes too far it can become too large
1432  					v = cur->vEnd;
1433  				else {
1434  					v=printer_state.vMaxReached-v;
1435  					if (v<cur->vEnd) v = cur->vEnd; // extra steps at the end of desceleration due to rounding erros
1436  				}
1437  				if(v>STEP_DOUBLER_FREQUENCY) {
1438  		#if ALLOW_QUADSTEPPING
1439  					if(v>STEP_DOUBLER_FREQUENCY*2) {
1440  						printer_state.stepper_loops = 4;
1441  						v = v>>2;
1442  					} else {
1443  						printer_state.stepper_loops = 2;
1444  						v = v>>1;
1445  					}
1446  		#else
1447  					printer_state.stepper_loops = 2;
1448  					v = v>>1;
1449  		#endif
1450  				} else {
1451  					printer_state.stepper_loops = 1;
1452  				}
1453  				printer_state.interval = CPUDivU2(v);
1454  				printer_state.timer+=printer_state.interval;
1455  		#ifdef USE_ADVANCE
1456  			#ifdef ENABLE_QUADRATIC_ADVANCE
1457  				long advance_target =printer_state.advance_executed-cur->advanceRate;
1458  				for(byte loop=1;loop<max_loops;loop++) advance_target-=cur->advanceRate;
1459  				if(advance_target<cur->advanceEnd)
1460  					advance_target = cur->advanceEnd;
1461  				long h=mulu6xu16to32(cur->advanceL,v);
1462  				int tred = ((advance_target+h)>>16);
1463  				cli();
1464  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1465  				printer_state.advance_steps_set = tred;
1466  				sei();
1467  				printer_state.advance_executed = advance_target;
1468  			#else
1469  				int tred=mulu6xu16shift16(cur->advanceL,v);
1470  				cli();
1471  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1472  				printer_state.advance_steps_set = tred;
1473  				sei();
1474  			#endif
1475  		#endif
1476  			} else {
1477  				// If we had acceleration, we need to use the latest vMaxReached and interval
1478  				// If we started full speed, we need to use cur->fullInterval and vMax
1479  		#ifdef USE_ADVANCE
1480  				unsigned int v;
1481  				if(!cur->accelSteps) {
1482  					v = cur->vMax;
1483  				} else {
1484  					v = printer_state.vMaxReached;
1485  				}
1486  			#ifdef ENABLE_QUADRATIC_ADVANCE
1487  				long h=mulu6xu16to32(cur->advanceL,v);
1488  				int tred = ((printer_state.advance_executed+h)>>16);
1489  				cli();
1490  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1491  				printer_state.advance_steps_set = tred;
1492  				sei();
1493  			#else
1494  				int tred=mulu6xu16shift16(cur->advanceL,v);
1495  				cli();
1496  				printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1497  				printer_state.advance_steps_set = tred;
1498  				sei();
1499  			#endif
1500  		#endif
1501  				if(!cur->accelSteps) {
1502  					if(cur->vMax>STEP_DOUBLER_FREQUENCY) {
1503  		#if ALLOW_QUADSTEPPING
1504  						if(cur->vMax>STEP_DOUBLER_FREQUENCY*2) {
1505  							printer_state.stepper_loops = 4;
1506  							printer_state.interval = cur->fullInterval>>2;
1507  						} else {
1508  							printer_state.stepper_loops = 2;
1509  							printer_state.interval = cur->fullInterval>>1;
1510  						}
1511  		#else
1512  						printer_state.stepper_loops = 2;
1513  						printer_state.interval = cur->fullInterval>>1;
1514  		#endif
1515  					} else {
1516  						printer_state.stepper_loops = 1;
1517  						printer_state.interval = cur->fullInterval;
1518  					}
1519  				}
1520  			}
1521  	#else
1522  			printer_state.interval = cur->fullInterval; // without RAMPS always use full speed
1523  	#endif
1524  		} // do_odd
1525  		if(do_even) {
1526  			printer_state.stepNumber+=max_loops;
1527  			cur->stepsRemaining-=max_loops;
1528  		}
1529  
1530  	#if USE_OPS==1
1531  		if(printer_state.opsMode==2 && (cur->joinFlags & FLAG_JOIN_END_RETRACT) && printer_state.filamentRetracted && cur->stepsRemaining<=cur->opsReverseSteps) {
1532  		#ifdef DEBUG_OPS
1533  			out.println_long_P(PSTR("DownX"),cur->stepsRemaining);
1534  		#endif
1535  			// Point for retraction reversal reached.
1536  			printer_state.filamentRetracted = false;
1537  			cli();
1538  			printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1539  		#ifdef DEBUG_OPS
1540  			sei();
1541  			out.println_long_P(PSTR("N="),printer_state.extruderStepsNeeded);
1542  		#endif
1543  		}
1544  	#endif
1545  	} // stepsRemaining
1546  	long interval;
1547  	if(cur->halfstep)
1548  		interval = (printer_state.interval>>1);		// time to come back
1549  	else
1550  		interval = printer_state.interval;
1551  	if(do_even) {
1552  		if(cur->stepsRemaining<=0 || (cur->dir & 240)==0) { // line finished
1553  //			out.println_int_P(PSTR("Line finished: "), (int) cur->numDeltaSegments);
1554  //			out.println_int_P(PSTR("DSC: "), (int) delta_segment_count);
1555  //			out.println_P(PSTR("F"));
1556  
1557  			// Release remaining delta segments
1558  			delta_segment_count -= cur->numDeltaSegments;
1559  	#ifdef DEBUG_STEPCOUNT
1560  			if(cur->totalStepsRemaining) {
1561  				out.println_long_P(PSTR("Missed steps:"), cur->totalStepsRemaining);
1562  				out.println_long_P(PSTR("Step/seg r:"), stepsPerSegRemaining);
1563  				out.println_int_P(PSTR("NDS:"), (int) cur->numDeltaSegments);
1564  				out.println_int_P(PSTR("HS:"), (int) cur->halfstep);
1565  			}
1566  	#endif
1567  
1568  	#if USE_OPS==1
1569  			if(cur->joinFlags & FLAG_JOIN_END_RETRACT) { // Make sure filament is pushed back
1570  				sei();
1571  				if(printer_state.filamentRetracted) {
1572  		#ifdef DEBUG_OPS
1573  					out.println_P(PSTR("Down"));
1574  		#endif
1575  					printer_state.filamentRetracted = false;
1576  					cli();
1577  					printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1578  				}
1579  				cli();
1580  				if(printer_state.extruderStepsNeeded) {
1581  		#ifdef DEBUG_OPS
1582      //      sei();
1583      //      out.println_int_P(PSTR("W"),printer_state.extruderStepsNeeded);
1584  		#endif
1585  					return 4000; // wait, work is done in other interrupt
1586  				}
1587  		#ifdef DEBUG_OPS
1588  				sei();
1589  		#endif
1590  			}
1591  	#endif
1592  			cli();
1593  			lines_pos++;
1594  			if(lines_pos>=MOVE_CACHE_SIZE) lines_pos=0;
1595  			cur = 0;
1596  			--lines_count;
1597  			if(DISABLE_X) disable_x();
1598  			if(DISABLE_Y) disable_y();
1599  			if(DISABLE_Z) disable_z();
1600  			if(lines_count==0) UI_STATUS(UI_TEXT_IDLE);
1601  			interval = printer_state.interval = interval>>1; // 50% of time to next call to do cur=0
1602  		}
1603  	        DEBUG_MEMORY;
1604  	} // Do even
1605  	return interval;
1606  }
1607  #else
1608  /**
1609    Moves the stepper motors one step. If the last step is reached, the next movement is started.
1610    The function must be called from a timer loop. It returns the time for the next call.
1611    
1612    Normal non delta algorithm
1613  */
1614  int lastblk=-1;
1615  long cur_errupd;
1616  inline long bresenham_step() {
1617    if(cur == 0) {
1618        sei();
1619        ANALYZER_ON(ANALYZER_CH0);
1620        cur = &lines[lines_pos];
1621        if(cur->flags & FLAG_BLOCKED) { // This step is in computation - shouldn't happen
1622          if(lastblk!=(int)cur) {
1623            lastblk = (int)cur;
1624            out.println_int_P(PSTR("BLK "),(unsigned int)lines_count);
1625          }
1626          cur = 0;
1627          return 2000;
1628        }
1629        lastblk = -1;
1630  #ifdef INCLUDE_DEBUG_NO_MOVE
1631        if(DEBUG_NO_MOVES) { // simulate a move, but do nothing in reality
1632          NEXT_PLANNER_INDEX(lines_pos);
1633          cur = 0;
1634          cli();
1635          --lines_count;
1636          return 1000;
1637        }
1638  #endif
1639          ANALYZER_OFF(ANALYZER_CH0);
1640        if(cur->flags & FLAG_WARMUP) {
1641            // This is a warmup move to initalize the path planner correctly. Just waste
1642            // a bit of time to get the planning up to date.
1643  #if USE_OPS==1
1644           if(cur->joinFlags & FLAG_JOIN_END_RETRACT) { // Make sure filament is pushed back
1645              if(printer_state.filamentRetracted) {
1646  	#ifdef DEBUG_OPS
1647                //sei();
1648                OUT_P_LN("DownW");
1649                cli();
1650  	#endif
1651                printer_state.filamentRetracted = false;
1652                printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1653              }
1654              if(printer_state.extruderStepsNeeded) {
1655                cur = 0;
1656                return 2000; // wait, work is done in other interrupt
1657              }
1658            } else if(cur->joinFlags & FLAG_JOIN_START_RETRACT) {
1659              if(!printer_state.filamentRetracted) {
1660  	#ifdef DEBUG_OPS
1661                OUT_P_LN("UpW");
1662                cli();
1663  	#endif
1664                printer_state.filamentRetracted = true;
1665                cli();
1666                printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1667                cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1668              }
1669              if(printer_state.extruderStepsNeeded) {
1670                cur = 0;
1671                return 2000; // wait, work is done in other interrupt
1672              }
1673            }
1674  #endif
1675            if(lines_count<=cur->primaryAxis) {
1676              cur=0;
1677              return 2000;
1678            }
1679            NEXT_PLANNER_INDEX(lines_pos);
1680            long wait = cur->accelerationPrim;
1681            cur = 0;
1682            cli();
1683            --lines_count;
1684            return(wait); // waste some time for path optimization to fill up
1685        } // End if WARMUP
1686  /*if(DEBUG_ECHO) {
1687  OUT_P_L_LN("MSteps:",cur->stepsRemaining);
1688    //OUT_P_F("Ln:",cur->startSpeed);
1689  //OUT_P_F_LN(":",cur->endSpeed);
1690  }*/
1691        //Only enable axis that are moving. If the axis doesn't need to move then it can stay disabled depending on configuration.
1692  #ifdef XY_GANTRY
1693        if(cur->dir & 48) {
1694          enable_x();
1695          enable_y();
1696        }
1697  #else
1698        if(cur->dir & 16) enable_x();
1699        if(cur->dir & 32) enable_y();
1700  #endif
1701        if(cur->dir & 64) {
1702          enable_z();
1703        }
1704        if(cur->dir & 128) extruder_enable();
1705        cur->joinFlags |= FLAG_JOIN_END_FIXED | FLAG_JOIN_START_FIXED; // don't touch this segment any more, just for safety
1706  #if USE_OPS==1
1707        if(printer_state.opsMode) { // Enabled?
1708          if(cur->joinFlags & FLAG_JOIN_START_RETRACT) {
1709           if(!printer_state.filamentRetracted) {
1710  	#ifdef DEBUG_OPS
1711              OUT_P_LN("Up");
1712  	#endif
1713              printer_state.filamentRetracted = true;
1714              cli();
1715              printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1716              sei();
1717              cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1718           }
1719          }
1720          // If path optimizer ran out of samples, he might miss some retractions. Solve them before printing
1721          else if((cur->joinFlags & FLAG_JOIN_NO_RETRACT)==0 && printmoveSeen) {
1722            if((cur->dir & 136)==136) {
1723              if(printer_state.filamentRetracted) { // Printmove and filament is still up!
1724  	#ifdef DEBUG_OPS
1725                OUT_P_LN("DownA");
1726  	#endif
1727                printer_state.filamentRetracted = false;
1728                cli();
1729                printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
1730                cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_DOWN;
1731              }
1732            } /*else if(!printer_state.filamentRetracted) {
1733  #ifdef DEBUG_OPS
1734              out.println_P(PSTR("UpA"));
1735  #endif
1736              printer_state.filamentRetracted = true;
1737              cli();
1738              printer_state.extruderStepsNeeded-=printer_state.opsRetractSteps;
1739              cur->joinFlags |= FLAG_JOIN_WAIT_EXTRUDER_UP;
1740            }*/
1741          }
1742          if(cur->joinFlags & FLAG_JOIN_WAIT_EXTRUDER_UP) { // Wait for filament pushback
1743            cli();
1744            if(printer_state.extruderStepsNeeded<printer_state.opsMoveAfterSteps) {
1745              cur=0;
1746              return 4000;
1747            }
1748          } else if(cur->joinFlags & FLAG_JOIN_WAIT_EXTRUDER_DOWN) { // Wait for filament pushback
1749            cli();
1750            if(printer_state.extruderStepsNeeded) {
1751              cur=0;
1752              return 4000;
1753            }
1754          }
1755        } // End if opsMode
1756  #endif
1757        sei(); // Allow interrupts
1758        if(cur->halfstep) {
1759          cur_errupd = cur->delta[cur->primaryAxis]<<1;
1760          //printer_state.interval = CPUDivU2(cur->vStart);
1761        } else
1762          cur_errupd = cur->delta[cur->primaryAxis];
1763        if(!(cur->joinFlags & FLAG_JOIN_STEPPARAMS_COMPUTED)) {// should never happen, but with bad timings???
1764  		updateStepsParameter(cur/*,8*/);
1765        }
1766        printer_state.vMaxReached = cur->vStart;
1767        printer_state.stepNumber=0;
1768        printer_state.timer = 0;
1769        cli();
1770        //Determine direction of movement,check if endstop was hit
1771  #if !defined(XY_GANTRY)
1772        if(cur->dir & 1) {
1773          WRITE(X_DIR_PIN,!INVERT_X_DIR);
1774        } else {
1775          WRITE(X_DIR_PIN,INVERT_X_DIR);
1776        }
1777        if(cur->dir & 2) {
1778          WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
1779        } else {
1780          WRITE(Y_DIR_PIN,INVERT_Y_DIR);
1781        }
1782  #else
1783        long gdx = (cur->dir & 1 ? cur->delta[0] : -cur->delta[0]); // Compute signed difference in steps
1784        long gdy = (cur->dir & 2 ? cur->delta[1] : -cur->delta[1]);
1785  #if DRIVE_SYSTEM==1
1786        if(gdx+gdy>=0) {
1787          WRITE(X_DIR_PIN,!INVERT_X_DIR);
1788          ANALYZER_ON(ANALYZER_CH4);
1789        } else {        
1790          WRITE(X_DIR_PIN,INVERT_X_DIR);
1791          ANALYZER_OFF(ANALYZER_CH4);
1792        }
1793        if(gdx>gdy) {
1794          WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
1795          ANALYZER_ON(ANALYZER_CH5);
1796        } else {
1797          WRITE(Y_DIR_PIN,INVERT_Y_DIR);
1798          ANALYZER_OFF(ANALYZER_CH5);
1799        }
1800  #endif
1801  #if DRIVE_SYSTEM==2
1802        if(gdx+gdy>=0) {
1803          WRITE(X_DIR_PIN,!INVERT_X_DIR);
1804        } else {
1805          WRITE(X_DIR_PIN,INVERT_X_DIR);
1806        }
1807        if(gdx<=gdy) {
1808          WRITE(Y_DIR_PIN,!INVERT_Y_DIR);
1809        } else {
1810          WRITE(Y_DIR_PIN,INVERT_Y_DIR);
1811        }
1812  #endif
1813  #endif
1814        if(cur->dir & 4) {
1815          WRITE(Z_DIR_PIN,!INVERT_Z_DIR);
1816        } else {
1817          WRITE(Z_DIR_PIN,INVERT_Z_DIR);
1818        }
1819  #if USE_OPS==1 || defined(USE_ADVANCE)
1820        if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)==0) // Set direction if no advance/OPS enabled
1821  #endif
1822          if(cur->dir & 8) {
1823            extruder_set_direction(1);
1824          } else {
1825            extruder_set_direction(0);
1826          }
1827  #ifdef USE_ADVANCE
1828       long h = mulu6xu16to32(cur->vStart,cur->advanceL);
1829       int tred = ((
1830  #ifdef ENABLE_QUADRATIC_ADVANCE
1831       (printer_state.advance_executed = cur->advanceStart)+
1832  #endif
1833       h)>>16);
1834       printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
1835       printer_state.advance_steps_set = tred;
1836  #endif
1837      if(printer_state.waslasthalfstepping && cur->halfstep==0) { // Switch halfstepping -> full stepping
1838        printer_state.waslasthalfstepping = 0;
1839        return printer_state.interval*3; // Wait an other 150% from last half step to make the 100% full
1840      } else if(!printer_state.waslasthalfstepping && cur->halfstep) { // Switch full to half stepping
1841        printer_state.waslasthalfstepping = 1;
1842      } else 
1843        return printer_state.interval; // Wait an other 50% from last step to make the 100% full
1844    } // End cur=0
1845    sei();
1846    /* For halfstepping, we divide the actions into even and odd actions to split
1847       time used per loop. */
1848    byte do_even;
1849    byte do_odd;
1850    if(cur->halfstep) {
1851      do_odd = cur->halfstep & 1;
1852      do_even = cur->halfstep & 2;
1853      cur->halfstep = 3-cur->halfstep;
1854    } else {
1855      do_even = 1;
1856      do_odd = 1;
1857    }
1858    cli();
1859    if(do_even) {
1860  	if(cur->flags & FLAG_CHECK_ENDSTOPS) {
1861  #if X_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_X
1862  		if((cur->dir & 17)==16) if(READ(X_MIN_PIN) != ENDSTOP_X_MIN_INVERTING) {
1863  #if DRIVE_SYSTEM==0
1864  			cur->dir&=~16;
1865  #else
1866  			cur->dir&=~48;
1867  #endif
1868  		}
1869  #endif
1870  #if Y_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_Y
1871  		if((cur->dir & 34)==32) if(READ(Y_MIN_PIN) != ENDSTOP_Y_MIN_INVERTING) {
1872  #if DRIVE_SYSTEM==0
1873  			cur->dir&=~32;
1874  #else
1875  			cur->dir&=~48;
1876  #endif
1877  		}
1878  #endif
1879  #if X_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_X
1880  		if((cur->dir & 17)==17) if(READ(X_MAX_PIN) != ENDSTOP_X_MAX_INVERTING) {
1881  #if DRIVE_SYSTEM==0
1882  			cur->dir&=~16;
1883  #else
1884  			cur->dir&=~48;
1885  #endif
1886  		}
1887  #endif
1888  #if Y_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Y
1889  		if((cur->dir & 34)==34) if(READ(Y_MAX_PIN) != ENDSTOP_Y_MAX_INVERTING) {
1890  #if DRIVE_SYSTEM==0
1891  			cur->dir&=~32;
1892  #else
1893  			cur->dir&=~48;
1894  #endif
1895  		}
1896  #endif
1897     }
1898     // Test Z-Axis every step if necessary, otherwise it could easyly ruin your printer!
1899  #if Z_MIN_PIN>-1 && MIN_HARDWARE_ENDSTOP_Z
1900     if((cur->dir & 68)==64) if(READ(Z_MIN_PIN) != ENDSTOP_Z_MIN_INVERTING) {cur->dir&=~64;}
1901  #endif
1902  #if Z_MAX_PIN>-1 && MAX_HARDWARE_ENDSTOP_Z
1903     if((cur->dir & 68)==68) if(READ(Z_MAX_PIN)!= ENDSTOP_Z_MAX_INVERTING) {cur->dir&=~64;}
1904  #endif
1905    }
1906    byte max_loops = (printer_state.stepper_loops<=cur->stepsRemaining ? printer_state.stepper_loops : cur->stepsRemaining);
1907    if(cur->stepsRemaining>0) {
1908     for(byte loop=0;loop<max_loops;loop++) {
1909      ANALYZER_ON(ANALYZER_CH1);
1910      if(loop>0)
1911  #if STEPPER_HIGH_DELAY>0
1912        delayMicroseconds(STEPPER_HIGH_DELAY+DOUBLE_STEP_DELAY);
1913  #else
1914        delayMicroseconds(DOUBLE_STEP_DELAY);
1915  #endif
1916       if(cur->dir & 128) {
1917        if((cur->error[3] -= cur->delta[3]) < 0) {
1918  #if USE_OPS==1 || defined(USE_ADVANCE)
1919         if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)) { // Use interrupt for movement
1920            if(cur->dir & 8)
1921              printer_state.extruderStepsNeeded++;
1922            else
1923              printer_state.extruderStepsNeeded--;
1924          } else {
1925  #endif
1926            extruder_step();
1927  #if USE_OPS==1 || defined(USE_ADVANCE)
1928          }
1929  #endif
1930          cur->error[3] += cur_errupd;
1931        }
1932      }
1933  #if defined(XY_GANTRY)
1934  #endif
1935      if(cur->dir & 16) {
1936        if((cur->error[0] -= cur->delta[0]) < 0) {
1937          ANALYZER_ON(ANALYZER_CH6);
1938  #if DRIVE_SYSTEM==0 || !defined(XY_GANTRY)
1939          ANALYZER_ON(ANALYZER_CH2);
1940          WRITE(X_STEP_PIN,HIGH);
1941  #else
1942  #if DRIVE_SYSTEM==1
1943          if(cur->dir & 1) {
1944            printer_state.motorX++;
1945            printer_state.motorY++;
1946          } else {
1947            printer_state.motorX--;
1948            printer_state.motorY--;
1949          }
1950  #endif
1951  #if DRIVE_SYSTEM==2
1952          if(cur->dir & 1) {
1953            printer_state.motorX++;
1954            printer_state.motorY--;
1955          } else {
1956            printer_state.motorX--;
1957            printer_state.motorY++;
1958          }
1959  #endif
1960  #endif // XY_GANTRY
1961          cur->error[0] += cur_errupd;
1962  #ifdef DEBUG_STEPCOUNT
1963          cur->totalStepsRemaining--;
1964  #endif
1965        }
1966      }
1967      if(cur->dir & 32) {
1968        if((cur->error[1] -= cur->delta[1]) < 0) {
1969          ANALYZER_ON(ANALYZER_CH7);
1970  #if DRIVE_SYSTEM==0 || !defined(XY_GANTRY)
1971          ANALYZER_ON(ANALYZER_CH3);
1972          WRITE(Y_STEP_PIN,HIGH);
1973  #else
1974  #if DRIVE_SYSTEM==1
1975          if(cur->dir & 2) {
1976            printer_state.motorX++;
1977            printer_state.motorY--;
1978          } else {
1979            printer_state.motorX--;
1980            printer_state.motorY++;
1981          }
1982  #endif
1983  #if DRIVE_SYSTEM==2
1984          if(cur->dir & 2) {
1985            printer_state.motorX++;
1986            printer_state.motorY++;
1987          } else {
1988            printer_state.motorX--;
1989            printer_state.motorY--;
1990          }
1991  #endif
1992  #endif // XY_GANTRY
1993          cur->error[1] += cur_errupd;
1994  #ifdef DEBUG_STEPCOUNT
1995          cur->totalStepsRemaining--;
1996  #endif
1997        }
1998      }
1999  #if defined(XY_GANTRY)
2000      if(printer_state.motorX <= -2) {
2001        ANALYZER_ON(ANALYZER_CH2);
2002        WRITE(X_STEP_PIN,HIGH);
2003        printer_state.motorX += 2;
2004      } else if(printer_state.motorX >= 2) {
2005        ANALYZER_ON(ANALYZER_CH2);
2006        WRITE(X_STEP_PIN,HIGH);
2007        printer_state.motorX -= 2;
2008      }
2009      if(printer_state.motorY <= -2) {
2010        ANALYZER_ON(ANALYZER_CH3);
2011        WRITE(Y_STEP_PIN,HIGH);
2012        printer_state.motorY += 2;
2013      } else if(printer_state.motorY >= 2) {
2014        ANALYZER_ON(ANALYZER_CH3);
2015        WRITE(Y_STEP_PIN,HIGH);
2016        printer_state.motorY -= 2;
2017      }
2018  
2019  #endif
2020  
2021      if(cur->dir & 64) {
2022        if((cur->error[2] -= cur->delta[2]) < 0) {
2023          WRITE(Z_STEP_PIN,HIGH);
2024          cur->error[2] += cur_errupd;
2025  #ifdef DEBUG_STEPCOUNT
2026          cur->totalStepsRemaining--;
2027  #endif
2028        }
2029      }
2030  #if STEPPER_HIGH_DELAY>0
2031      delayMicroseconds(STEPPER_HIGH_DELAY);
2032  #endif
2033  #if USE_OPS==1 || defined(USE_ADVANCE)
2034      if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)==0) // Use interrupt for movement
2035  #endif
2036        extruder_unstep();
2037      WRITE(X_STEP_PIN,LOW);
2038      WRITE(Y_STEP_PIN,LOW);
2039      WRITE(Z_STEP_PIN,LOW);
2040      ANALYZER_OFF(ANALYZER_CH1);
2041      ANALYZER_OFF(ANALYZER_CH2);
2042      ANALYZER_OFF(ANALYZER_CH3);
2043      ANALYZER_OFF(ANALYZER_CH6);
2044      ANALYZER_OFF(ANALYZER_CH7);
2045    } // for loop
2046    if(do_odd) {
2047        sei(); // Allow interrupts for other types, timer1 is still disabled
2048  #ifdef RAMP_ACCELERATION
2049        //If acceleration is enabled on this move and we are in the acceleration segment, calculate the current interval
2050        if (printer_state.stepNumber <= cur->accelSteps) { // we are accelerating
2051          printer_state.vMaxReached = ComputeV(printer_state.timer,cur->facceleration)+cur->vStart;
2052          if(printer_state.vMaxReached>cur->vMax) printer_state.vMaxReached = cur->vMax;
2053          unsigned int v;
2054          if(printer_state.vMaxReached>STEP_DOUBLER_FREQUENCY) {
2055   #if ALLOW_QUADSTEPPING
2056            if(printer_state.vMaxReached>STEP_DOUBLER_FREQUENCY*2) {
2057              printer_state.stepper_loops = 4;
2058              v = printer_state.vMaxReached>>2;
2059            } else {
2060              printer_state.stepper_loops = 2;
2061              v = printer_state.vMaxReached>>1;
2062            }
2063   #else
2064            printer_state.stepper_loops = 2;
2065            v = printer_state.vMaxReached>>1;
2066   #endif
2067          } else {
2068            printer_state.stepper_loops = 1;
2069            v = printer_state.vMaxReached;
2070          }
2071          printer_state.interval = CPUDivU2(v);
2072          printer_state.timer+=printer_state.interval;
2073  #ifdef USE_ADVANCE
2074  #ifdef ENABLE_QUADRATIC_ADVANCE
2075          long advance_target =printer_state.advance_executed+cur->advanceRate;
2076          for(byte loop=1;loop<max_loops;loop++) advance_target+=cur->advanceRate;
2077          if(advance_target>cur->advanceFull)
2078            advance_target = cur->advanceFull;
2079          cli();
2080          long h = mulu6xu16to32(printer_state.vMaxReached,cur->advanceL);
2081          int tred = ((advance_target+h)>>16);
2082          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2083          printer_state.advance_steps_set = tred;
2084          sei();
2085          printer_state.advance_executed = advance_target;
2086  #else
2087          int tred = mulu6xu16shift16(printer_state.vMaxReached,cur->advanceL);
2088          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2089          printer_state.advance_steps_set = tred;
2090          sei();
2091  #endif
2092  #endif
2093        } else if (cur->stepsRemaining <= cur->decelSteps) { // time to slow down
2094          if (!(cur->flags & FLAG_DECELERATING)) {
2095             printer_state.timer = 0;
2096             cur->flags |= FLAG_DECELERATING;
2097          }
2098          unsigned int v = ComputeV(printer_state.timer,cur->facceleration);
2099          if (v > printer_state.vMaxReached)   // if deceleration goes too far it can become too large
2100            v = cur->vEnd;
2101          else{
2102            v=printer_state.vMaxReached-v;
2103            if (v<cur->vEnd) v = cur->vEnd; // extra steps at the end of desceleration due to rounding erros
2104          }
2105  #ifdef USE_ADVANCE
2106          unsigned int v0 = v;
2107  #endif
2108          if(v>STEP_DOUBLER_FREQUENCY) {
2109  #if ALLOW_QUADSTEPPING
2110            if(v>STEP_DOUBLER_FREQUENCY*2) {
2111              printer_state.stepper_loops = 4;
2112              v = v>>2;
2113            } else {
2114              printer_state.stepper_loops = 2;
2115              v = v>>1;
2116            }
2117  #else
2118            printer_state.stepper_loops = 2;
2119            v = v>>1;
2120  #endif
2121          } else {
2122            printer_state.stepper_loops = 1;
2123          }
2124          printer_state.interval = CPUDivU2(v);
2125          printer_state.timer+=printer_state.interval;
2126  #ifdef USE_ADVANCE
2127  #ifdef ENABLE_QUADRATIC_ADVANCE
2128          long advance_target =printer_state.advance_executed-cur->advanceRate;
2129          for(byte loop=1;loop<max_loops;loop++) advance_target-=cur->advanceRate;
2130          if(advance_target<cur->advanceEnd)
2131            advance_target = cur->advanceEnd;
2132          long h=mulu6xu16to32(cur->advanceL,v0);
2133          int tred = ((advance_target+h)>>16);
2134          cli();
2135          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2136          printer_state.advance_steps_set = tred;
2137          sei();
2138          printer_state.advance_executed = advance_target;
2139  #else
2140          int tred=mulu6xu16shift16(cur->advanceL,v0);
2141          cli();
2142          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2143          printer_state.advance_steps_set = tred;
2144          sei();
2145  #endif
2146  #endif
2147        } else {
2148          // If we had acceleration, we need to use the latest vMaxReached and interval
2149          // If we started full speed, we need to use cur->fullInterval and vMax
2150  #ifdef USE_ADVANCE
2151          unsigned int v;
2152          if(!cur->accelSteps) {
2153            v = cur->vMax;
2154          } else {
2155            v = printer_state.vMaxReached;
2156          }
2157  #ifdef ENABLE_QUADRATIC_ADVANCE
2158          long h=mulu6xu16to32(cur->advanceL,v);
2159          int tred = ((printer_state.advance_executed+h)>>16);
2160          cli();
2161          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2162          printer_state.advance_steps_set = tred;
2163          sei();
2164  #else
2165          int tred=mulu6xu16shift16(cur->advanceL,v);
2166          cli();
2167          printer_state.extruderStepsNeeded+=tred-printer_state.advance_steps_set;
2168          printer_state.advance_steps_set = tred;
2169          sei();
2170  #endif
2171  #endif
2172          if(!cur->accelSteps) {
2173            if(cur->vMax>STEP_DOUBLER_FREQUENCY) {
2174  #if ALLOW_QUADSTEPPING
2175              if(cur->vMax>STEP_DOUBLER_FREQUENCY*2) {
2176                printer_state.stepper_loops = 4;
2177                printer_state.interval = cur->fullInterval>>2;
2178              } else {
2179                printer_state.stepper_loops = 2;
2180                printer_state.interval = cur->fullInterval>>1;
2181              }
2182  #else
2183              printer_state.stepper_loops = 2;
2184              printer_state.interval = cur->fullInterval>>1;
2185  #endif
2186            } else {
2187              printer_state.stepper_loops = 1;
2188              printer_state.interval = cur->fullInterval;
2189           }
2190         }
2191        }
2192  #else
2193        printer_state.interval = cur->fullInterval; // without RAMPS always use full speed
2194  #endif
2195      } // do_odd
2196      if(do_even) {
2197       printer_state.stepNumber+=max_loops;
2198       cur->stepsRemaining-=max_loops;
2199      }
2200  
2201  #if USE_OPS==1
2202      if(printer_state.opsMode==2 && (cur->joinFlags & FLAG_JOIN_END_RETRACT) && printer_state.filamentRetracted && cur->stepsRemaining<=cur->opsReverseSteps) {
2203  #ifdef DEBUG_OPS
2204        OUT_P_L_LN("DownX",cur->stepsRemaining);
2205  #endif
2206        // Point for retraction reversal reached.
2207        printer_state.filamentRetracted = false;
2208        cli();
2209        printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
2210  #ifdef DEBUG_OPS
2211        sei();
2212        OUT_P_L_LN("N=",printer_state.extruderStepsNeeded);
2213  #endif
2214    }
2215  #endif
2216    } // stepsRemaining
2217    long interval;
2218    if(cur->halfstep) interval = (printer_state.interval>>1); // time to come back
2219    else interval = printer_state.interval;
2220    if(do_even) {
2221      if(cur->stepsRemaining<=0 || (cur->dir & 240)==0) { // line finished
2222  #ifdef DEBUG_STEPCOUNT
2223          if(cur->totalStepsRemaining)
2224            OUT_P_L_LN("Missed steps:",cur->totalStepsRemaining);
2225  #endif
2226  
2227  #if USE_OPS==1
2228       if(cur->joinFlags & FLAG_JOIN_END_RETRACT) { // Make sure filament is pushed back
2229          sei();
2230          if(printer_state.filamentRetracted) {
2231  #ifdef DEBUG_OPS
2232            out.println_P(PSTR("Down"));
2233  #endif
2234            printer_state.filamentRetracted = false;
2235            cli();
2236            printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
2237          }
2238          cli();
2239          if(printer_state.extruderStepsNeeded) {
2240  #ifdef DEBUG_OPS
2241      //      sei();
2242      //      out.println_int_P(PSTR("W"),printer_state.extruderStepsNeeded);
2243  #endif
2244            return 4000; // wait, work is done in other interrupt
2245          }
2246  #ifdef DEBUG_OPS
2247            sei();
2248  #endif
2249       }
2250  #endif
2251       cli();
2252       NEXT_PLANNER_INDEX(lines_pos);
2253       cur = 0;
2254       --lines_count;
2255  #ifdef XY_GANTRY
2256         if(DISABLE_X && DISABLE_Y) {
2257           disable_x();
2258           disable_y();
2259         }
2260  #else
2261         if(DISABLE_X) disable_x();
2262         if(DISABLE_Y) disable_y();
2263  #endif
2264         if(DISABLE_Z) disable_z();
2265       if(lines_count==0) UI_STATUS(UI_TEXT_IDLE);
2266       interval = printer_state.interval = interval>>1; // 50% of time to next call to do cur=0
2267     }
2268     DEBUG_MEMORY;
2269    } // Do even
2270    return interval;
2271  }
2272  #endif
2273  void(* resetFunc) (void) = 0; //declare reset function @ address 0
2274  /**
2275    \brief Stop heater and stepper motors. Disable power,if possible.
2276  */
2277  void kill(byte only_steppers)
2278  {
2279    if((printer_state.flag0 & PRINTER_FLAG0_STEPPER_DISABLED) && only_steppers) return;
2280    printer_state.flag0 |=PRINTER_FLAG0_STEPPER_DISABLED;
2281    disable_x();
2282    disable_y();
2283    disable_z();
2284    extruder_disable();
2285    if(!only_steppers) {
2286      for(byte i=0;i<NUM_EXTRUDER;i++)
2287        extruder_set_temperature(0,i);
2288      heated_bed_set_temperature(0);
2289      UI_STATUS_UPD(UI_TEXT_KILLED);
2290  #if defined(PS_ON_PIN) && PS_ON_PIN>-1
2291        //pinMode(PS_ON_PIN,INPUT);
2292        SET_OUTPUT(PS_ON_PIN); //GND
2293        WRITE(PS_ON_PIN, HIGH);
2294  #endif
2295    } else UI_STATUS_UPD(UI_TEXT_STEPPER_DISABLED);
2296  }
2297  long stepperWait = 0;
2298  /** \brief Sets the timer 1 compare value to delay ticks.
2299  
2300  This function sets the OCR1A compare counter  to get the next interrupt
2301  at delay ticks measured from the last interrupt. delay must be << 2^24
2302  */
2303  inline void setTimer(unsigned long delay)
2304  {
2305    __asm__ __volatile__ (
2306    "cli \n\t"
2307    "tst %C[delay] \n\t" //if(delay<65536) {
2308    "brne else%= \n\t"
2309    "cpi %B[delay],255 \n\t"
2310    "breq else%= \n\t" // delay <65280
2311    "sts stepperWait,r1 \n\t" // stepperWait = 0;
2312    "sts stepperWait+1,r1 \n\t"
2313    "sts stepperWait+2,r1 \n\t"
2314    "lds %C[delay],%[time] \n\t" // Read TCNT1
2315    "lds %D[delay],%[time]+1 \n\t"
2316    "ldi r18,100 \n\t" // Add 100 to TCNT1
2317    "add %C[delay],r18 \n\t"
2318    "adc %D[delay],r1 \n\t"
2319    "cp %A[delay],%C[delay] \n\t" // delay<TCNT1+1
2320    "cpc %B[delay],%D[delay] \n\t"
2321    "brcc exact%= \n\t"
2322    "sts %[ocr]+1,%D[delay] \n\t" //  OCR1A = TCNT1+100;
2323    "sts %[ocr],%C[delay] \n\t"
2324    "rjmp end%= \n\t"
2325    "exact%=: sts %[ocr]+1,%B[delay] \n\t" //  OCR1A = delay;
2326    "sts %[ocr],%A[delay] \n\t"
2327    "rjmp end%= \n\t"
2328    "else%=: subi	%B[delay], 0x80 \n\t" //} else { stepperWait = delay-32768;
2329    "sbci	%C[delay], 0x00 \n\t"
2330    "sts stepperWait,%A[delay] \n\t"
2331    "sts stepperWait+1,%B[delay] \n\t"
2332    "sts stepperWait+2,%C[delay] \n\t"
2333    "ldi	%D[delay], 0x80 \n\t" //OCR1A = 32768;
2334    "sts	%[ocr]+1, %D[delay] \n\t"
2335    "sts	%[ocr], r1 \n\t"
2336    "end%=: \n\t"
2337    :[delay]"=&d"(delay) // Output
2338    :"0"(delay),[ocr]"i" (_SFR_MEM_ADDR(OCR1A)),[time]"i"(_SFR_MEM_ADDR(TCNT1)) // Input
2339    :"r18" // Clobber
2340    );
2341  /* // Assembler above replaced this code
2342    if(delay<65280) {
2343      stepperWait = 0;
2344      unsigned int count = TCNT1+100;
2345      if(delay<count)
2346        OCR1A = count;
2347      else
2348        OCR1A = delay;
2349    } else {
2350      stepperWait = delay-32768;
2351      OCR1A = 32768;
2352    }*/
2353  }
2354  volatile byte insideTimer1=0;
2355  /** \brief Timer interrupt routine to drive the stepper motors.
2356  */
2357  ISR(TIMER1_COMPA_vect)
2358  {
2359    if(insideTimer1) return;
2360    byte doExit;
2361    __asm__ __volatile__ (
2362    "ldi %[ex],0 \n\t"
2363    "lds r23,stepperWait+2 \n\t"
2364    "tst r23 \n\t" //if(stepperWait<65536) {
2365    "brne else%= \n\t" // Still > 65535
2366    "lds r23,stepperWait+1 \n\t"
2367    "tst r23 \n\t"
2368    "brne last%= \n\t" // Still not 0, go ahead
2369    "lds r22,stepperWait \n\t"
2370    "breq end%= \n\t" // stepperWait is 0, do your work
2371    "last%=: \n\t"
2372    "sts %[ocr]+1,r23 \n\t" //  OCR1A = stepper wait;
2373    "sts %[ocr],r22 \n\t"
2374    "sts stepperWait,r1 \n\t"
2375    "sts stepperWait+1,r1 \n\t"
2376    "rjmp end1%= \n\t"
2377    "else%=: lds r22,stepperWait+1 \n\t" //} else { stepperWait = stepperWait-32768;
2378    "subi	r22, 0x80 \n\t"
2379    "sbci	r23, 0x00 \n\t"
2380    "sts stepperWait+1,r22 \n\t"	// ocr1a stays 32768
2381    "sts stepperWait+2,r23 \n\t"
2382    "end1%=: ldi %[ex],1 \n\t"
2383    "end%=: \n\t"
2384    :[ex]"=&d"(doExit):[ocr]"i" (_SFR_MEM_ADDR(OCR1A)):"r22","r23" );
2385    if(doExit) return;
2386    insideTimer1=1;
2387    OCR1A=61000;
2388    if(lines_count) {
2389      setTimer(bresenham_step());
2390    } else {
2391      if(waitRelax==0) {
2392  #if USE_OPS==1
2393        // push filament in normal position if printings stops, so we have a defined starting position
2394        if(printer_state.opsMode && printer_state.filamentRetracted) {
2395  #ifdef DEBUG_OPS
2396          out.println_P(PSTR("DownI"));
2397  #endif
2398          printer_state.extruderStepsNeeded+=printer_state.opsPushbackSteps;
2399          printer_state.filamentRetracted = false;
2400        }
2401        printmoveSeen = 0;
2402  #endif
2403  #ifdef USE_ADVANCE
2404        if(printer_state.advance_steps_set) {
2405          printer_state.extruderStepsNeeded-=printer_state.advance_steps_set;
2406  #ifdef ENABLE_QUADRATIC_ADVANCE
2407          printer_state.advance_executed = 0;
2408  #endif
2409          printer_state.advance_steps_set = 0;
2410        }
2411  #endif
2412  #if USE_OPS==1 || defined(USE_ADVANCE)
2413        if(!printer_state.extruderStepsNeeded) if(DISABLE_E) extruder_disable();
2414  #else
2415        if(DISABLE_E) extruder_disable();
2416  #endif
2417      } else waitRelax--;
2418      stepperWait = 0; // Importent becaus of optimization in asm at begin
2419      OCR1A = 65500; // Wait for next move
2420    }
2421    DEBUG_MEMORY;
2422    insideTimer1=0;
2423  }
2424  
2425  #if USE_OPS==1 || defined(USE_ADVANCE)
2426  byte extruder_wait_dirchange=0; ///< Wait cycles, if direction changes. Prevents stepper from loosing steps.
2427  char extruder_last_dir = 0;
2428  byte extruder_speed = 0;
2429  #endif
2430  
2431  
2432  /** \brief Timer routine for extruder stepper.
2433  
2434  Several methods need to move the extruder. To get a optima result,
2435  all methods update the printer_state.extruderStepsNeeded with the
2436  number of additional steps needed. During this interrupt, one step
2437  is executed. This will keep the extruder moving, until the total
2438  wanted movement is achieved. This will be done with the maximum
2439  allowable speed for the extruder.
2440  */
2441  ISR(EXTRUDER_TIMER_VECTOR)
2442  {
2443  #if USE_OPS==1 || defined(USE_ADVANCE)
2444    if((printer_state.flag0 & PRINTER_FLAG0_SEPERATE_EXTRUDER_INT)==0) return; // currently no need
2445    byte timer = EXTRUDER_OCR;
2446    bool increasing = printer_state.extruderStepsNeeded>0;
2447    
2448    if(printer_state.extruderStepsNeeded==0) {
2449        extruder_last_dir = 0;
2450    }  else if((increasing>0 && extruder_last_dir<0) || (!increasing && extruder_last_dir>0)) {
2451      EXTRUDER_OCR = timer+50; // Little delay to accomodate to reversed direction     
2452      extruder_set_direction(increasing ? 1 : 0);    
2453      extruder_last_dir = (increasing ? 1 : -1);
2454      return;
2455    } else {
2456      if(extruder_last_dir==0) {
2457        extruder_set_direction(increasing ? 1 : 0);    
2458        extruder_last_dir = (increasing ? 1 : -1);
2459      }
2460      extruder_step();
2461      printer_state.extruderStepsNeeded-=extruder_last_dir;
2462  #if STEPPER_HIGH_DELAY>0
2463      delayMicroseconds(STEPPER_HIGH_DELAY);
2464  #endif    
2465      extruder_unstep();
2466    }
2467    EXTRUDER_OCR = timer+printer_state.maxExtruderSpeed;
2468    
2469  /* Version of 0.7 branch
2470    static byte accdelay=10;
2471    if(printer_state.extruderStepsNeeded==0) {
2472        extruder_last_dir = 0;
2473    }  else if((increasing>0 && extruder_last_dir<0) || (!increasing && extruder_last_dir>0)) {
2474      EXTRUDER_OCR = timer+50; // Little delay to accomodate to reversed direction     
2475      extruder_set_direction(increasing ? 1 : 0);    
2476      extruder_last_dir = (increasing ? 1 : -1);
2477      return;
2478    } else {
2479      if(extruder_last_dir==0) {
2480        extruder_set_direction(increasing ? 1 : 0);    
2481        extruder_last_dir = (increasing ? 1 : -1);
2482      }
2483      extruder_step();
2484      printer_state.extruderStepsNeeded-=extruder_last_dir;
2485  #if STEPPER_HIGH_DELAY>0
2486      delayMicroseconds(STEPPER_HIGH_DELAY);
2487  #endif    
2488      extruder_unstep();
2489    }
2490    EXTRUDER_OCR = timer+printer_state.maxExtruderSpeed;  
2491    }
2492    */
2493  /*
2494    EXTRUDER_OCR += printer_state.timer0Interval; // time to come back
2495    // The stepper signals are in strategical positions for optimal timing. If you
2496    // still have timing issues, add dummy commands between.
2497    if(printer_state.extruderStepsNeeded) {
2498      extruder_unstep();
2499      if(printer_state.extruderStepsNeeded<0) { // Backward step
2500        extruder_set_direction(0);
2501        if(extruder_wait_dirchange && extruder_last_dir==-1) {
2502          extruder_wait_dirchange--;
2503          return;
2504        }
2505        extruder_last_dir = 1;
2506        extruder_wait_dirchange=2;
2507        printer_state.extruderStepsNeeded++;
2508      } else { // Forward step
2509        extruder_set_direction(1);
2510        if(extruder_wait_dirchange && extruder_last_dir==1) {
2511          extruder_wait_dirchange--;
2512          return;
2513        }
2514        extruder_last_dir = -1;
2515        extruder_wait_dirchange=2;
2516        printer_state.extruderStepsNeeded--;
2517      }
2518      if(current_extruder->currentTemperatureC>=MIN_EXTRUDER_TEMP<<CELSIUS_EXTRA_BITS) // Saftey first
2519        extruder_step();
2520    } else {
2521      if(extruder_wait_dirchange)
2522        extruder_wait_dirchange--;
2523    }*/
2524  #endif
2525  }
2526  
2527  /**
2528  This timer is called 3906 timer per second. It is used to update pwm values for heater and some other frequent jobs.
2529  */
2530  ISR(PWM_TIMER_VECTOR)
2531  {
2532    static byte pwm_count = 0;
2533    static byte pwm_pos_set[NUM_EXTRUDER+3];
2534    static byte pwm_cooler_pos_set[NUM_EXTRUDER];
2535    PWM_OCR += 64; 
2536    if(pwm_count==0) {
2537  #if EXT0_HEATER_PIN>-1
2538      if((pwm_pos_set[0] = pwm_pos[0])>0) WRITE(EXT0_HEATER_PIN,1);
2539  #if EXT0_EXTRUDER_COOLER_PIN>-1
2540      if((pwm_cooler_pos_set[0] = extruder[0].coolerPWM)>0) WRITE(EXT0_EXTRUDER_COOLER_PIN,1);
2541  #endif
2542  #endif
2543  #if defined(EXT1_HEATER_PIN) && EXT1_HEATER_PIN>-1
2544      if((pwm_pos_set[1] = pwm_pos[1])>0) WRITE(EXT1_HEATER_PIN,1);
2545  #if EXT1_EXTRUDER_COOLER_PIN>-1
2546      if((pwm_cooler_pos_set[1] = extruder[1].coolerPWM)>0) WRITE(EXT1_EXTRUDER_COOLER_PIN,1);
2547  #endif
2548  #endif
2549  #if defined(EXT2_HEATER_PIN) && EXT2_HEATER_PIN>-1
2550      if((pwm_pos_set[2] = pwm_pos[2])>0) WRITE(EXT2_HEATER_PIN,1);
2551  #if EXT2_EXTRUDER_COOLER_PIN>-1
2552      if((pwm_cooler_pos_set[2] = extruder[2].coolerPWM)>0) WRITE(EXT2_EXTRUDER_COOLER_PIN,1);
2553  #endif
2554  #endif
2555  #if defined(EXT3_HEATER_PIN) && EXT3_HEATER_PIN>-1
2556      if((pwm_pos_set[3] = pwm_pos[3])>0) WRITE(EXT3_HEATER_PIN,1);
2557  #if EXT3_EXTRUDER_COOLER_PIN>-1
2558      if((pwm_cooler_pos_set[3] = extruder[3].coolerPWM)>0) WRITE(EXT3_EXTRUDER_COOLER_PIN,1);
2559  #endif
2560  #endif
2561  #if defined(EXT4_HEATER_PIN) && EXT4_HEATER_PIN>-1
2562      if((pwm_pos_set[4] = pwm_pos[4])>0) WRITE(EXT4_HEATER_PIN,1);
2563  #if EXT4_EXTRUDER_COOLER_PIN>-1
2564      if((pwm_cooler_pos_set[4] = pwm_pos[4].coolerPWM)>0) WRITE(EXT4_EXTRUDER_COOLER_PIN,1);
2565  #endif
2566  #endif
2567  #if defined(EXT5_HEATER_PIN) && EXT5_HEATER_PIN>-1
2568      if((pwm_pos_set[5] = pwm_pos[5])>0) WRITE(EXT5_HEATER_PIN,1);
2569  #if EXT5_EXTRUDER_COOLER_PIN>-1
2570      if((pwm_cooler_pos_set[5] = extruder[5].coolerPWM)>0) WRITE(EXT5_EXTRUDER_COOLER_PIN,1);
2571  #endif
2572  #endif
2573  #if FAN_BOARD_PIN>-1
2574      if((pwm_pos_set[NUM_EXTRUDER+1] = pwm_pos[NUM_EXTRUDER+1])>0) WRITE(FAN_BOARD_PIN,1);
2575  #endif
2576  #if FAN_PIN>-1 && FEATURE_FAN_CONTROL
2577      if((pwm_pos_set[NUM_EXTRUDER+2] = pwm_pos[NUM_EXTRUDER+2])>0) WRITE(FAN_PIN,1);
2578  #endif
2579  #if HEATED_BED_HEATER_PIN>-1 && HAVE_HEATED_BED
2580      if((pwm_pos_set[NUM_EXTRUDER] = pwm_pos[NUM_EXTRUDER])>0) WRITE(HEATED_BED_HEATER_PIN,1);
2581  #endif
2582    }
2583  #if EXT0_HEATER_PIN>-1
2584      if(pwm_pos_set[0] == pwm_count && pwm_pos_set[0]!=255) WRITE(EXT0_HEATER_PIN,0);
2585  #if EXT0_EXTRUDER_COOLER_PIN>-1
2586      if(pwm_cooler_pos_set[0] == pwm_count && pwm_cooler_pos_set[0]!=255) WRITE(EXT0_EXTRUDER_COOLER_PIN,0);
2587  #endif
2588  #endif
2589  #if defined(EXT1_HEATER_PIN) && EXT1_HEATER_PIN>-1
2590      if(pwm_pos_set[1] == pwm_count && pwm_pos_set[1]!=255) WRITE(EXT1_HEATER_PIN,0);
2591  #if EXT1_EXTRUDER_COOLER_PIN>-1
2592      if(pwm_cooler_pos_set[1] == pwm_count && pwm_cooler_pos_set[1]!=255) WRITE(EXT1_EXTRUDER_COOLER_PIN,0);
2593  #endif
2594  #endif
2595  #if defined(EXT2_HEATER_PIN) && EXT2_HEATER_PIN>-1
2596      if(pwm_pos_set[2] == pwm_count && pwm_pos_set[2]!=255) WRITE(EXT2_HEATER_PIN,0);
2597  #if EXT2_EXTRUDER_COOLER_PIN>-1
2598      if(pwm_cooler_pos_set[2] == pwm_count && pwm_cooler_pos_set[2]!=255) WRITE(EXT2_EXTRUDER_COOLER_PIN,0);
2599  #endif
2600  #endif
2601  #if defined(EXT3_HEATER_PIN) && EXT3_HEATER_PIN>-1
2602      if(pwm_pos_set[3] == pwm_count && pwm_pos_set[3]!=255) WRITE(EXT3_HEATER_PIN,0);
2603  #if EXT3_EXTRUDER_COOLER_PIN>-1
2604      if(pwm_cooler_pos_set[3] == pwm_count && pwm_cooler_pos_set[3]!=255) WRITE(EXT3_EXTRUDER_COOLER_PIN,0);
2605  #endif
2606  #endif
2607  #if defined(EXT4_HEATER_PIN) && EXT4_HEATER_PIN>-1
2608      if(pwm_pos_set[4] == pwm_count && pwm_pos_set[4]!=255) WRITE(EXT4_HEATER_PIN,0);
2609  #if EXT4_EXTRUDER_COOLER_PIN>-1
2610      if(pwm_cooler_pos_set[4] == pwm_count && pwm_cooler_pos_set[4]!=255) WRITE(EXT4_EXTRUDER_COOLER_PIN,0);
2611  #endif
2612  #endif
2613  #if defined(EXT5_HEATER_PIN) && EXT5_HEATER_PIN>-1
2614      if(pwm_pos_set[5] == pwm_count && pwm_pos_set[5]!=255) WRITE(EXT5_HEATER_PIN,0);
2615  #if EXT5_EXTRUDER_COOLER_PIN>-1
2616      if(pwm_cooler_pos_set[5] == pwm_count && pwm_cooler_pos_set[5]!=255) WRITE(EXT5_EXTRUDER_COOLER_PIN,0);
2617  #endif
2618  #endif
2619  #if FAN_BOARD_PIN>-1
2620      if(pwm_pos_set[NUM_EXTRUDER+2] == pwm_count && pwm_pos_set[NUM_EXTRUDER+2]!=255) WRITE(FAN_BOARD_PIN,0);
2621  #endif
2622  #if FAN_PIN>-1 && FEATURE_FAN_CONTROL
2623      if(pwm_pos_set[NUM_EXTRUDER+2] == pwm_count && pwm_pos_set[NUM_EXTRUDER+2]!=255) WRITE(FAN_PIN,0);
2624  #endif
2625  #if HEATED_BED_HEATER_PIN>-1 && HAVE_HEATED_BED
2626      if(pwm_pos_set[NUM_EXTRUDER] == pwm_count && pwm_pos_set[NUM_EXTRUDER]!=255) WRITE(HEATED_BED_HEATER_PIN,0);
2627  #endif
2628    sei(); 
2629    counter_periodical++; // Appxoimate a 100ms timer
2630    if(counter_periodical>=(int)(F_CPU/40960)) {
2631      counter_periodical=0;
2632      execute_periodical=1;
2633    }
2634  // read analog values
2635  #if ANALOG_INPUTS>0
2636  if((ADCSRA & _BV(ADSC))==0) { // Conversion finished?
2637    osAnalogInputBuildup[osAnalogInputPos] += ADCW;
2638    if(++osAnalogInputCounter[osAnalogInputPos]>=_BV(ANALOG_INPUT_SAMPLE)) {
2639  #if ANALOG_INPUT_BITS+ANALOG_INPUT_SAMPLE<12
2640      osAnalogInputValues[osAnalogInputPos] =
2641        osAnalogInputBuildup[osAnalogInputPos] <<
2642        (12-ANALOG_INPUT_BITS-ANALOG_INPUT_SAMPLE);
2643  #endif
2644  #if ANALOG_INPUT_BITS+ANALOG_INPUT_SAMPLE>12
2645      osAnalogInputValues[osAnalogInputPos] =
2646        osAnalogInputBuildup[osAnalogInputPos] >>
2647        (ANALOG_INPUT_BITS+ANALOG_INPUT_SAMPLE-12);
2648  #endif
2649  #if ANALOG_INPUT_BITS+ANALOG_INPUT_SAMPLE==12
2650      osAnalogInputValues[osAnalogInputPos] =
2651        osAnalogInputBuildup[osAnalogInputPos];
2652  #endif
2653      osAnalogInputBuildup[osAnalogInputPos] = 0;
2654      osAnalogInputCounter[osAnalogInputPos] = 0;
2655      // Start next conversion
2656      if(++osAnalogInputPos>=ANALOG_INPUTS) osAnalogInputPos = 0;
2657      byte channel = pgm_read_byte(&osAnalogInputChannels[osAnalogInputPos]);
2658  #if defined(ADCSRB) && defined(MUX5)
2659        if(channel & 8)  // Reading channel 0-7 or 8-15?
2660          ADCSRB |= _BV(MUX5);
2661        else
2662          ADCSRB &= ~_BV(MUX5);
2663  #endif
2664      ADMUX = (ADMUX & ~(0x1F)) | (channel & 7);
2665    }
2666    ADCSRA |= _BV(ADSC);  // start next conversion
2667    }
2668  #endif
2669  
2670   UI_FAST; // Short timed user interface action
2671   pwm_count++;
2672  }
2673  
2674