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 © 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