2016-03-25 07:19:46 +01:00
/**
2016-03-24 19:01:20 +01:00
* Marlin 3 D Printer Firmware
* Copyright ( C ) 2016 MarlinFirmware [ https : //github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl .
* Copyright ( C ) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
2015-05-17 10:44:53 +02:00
/**
2016-04-27 16:15:20 +02:00
* stepper . cpp - A singleton object to execute motion plans using stepper motors
2015-05-17 10:44:53 +02:00
* Marlin Firmware
*
* Derived from Grbl
* Copyright ( c ) 2009 - 2011 Simen Svale Skogsrud
*
* Grbl is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Grbl is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Grbl . If not , see < http : //www.gnu.org/licenses/>.
*/
2011-11-13 20:42:08 +01:00
/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
and Philipp Tiefenbacher . */
# include "Marlin.h"
2011-12-22 14:55:45 +01:00
# include "stepper.h"
2016-04-27 16:15:20 +02:00
# include "endstops.h"
2011-11-13 20:42:08 +01:00
# include "planner.h"
# include "temperature.h"
# include "ultralcd.h"
2012-03-03 16:51:47 +01:00
# include "language.h"
2013-01-08 11:53:18 +01:00
# include "cardreader.h"
2011-11-13 20:42:08 +01:00
# include "speed_lookuptable.h"
2016-03-20 03:03:17 +01:00
2017-11-23 01:28:43 +01:00
# if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(ULTIPANEL)
# include "ubl.h"
# endif
2015-03-14 12:28:22 +01:00
# if HAS_DIGIPOTSS
# include <SPI.h>
2012-11-21 20:53:56 +01:00
# endif
2011-11-13 20:42:08 +01:00
2016-04-27 16:15:20 +02:00
Stepper stepper ; // Singleton
2011-12-04 21:03:02 +01:00
2016-05-12 00:24:24 +02:00
// public:
block_t * Stepper : : current_block = NULL ; // A pointer to the block currently being traced
# if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
bool Stepper : : abort_on_endstop_hit = false ;
# endif
2017-10-27 23:24:34 +02:00
# if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
2016-05-12 00:24:24 +02:00
bool Stepper : : performing_homing = false ;
# endif
2017-06-03 07:38:07 +02:00
# if HAS_MOTOR_CURRENT_PWM
2017-07-18 10:17:50 +02:00
uint32_t Stepper : : motor_current_setting [ 3 ] ; // Initialized by settings.load()
2017-06-03 07:38:07 +02:00
# endif
2016-05-12 00:24:24 +02:00
// private:
2017-06-25 05:23:45 +02:00
uint8_t Stepper : : last_direction_bits = 0 ; // The next stepping-bits to be output
2017-12-06 20:23:28 +01:00
int16_t Stepper : : cleaning_buffer_counter = 0 ;
2016-05-12 00:24:24 +02:00
2017-10-27 23:24:34 +02:00
# if ENABLED(X_DUAL_ENDSTOPS)
bool Stepper : : locked_x_motor = false , Stepper : : locked_x2_motor = false ;
# endif
# if ENABLED(Y_DUAL_ENDSTOPS)
bool Stepper : : locked_y_motor = false , Stepper : : locked_y2_motor = false ;
# endif
2016-05-12 00:24:24 +02:00
# if ENABLED(Z_DUAL_ENDSTOPS)
2017-10-27 23:24:34 +02:00
bool Stepper : : locked_z_motor = false , Stepper : : locked_z2_motor = false ;
2016-05-12 00:24:24 +02:00
# endif
2016-09-20 12:16:05 +02:00
long Stepper : : counter_X = 0 ,
Stepper : : counter_Y = 0 ,
Stepper : : counter_Z = 0 ,
Stepper : : counter_E = 0 ;
2016-05-12 00:24:24 +02:00
2016-08-30 21:19:49 +02:00
volatile uint32_t Stepper : : step_events_completed = 0 ; // The number of step events executed in the current block
2016-05-12 00:24:24 +02:00
2017-10-09 11:13:43 +02:00
# if ENABLED(LIN_ADVANCE)
2016-05-04 21:10:42 +02:00
2016-12-24 03:43:23 +01:00
constexpr uint16_t ADV_NEVER = 65535 ;
2016-12-12 20:30:02 +01:00
uint16_t Stepper : : nextMainISR = 0 ,
2016-12-24 03:43:23 +01:00
Stepper : : nextAdvanceISR = ADV_NEVER ,
Stepper : : eISR_Rate = ADV_NEVER ;
2016-05-04 21:10:42 +02:00
2017-10-09 11:13:43 +02:00
volatile int Stepper : : e_steps [ E_STEPPERS ] ;
int Stepper : : final_estep_rate ,
Stepper : : current_estep_rate [ E_STEPPERS ] ,
Stepper : : current_adv_steps [ E_STEPPERS ] ;
2016-12-24 03:43:23 +01:00
2017-06-19 12:14:05 +02:00
/**
* See https : //github.com/MarlinFirmware/Marlin/issues/5699#issuecomment-309264382
*
* This fix isn ' t perfect and may lose steps - but better than locking up completely
* in future the planner should slow down if advance stepping rate would be too high
*/
FORCE_INLINE uint16_t adv_rate ( const int steps , const uint16_t timer , const uint8_t loops ) {
if ( steps ) {
const uint16_t rate = ( timer * loops ) / abs ( steps ) ;
//return constrain(rate, 1, ADV_NEVER - 1)
return rate ? rate : 1 ;
}
return ADV_NEVER ;
}
2016-12-24 03:43:23 +01:00
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2016-05-12 00:24:24 +02:00
long Stepper : : acceleration_time , Stepper : : deceleration_time ;
volatile long Stepper : : count_position [ NUM_AXIS ] = { 0 } ;
volatile signed char Stepper : : count_direction [ NUM_AXIS ] = { 1 , 1 , 1 , 1 } ;
2016-06-29 00:06:56 +02:00
# if ENABLED(MIXING_EXTRUDER)
2016-09-02 18:31:45 +02:00
long Stepper : : counter_m [ MIXING_STEPPERS ] ;
2016-06-29 00:06:56 +02:00
# endif
2016-05-12 00:24:24 +02:00
uint8_t Stepper : : step_loops , Stepper : : step_loops_nominal ;
2017-12-09 05:40:07 +01:00
uint16_t Stepper : : OCR1A_nominal ,
Stepper : : acc_step_rate ; // needed for deceleration start point
2016-05-12 00:24:24 +02:00
2016-08-21 05:38:32 +02:00
volatile long Stepper : : endstops_trigsteps [ XYZ ] ;
2016-05-12 00:24:24 +02:00
2017-10-27 23:24:34 +02:00
# if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
# define LOCKED_X_MOTOR locked_x_motor
# define LOCKED_Y_MOTOR locked_y_motor
# define LOCKED_Z_MOTOR locked_z_motor
# define LOCKED_X2_MOTOR locked_x2_motor
# define LOCKED_Y2_MOTOR locked_y2_motor
# define LOCKED_Z2_MOTOR locked_z2_motor
# define DUAL_ENDSTOP_APPLY_STEP(AXIS,v) \
if ( performing_homing ) { \
if ( AXIS # # _HOME_DIR < 0 ) { \
if ( ! ( TEST ( endstops . old_endstop_bits , AXIS # # _MIN ) & & ( count_direction [ AXIS # # _AXIS ] < 0 ) ) & & ! LOCKED_ # # AXIS # # _MOTOR ) AXIS # # _STEP_WRITE ( v ) ; \
if ( ! ( TEST ( endstops . old_endstop_bits , AXIS # # 2 _MIN ) & & ( count_direction [ AXIS # # _AXIS ] < 0 ) ) & & ! LOCKED_ # # AXIS # # 2 _MOTOR ) AXIS # # 2 _STEP_WRITE ( v ) ; \
} \
else { \
if ( ! ( TEST ( endstops . old_endstop_bits , AXIS # # _MAX ) & & ( count_direction [ AXIS # # _AXIS ] > 0 ) ) & & ! LOCKED_ # # AXIS # # _MOTOR ) AXIS # # _STEP_WRITE ( v ) ; \
if ( ! ( TEST ( endstops . old_endstop_bits , AXIS # # 2 _MAX ) & & ( count_direction [ AXIS # # _AXIS ] > 0 ) ) & & ! LOCKED_ # # AXIS # # 2 _MOTOR ) AXIS # # 2 _STEP_WRITE ( v ) ; \
} \
} \
else { \
AXIS # # _STEP_WRITE ( v ) ; \
AXIS # # 2 _STEP_WRITE ( v ) ; \
}
# endif
2016-07-11 19:19:07 +02:00
# if ENABLED(X_DUAL_STEPPER_DRIVERS)
# define X_APPLY_DIR(v,Q) do{ X_DIR_WRITE(v); X2_DIR_WRITE((v) != INVERT_X2_VS_X_DIR); }while(0)
2017-10-27 23:24:34 +02:00
# if ENABLED(DUAL_X_CARRIAGE)
# define X_APPLY_DIR(v,ALWAYS) \
if ( extruder_duplication_enabled | | ALWAYS ) { \
X_DIR_WRITE ( v ) ; \
X2_DIR_WRITE ( v ) ; \
} \
else { \
if ( current_block - > active_extruder ) X2_DIR_WRITE ( v ) ; else X_DIR_WRITE ( v ) ; \
}
# define X_APPLY_STEP(v,ALWAYS) \
if ( extruder_duplication_enabled | | ALWAYS ) { \
X_STEP_WRITE ( v ) ; \
X2_STEP_WRITE ( v ) ; \
} \
else { \
if ( current_block - > active_extruder ) X2_STEP_WRITE ( v ) ; else X_STEP_WRITE ( v ) ; \
}
# elif ENABLED(X_DUAL_ENDSTOPS)
# define X_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(X,v)
# else
# define X_APPLY_STEP(v,Q) do{ X_STEP_WRITE(v); X2_STEP_WRITE(v); }while(0)
# endif
2015-03-14 12:28:22 +01:00
# else
2015-03-15 02:31:25 +01:00
# define X_APPLY_DIR(v,Q) X_DIR_WRITE(v)
# define X_APPLY_STEP(v,Q) X_STEP_WRITE(v)
2015-03-14 12:28:22 +01:00
# endif
2015-07-31 07:28:11 +02:00
# if ENABLED(Y_DUAL_STEPPER_DRIVERS)
2016-07-11 19:19:07 +02:00
# define Y_APPLY_DIR(v,Q) do{ Y_DIR_WRITE(v); Y2_DIR_WRITE((v) != INVERT_Y2_VS_Y_DIR); }while(0)
2017-10-27 23:24:34 +02:00
# if ENABLED(Y_DUAL_ENDSTOPS)
# define Y_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Y,v)
# else
# define Y_APPLY_STEP(v,Q) do{ Y_STEP_WRITE(v); Y2_STEP_WRITE(v); }while(0)
# endif
2015-03-14 12:28:22 +01:00
# else
2015-03-15 02:31:25 +01:00
# define Y_APPLY_DIR(v,Q) Y_DIR_WRITE(v)
# define Y_APPLY_STEP(v,Q) Y_STEP_WRITE(v)
2015-03-14 12:28:22 +01:00
# endif
2015-07-31 07:28:11 +02:00
# if ENABLED(Z_DUAL_STEPPER_DRIVERS)
2016-07-11 19:19:07 +02:00
# define Z_APPLY_DIR(v,Q) do{ Z_DIR_WRITE(v); Z2_DIR_WRITE(v); }while(0)
2015-07-31 07:28:11 +02:00
# if ENABLED(Z_DUAL_ENDSTOPS)
2017-10-27 23:24:34 +02:00
# define Z_APPLY_STEP(v,Q) DUAL_ENDSTOP_APPLY_STEP(Z,v)
2015-03-24 18:06:44 +01:00
# else
2016-07-11 19:19:07 +02:00
# define Z_APPLY_STEP(v,Q) do{ Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }while(0)
2015-03-24 18:06:44 +01:00
# endif
2015-03-14 12:28:22 +01:00
# else
2015-03-15 02:31:25 +01:00
# define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v)
# define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
2015-03-14 12:28:22 +01:00
# endif
2016-06-29 00:06:56 +02:00
# if DISABLED(MIXING_EXTRUDER)
# define E_APPLY_STEP(v,Q) E_STEP_WRITE(v)
# endif
2011-11-13 20:42:08 +01:00
2015-04-17 00:04:38 +02:00
// intRes = longIn1 * longIn2 >> 24
// uses:
// r26 to store 0
// r27 to store bits 16-23 of the 48bit result. The top bit is used to round the two byte result.
// note that the lower two bytes and the upper byte of the 48bit result are not calculated.
// this can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
// B0 A0 are bits 24-39 and are the returned value
// C1 B1 A1 is longIn1
// D2 C2 B2 A2 is longIn2
//
# define MultiU24X32toH16(intRes, longIn1, longIn2) \
2015-03-14 12:28:22 +01:00
asm volatile ( \
2015-10-03 08:08:58 +02:00
" clr r26 \n \t " \
" mul %A1, %B2 \n \t " \
" mov r27, r1 \n \t " \
" mul %B1, %C2 \n \t " \
" movw %A0, r0 \n \t " \
" mul %C1, %C2 \n \t " \
" add %B0, r0 \n \t " \
" mul %C1, %B2 \n \t " \
" add %A0, r0 \n \t " \
" adc %B0, r1 \n \t " \
" mul %A1, %C2 \n \t " \
" add r27, r0 \n \t " \
" adc %A0, r1 \n \t " \
" adc %B0, r26 \n \t " \
" mul %B1, %B2 \n \t " \
" add r27, r0 \n \t " \
" adc %A0, r1 \n \t " \
" adc %B0, r26 \n \t " \
" mul %C1, %A2 \n \t " \
" add r27, r0 \n \t " \
" adc %A0, r1 \n \t " \
" adc %B0, r26 \n \t " \
" mul %B1, %A2 \n \t " \
" add r27, r1 \n \t " \
" adc %A0, r26 \n \t " \
" adc %B0, r26 \n \t " \
" lsr r27 \n \t " \
" adc %A0, r26 \n \t " \
" adc %B0, r26 \n \t " \
" mul %D2, %A1 \n \t " \
" add %A0, r0 \n \t " \
" adc %B0, r1 \n \t " \
" mul %D2, %B1 \n \t " \
" add %B0, r0 \n \t " \
" clr r1 \n \t " \
: \
" =&r " ( intRes ) \
: \
" d " ( longIn1 ) , \
" d " ( longIn2 ) \
: \
" r26 " , " r27 " \
)
2011-11-13 20:42:08 +01:00
// Some useful constants
2016-04-27 16:15:20 +02:00
/**
* __________________________
* / | | \ _________________ ^
* / | | \ / | | \ |
* / | | \ / | | \ s
* / | | | | | \ p
* / | | | | | \ e
* + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + - - - + - - + - - - - - - - - - - - - - - - + - - - - + e
* | BLOCK 1 | BLOCK 2 | d
*
* time - - - - - >
*
* The trapezoid is the shape the speed curve over time . It starts at block - > initial_rate , accelerates
* first block - > accelerate_until step_events_completed , then keeps going at constant speed until
* step_events_completed reaches block - > decelerate_after after which it decelerates until the trapezoid generator is reset .
* The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far .
*/
void Stepper : : wake_up ( ) {
2017-04-12 07:08:24 +02:00
// TCNT1 = 0;
2013-08-01 15:06:39 +02:00
ENABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
2011-11-13 20:42:08 +01:00
}
2015-06-16 02:36:41 +02:00
/**
* Set the stepper direction of each axis
*
2016-05-20 22:27:49 +02:00
* COREXY : X_AXIS = A_AXIS and Y_AXIS = B_AXIS
* COREXZ : X_AXIS = A_AXIS and Z_AXIS = C_AXIS
* COREYZ : Y_AXIS = B_AXIS and Z_AXIS = C_AXIS
2015-06-16 02:36:41 +02:00
*/
2016-04-27 16:15:20 +02:00
void Stepper : : set_directions ( ) {
2015-06-16 02:36:41 +02:00
2016-03-10 10:42:58 +01:00
# define SET_STEP_DIR(AXIS) \
2016-04-27 16:15:20 +02:00
if ( motor_direction ( AXIS # # _AXIS ) ) { \
2016-03-10 10:42:58 +01:00
AXIS # # _APPLY_DIR ( INVERT_ # # AXIS # # _DIR , false ) ; \
count_direction [ AXIS # # _AXIS ] = - 1 ; \
} \
else { \
AXIS # # _APPLY_DIR ( ! INVERT_ # # AXIS # # _DIR , false ) ; \
count_direction [ AXIS # # _AXIS ] = 1 ; \
}
2015-10-03 08:08:58 +02:00
2016-08-28 02:38:24 +02:00
# if HAS_X_DIR
SET_STEP_DIR ( X ) ; // A
# endif
# if HAS_Y_DIR
SET_STEP_DIR ( Y ) ; // B
# endif
# if HAS_Z_DIR
SET_STEP_DIR ( Z ) ; // C
# endif
2015-10-03 08:08:58 +02:00
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2016-10-01 11:51:45 +02:00
if ( motor_direction ( E_AXIS ) ) {
REV_E_DIR ( ) ;
count_direction [ E_AXIS ] = - 1 ;
}
else {
NORM_E_DIR ( ) ;
count_direction [ E_AXIS ] = 1 ;
}
2017-10-09 11:13:43 +02:00
# endif // !LIN_ADVANCE
2015-05-17 14:33:09 +02:00
}
2016-11-05 22:38:48 +01:00
# if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
extern volatile uint8_t e_hit ;
# endif
2016-10-09 17:06:31 +02:00
/**
* Stepper Driver Interrupt
*
* Directly pulses the stepper motors at high frequency .
* Timer 1 runs at a base frequency of 2 MHz , with this ISR using OCR1A compare mode .
*
* OCR1A Frequency
* 1 2 MHz
* 50 40 KHz
* 100 20 KHz - capped max rate
* 200 10 KHz - nominal max rate
* 2000 1 KHz - sleep rate
* 4000 500 Hz - init rate
*/
2016-12-12 20:30:02 +01:00
ISR ( TIMER1_COMPA_vect ) {
2017-10-09 11:13:43 +02:00
# if ENABLED(LIN_ADVANCE)
2016-12-12 20:30:02 +01:00
Stepper : : advance_isr_scheduler ( ) ;
# else
Stepper : : isr ( ) ;
# endif
}
2015-03-19 18:16:18 +01:00
2017-02-14 13:00:17 +01:00
# define _ENABLE_ISRs() do { cli(); if (thermalManager.in_temp_isr) CBI(TIMSK0, OCIE0B); else SBI(TIMSK0, OCIE0B); ENABLE_STEPPER_DRIVER_INTERRUPT(); } while(0)
2016-12-12 20:30:02 +01:00
2017-02-14 13:00:17 +01:00
void Stepper : : isr ( ) {
2017-01-22 01:10:02 +01:00
2017-02-14 13:00:17 +01:00
uint16_t ocr_val ;
2017-12-06 20:23:28 +01:00
# define ENDSTOP_NOMINAL_OCR_VAL 3000 // Check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
# define OCR_VAL_TOLERANCE 1000 // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
2017-01-22 01:10:02 +01:00
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2017-01-22 01:10:02 +01:00
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
CBI ( TIMSK0 , OCIE0B ) ; // Temperature ISR
2016-12-12 20:30:02 +01:00
DISABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
sei ( ) ;
2016-11-20 13:09:12 +01:00
# endif
2016-12-15 16:21:32 +01:00
2017-01-22 01:10:02 +01:00
# define _SPLIT(L) (ocr_val = (uint16_t)L)
# if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
2017-12-06 20:23:28 +01:00
2017-01-22 01:10:02 +01:00
# define SPLIT(L) _SPLIT(L)
2017-12-06 20:23:28 +01:00
# else // !ENDSTOP_INTERRUPTS_FEATURE : Sample endstops between stepping ISRs
2017-03-13 14:39:04 +01:00
static uint32_t step_remaining = 0 ;
2017-12-06 20:23:28 +01:00
2017-01-22 01:10:02 +01:00
# define SPLIT(L) do { \
_SPLIT ( L ) ; \
if ( ENDSTOPS_ENABLED & & L > ENDSTOP_NOMINAL_OCR_VAL ) { \
2017-04-13 13:20:23 +02:00
const uint16_t remainder = ( uint16_t ) L % ( ENDSTOP_NOMINAL_OCR_VAL ) ; \
2017-01-22 01:10:02 +01:00
ocr_val = ( remainder < OCR_VAL_TOLERANCE ) ? ENDSTOP_NOMINAL_OCR_VAL + remainder : ENDSTOP_NOMINAL_OCR_VAL ; \
step_remaining = ( uint16_t ) L - ocr_val ; \
} \
2017-06-15 22:15:11 +02:00
} while ( 0 )
2017-01-22 01:10:02 +01:00
if ( step_remaining & & ENDSTOPS_ENABLED ) { // Just check endstops - not yet time for a step
endstops . update ( ) ;
2017-02-14 13:00:17 +01:00
2017-12-06 20:23:28 +01:00
// Next ISR either for endstops or stepping
ocr_val = step_remaining < = ENDSTOP_NOMINAL_OCR_VAL ? step_remaining : ENDSTOP_NOMINAL_OCR_VAL ;
step_remaining - = ocr_val ;
2017-02-14 13:00:17 +01:00
_NEXT_ISR ( ocr_val ) ;
2017-01-22 01:10:02 +01:00
NOLESS ( OCR1A , TCNT1 + 16 ) ;
_ENABLE_ISRs ( ) ; // re-enable ISRs
return ;
}
2017-12-06 20:23:28 +01:00
# endif // !ENDSTOP_INTERRUPTS_FEATURE
//
// When cleaning, discard the current block and run fast
//
2015-07-20 00:20:12 +02:00
if ( cleaning_buffer_counter ) {
2017-12-08 05:38:40 +01:00
if ( cleaning_buffer_counter < 0 ) { // Count up for endstop hit
if ( current_block ) planner . discard_current_block ( ) ; // Discard the active block that led to the trigger
if ( ! planner . discard_continued_block ( ) ) // Discard next CONTINUED block
cleaning_buffer_counter = 0 ; // Keep discarding until non-CONTINUED
}
2017-12-06 20:23:28 +01:00
else {
2017-12-08 05:38:40 +01:00
planner . discard_current_block ( ) ;
- - cleaning_buffer_counter ; // Count down for abort print
2017-12-25 03:33:58 +01:00
# if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
if ( ! cleaning_buffer_counter ) enqueue_and_echo_commands_P ( PSTR ( SD_FINISHED_RELEASECOMMAND ) ) ;
2017-12-06 20:23:28 +01:00
# endif
}
2017-12-08 05:38:40 +01:00
current_block = NULL ; // Prep to get a new block after cleaning
2017-12-06 20:23:28 +01:00
_NEXT_ISR ( 200 ) ; // Run at max speed - 10 KHz
_ENABLE_ISRs ( ) ;
2015-03-19 18:16:18 +01:00
return ;
}
2015-04-24 08:03:17 +02:00
2011-11-13 20:42:08 +01:00
// If there is no current block, attempt to pop one from the buffer
2015-03-14 12:28:22 +01:00
if ( ! current_block ) {
2011-11-13 20:42:08 +01:00
// Anything in the buffer?
2017-12-02 06:21:02 +01:00
if ( ( current_block = planner . get_current_block ( ) ) ) {
2011-11-13 20:42:08 +01:00
trapezoid_generator_reset ( ) ;
2016-06-29 00:06:56 +02:00
// Initialize Bresenham counters to 1/2 the ceiling
counter_X = counter_Y = counter_Z = counter_E = - ( current_block - > step_event_count > > 1 ) ;
# if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP ( i )
2016-09-02 18:31:45 +02:00
counter_m [ i ] = - ( current_block - > mix_event_count [ i ] > > 1 ) ;
2016-06-29 00:06:56 +02:00
# endif
2013-08-01 15:06:39 +02:00
step_events_completed = 0 ;
2016-11-15 16:41:13 +01:00
# if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
e_hit = 2 ; // Needed for the case an endstop is already triggered before the new move begins.
// No 'change' can be detected.
# endif
2015-07-31 07:28:11 +02:00
# if ENABLED(Z_LATE_ENABLE)
2015-03-21 04:42:49 +01:00
if ( current_block - > steps [ Z_AXIS ] > 0 ) {
2017-04-11 18:10:26 +02:00
enable_Z ( ) ;
2016-12-12 20:30:02 +01:00
_NEXT_ISR ( 2000 ) ; // Run at slow speed - 1 KHz
_ENABLE_ISRs ( ) ; // re-enable ISRs
2012-02-06 17:38:16 +01:00
return ;
}
# endif
2013-08-01 15:06:39 +02:00
}
2011-11-13 20:42:08 +01:00
else {
2016-12-12 20:30:02 +01:00
_NEXT_ISR ( 2000 ) ; // Run at slow speed - 1 KHz
_ENABLE_ISRs ( ) ; // re-enable ISRs
2016-09-22 00:28:54 +02:00
return ;
2013-08-01 15:06:39 +02:00
}
}
2011-11-13 20:42:08 +01:00
2016-09-22 00:28:54 +02:00
// Update endstops state, if enabled
2017-01-22 01:10:02 +01:00
# if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
2017-03-06 08:43:08 +01:00
if ( e_hit & & ENDSTOPS_ENABLED ) {
2017-01-22 01:10:02 +01:00
endstops . update ( ) ;
2016-11-05 22:38:48 +01:00
e_hit - - ;
2017-01-22 01:10:02 +01:00
}
# else
if ( ENDSTOPS_ENABLED ) endstops . update ( ) ;
# endif
2015-04-24 08:03:17 +02:00
2016-09-22 00:28:54 +02:00
// Take multiple steps per interrupt (For high speed moves)
bool all_steps_done = false ;
2017-04-11 18:11:17 +02:00
for ( uint8_t i = step_loops ; i - - ; ) {
2016-09-22 00:28:54 +02:00
# if ENABLED(LIN_ADVANCE)
2012-12-09 10:32:09 +01:00
2016-09-22 00:28:54 +02:00
counter_E + = current_block - > steps [ E_AXIS ] ;
if ( counter_E > 0 ) {
counter_E - = current_block - > step_event_count ;
# if DISABLED(MIXING_EXTRUDER)
// Don't step E here for mixing extruder
count_position [ E_AXIS ] + = count_direction [ E_AXIS ] ;
motor_direction ( E_AXIS ) ? - - e_steps [ TOOL_E_INDEX ] : + + e_steps [ TOOL_E_INDEX ] ;
# endif
}
2016-05-04 21:10:42 +02:00
2016-09-22 00:28:54 +02:00
# if ENABLED(MIXING_EXTRUDER)
// Step mixing steppers proportionally
2016-10-08 18:13:04 +02:00
const bool dir = motor_direction ( E_AXIS ) ;
2016-09-22 00:28:54 +02:00
MIXING_STEPPERS_LOOP ( j ) {
counter_m [ j ] + = current_block - > steps [ E_AXIS ] ;
if ( counter_m [ j ] > 0 ) {
counter_m [ j ] - = current_block - > mix_event_count [ j ] ;
dir ? - - e_steps [ j ] : + + e_steps [ j ] ;
}
2016-05-04 18:53:17 +02:00
}
2016-09-22 00:28:54 +02:00
# endif
2016-05-04 21:10:42 +02:00
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2013-08-01 15:06:39 +02:00
2016-09-22 00:28:54 +02:00
# define _COUNTER(AXIS) counter_## AXIS
# define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP
# define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN
2016-08-28 06:38:05 +02:00
2016-09-22 00:28:54 +02:00
// Advance the Bresenham counter; start a pulse if the axis needs a step
# define PULSE_START(AXIS) \
_COUNTER ( AXIS ) + = current_block - > steps [ _AXIS ( AXIS ) ] ; \
if ( _COUNTER ( AXIS ) > 0 ) { _APPLY_STEP ( AXIS ) ( ! _INVERT_STEP_PIN ( AXIS ) , 0 ) ; }
2016-08-28 06:38:05 +02:00
2016-09-22 00:28:54 +02:00
// Stop an active pulse, reset the Bresenham counter, update the position
# define PULSE_STOP(AXIS) \
if ( _COUNTER ( AXIS ) > 0 ) { \
_COUNTER ( AXIS ) - = current_block - > step_event_count ; \
count_position [ _AXIS ( AXIS ) ] + = count_direction [ _AXIS ( AXIS ) ] ; \
_APPLY_STEP ( AXIS ) ( _INVERT_STEP_PIN ( AXIS ) , 0 ) ; \
}
2016-06-29 00:06:56 +02:00
2017-05-31 18:30:01 +02:00
/**
* Estimate the number of cycles that the stepper logic already takes
* up between the start and stop of the X stepper pulse .
*
* Currently this uses very modest estimates of around 5 cycles .
* True values may be derived by careful testing .
*
* Once any delay is added , the cost of the delay code itself
* may be subtracted from this value to get a more accurate delay .
* Delays under 20 cycles ( 1.25 µ s ) will be very accurate , using NOPs .
* Longer delays use a loop . The resolution is 8 cycles .
*/
2017-04-11 18:11:17 +02:00
# if HAS_X_STEP
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_1 5
2017-04-11 18:11:17 +02:00
# else
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_1 0
# endif
# if ENABLED(X_DUAL_STEPPER_DRIVERS)
# define _CYCLE_APPROX_2 _CYCLE_APPROX_1 + 4
# else
# define _CYCLE_APPROX_2 _CYCLE_APPROX_1
2017-04-11 18:11:17 +02:00
# endif
# if HAS_Y_STEP
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_3 _CYCLE_APPROX_2 + 5
2017-04-11 18:11:17 +02:00
# else
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_3 _CYCLE_APPROX_2
# endif
# if ENABLED(Y_DUAL_STEPPER_DRIVERS)
# define _CYCLE_APPROX_4 _CYCLE_APPROX_3 + 4
# else
# define _CYCLE_APPROX_4 _CYCLE_APPROX_3
2017-04-11 18:11:17 +02:00
# endif
# if HAS_Z_STEP
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_5 _CYCLE_APPROX_4 + 5
2017-04-11 18:11:17 +02:00
# else
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_5 _CYCLE_APPROX_4
# endif
# if ENABLED(Z_DUAL_STEPPER_DRIVERS)
# define _CYCLE_APPROX_6 _CYCLE_APPROX_5 + 4
# else
# define _CYCLE_APPROX_6 _CYCLE_APPROX_5
2017-04-11 18:11:17 +02:00
# endif
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2017-05-31 18:30:01 +02:00
# if ENABLED(MIXING_EXTRUDER)
# define _CYCLE_APPROX_7 _CYCLE_APPROX_6 + (MIXING_STEPPERS) * 6
# else
# define _CYCLE_APPROX_7 _CYCLE_APPROX_6 + 5
# endif
2017-04-11 18:11:17 +02:00
# else
2017-05-31 18:30:01 +02:00
# define _CYCLE_APPROX_7 _CYCLE_APPROX_6
2017-04-11 18:11:17 +02:00
# endif
2017-05-31 18:30:01 +02:00
# define CYCLES_EATEN_XYZE _CYCLE_APPROX_7
2017-04-11 18:11:17 +02:00
# define EXTRA_CYCLES_XYZE (STEP_PULSE_CYCLES - (CYCLES_EATEN_XYZE))
2016-09-24 06:59:16 +02:00
2017-05-31 18:30:01 +02:00
/**
* If a minimum pulse time was specified get the timer 0 value .
*
2017-06-04 18:30:03 +02:00
* TCNT0 has an 8 x prescaler , so it increments every 8 cycles .
2017-05-31 18:30:01 +02:00
* That ' s every 0.5 µ s on 16 MHz and every 0.4 µ s on 20 MHz .
* 20 counts of TCNT0 - by itself - is a good pulse delay .
* 10 µ s = 160 or 200 cycles .
*/
2017-04-11 18:11:17 +02:00
# if EXTRA_CYCLES_XYZE > 20
2017-03-24 06:50:05 +01:00
uint32_t pulse_start = TCNT0 ;
2016-09-22 00:28:54 +02:00
# endif
2015-03-14 12:28:22 +01:00
2016-09-22 00:28:54 +02:00
# if HAS_X_STEP
PULSE_START ( X ) ;
# endif
# if HAS_Y_STEP
PULSE_START ( Y ) ;
# endif
# if HAS_Z_STEP
PULSE_START ( Z ) ;
# endif
2015-03-07 07:14:34 +01:00
2016-09-22 00:28:54 +02:00
// For non-advance use linear interpolation for E also
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2016-09-22 00:28:54 +02:00
# if ENABLED(MIXING_EXTRUDER)
// Keep updating the single E axis
counter_E + = current_block - > steps [ E_AXIS ] ;
// Tick the counters used for this mix
MIXING_STEPPERS_LOOP ( j ) {
// Step mixing steppers (proportionally)
counter_m [ j ] + = current_block - > steps [ E_AXIS ] ;
// Step when the counter goes over zero
if ( counter_m [ j ] > 0 ) En_STEP_WRITE ( j , ! INVERT_E_STEP_PIN ) ;
}
# else // !MIXING_EXTRUDER
PULSE_START ( E ) ;
2016-08-28 02:38:24 +02:00
# endif
2017-10-09 11:13:43 +02:00
# endif // !LIN_ADVANCE
2016-06-29 00:06:56 +02:00
2017-04-11 18:11:17 +02:00
// For minimum pulse time wait before stopping pulses
# if EXTRA_CYCLES_XYZE > 20
while ( EXTRA_CYCLES_XYZE > ( uint32_t ) ( TCNT0 - pulse_start ) * ( INT0_PRESCALER ) ) { /* nada */ }
pulse_start = TCNT0 ;
# elif EXTRA_CYCLES_XYZE > 0
DELAY_NOPS ( EXTRA_CYCLES_XYZE ) ;
2016-05-08 21:16:26 +02:00
# endif
2016-09-22 00:28:54 +02:00
# if HAS_X_STEP
PULSE_STOP ( X ) ;
# endif
# if HAS_Y_STEP
PULSE_STOP ( Y ) ;
# endif
# if HAS_Z_STEP
PULSE_STOP ( Z ) ;
# endif
2013-08-01 15:06:39 +02:00
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2016-09-22 00:28:54 +02:00
# if ENABLED(MIXING_EXTRUDER)
// Always step the single E axis
if ( counter_E > 0 ) {
counter_E - = current_block - > step_event_count ;
count_position [ E_AXIS ] + = count_direction [ E_AXIS ] ;
}
MIXING_STEPPERS_LOOP ( j ) {
if ( counter_m [ j ] > 0 ) {
counter_m [ j ] - = current_block - > mix_event_count [ j ] ;
En_STEP_WRITE ( j , INVERT_E_STEP_PIN ) ;
}
}
# else // !MIXING_EXTRUDER
PULSE_STOP ( E ) ;
# endif
2017-10-09 11:13:43 +02:00
# endif // !LIN_ADVANCE
2013-08-01 15:06:39 +02:00
2016-09-22 00:28:54 +02:00
if ( + + step_events_completed > = current_block - > step_event_count ) {
all_steps_done = true ;
break ;
}
2017-04-11 18:11:17 +02:00
2017-05-31 18:30:01 +02:00
// For minimum pulse time wait after stopping pulses also
2017-04-11 18:11:17 +02:00
# if EXTRA_CYCLES_XYZE > 20
if ( i ) while ( EXTRA_CYCLES_XYZE > ( uint32_t ) ( TCNT0 - pulse_start ) * ( INT0_PRESCALER ) ) { /* nada */ }
# elif EXTRA_CYCLES_XYZE > 0
if ( i ) DELAY_NOPS ( EXTRA_CYCLES_XYZE ) ;
# endif
} // steps_loop
2011-11-13 20:42:08 +01:00
2016-10-08 18:13:04 +02:00
# if ENABLED(LIN_ADVANCE)
2017-10-09 11:13:43 +02:00
2016-10-08 18:13:04 +02:00
if ( current_block - > use_advance_lead ) {
2017-04-13 13:20:23 +02:00
const int delta_adv_steps = current_estep_rate [ TOOL_E_INDEX ] - current_adv_steps [ TOOL_E_INDEX ] ;
2016-10-08 18:13:04 +02:00
current_adv_steps [ TOOL_E_INDEX ] + = delta_adv_steps ;
# if ENABLED(MIXING_EXTRUDER)
// Mixing extruders apply advance lead proportionally
MIXING_STEPPERS_LOOP ( j )
e_steps [ j ] + = delta_adv_steps * current_block - > step_event_count / current_block - > mix_event_count [ j ] ;
# else
// For most extruders, advance the single E stepper
e_steps [ TOOL_E_INDEX ] + = delta_adv_steps ;
# endif
2017-10-09 11:13:43 +02:00
}
2016-09-22 00:28:54 +02:00
// If we have esteps to execute, fire the next advance_isr "now"
2016-12-12 20:30:02 +01:00
if ( e_steps [ TOOL_E_INDEX ] ) nextAdvanceISR = 0 ;
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2016-05-08 21:16:26 +02:00
2016-09-22 00:28:54 +02:00
// Calculate new timer value
if ( step_events_completed < = ( uint32_t ) current_block - > accelerate_until ) {
2016-05-04 21:10:42 +02:00
2017-12-17 08:54:17 +01:00
MultiU24X32toH16 ( acc_step_rate , acceleration_time , current_block - > acceleration_rate ) ;
acc_step_rate + = current_block - > initial_rate ;
2016-06-29 00:06:56 +02:00
2016-09-22 00:28:54 +02:00
// upper limit
NOMORE ( acc_step_rate , current_block - > nominal_rate ) ;
2015-10-03 08:08:58 +02:00
2016-09-22 00:28:54 +02:00
// step_rate to timer interval
2017-12-09 05:40:07 +01:00
const uint16_t interval = calc_timer_interval ( acc_step_rate ) ;
2017-01-22 01:10:02 +01:00
2017-12-13 09:15:21 +01:00
SPLIT ( interval ) ; // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
2017-01-22 01:10:02 +01:00
_NEXT_ISR ( ocr_val ) ;
2017-12-09 05:40:07 +01:00
acceleration_time + = interval ;
2015-10-03 08:08:58 +02:00
2016-09-22 00:28:54 +02:00
# if ENABLED(LIN_ADVANCE)
2015-12-10 14:05:38 +01:00
2016-09-22 00:28:54 +02:00
if ( current_block - > use_advance_lead ) {
2016-06-29 00:06:56 +02:00
# if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP ( j )
2016-10-31 16:17:30 +01:00
current_estep_rate [ j ] = ( ( uint32_t ) acc_step_rate * current_block - > abs_adv_steps_multiplier8 * current_block - > step_event_count / current_block - > mix_event_count [ j ] ) > > 17 ;
2016-06-29 00:06:56 +02:00
# else
2016-10-31 16:17:30 +01:00
current_estep_rate [ TOOL_E_INDEX ] = ( ( uint32_t ) acc_step_rate * current_block - > abs_adv_steps_multiplier8 ) > > 17 ;
2016-06-29 00:06:56 +02:00
# endif
2016-09-22 00:28:54 +02:00
}
2017-12-09 05:40:07 +01:00
eISR_Rate = adv_rate ( e_steps [ TOOL_E_INDEX ] , interval , step_loops ) ;
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2016-09-22 00:28:54 +02:00
}
2018-01-14 16:29:19 +01:00
else if ( step_events_completed > = ( uint32_t ) current_block - > decelerate_after & & current_block - > step_event_count ! = ( uint32_t ) current_block - > decelerate_after ) {
2016-11-18 06:42:41 +01:00
uint16_t step_rate ;
2018-01-14 16:29:19 +01:00
// If we are entering the deceleration phase for the first time, we have to see how long we have been decelerating up to now. Equals last acceleration time interval.
if ( ! deceleration_time )
deceleration_time = calc_timer_interval ( acc_step_rate ) ;
2016-09-22 00:28:54 +02:00
MultiU24X32toH16 ( step_rate , deceleration_time , current_block - > acceleration_rate ) ;
if ( step_rate < acc_step_rate ) { // Still decelerating?
step_rate = acc_step_rate - step_rate ;
NOLESS ( step_rate , current_block - > final_rate ) ;
}
else
step_rate = current_block - > final_rate ;
2016-05-04 21:10:42 +02:00
2016-09-22 00:28:54 +02:00
// step_rate to timer interval
2017-12-09 05:40:07 +01:00
const uint16_t interval = calc_timer_interval ( step_rate ) ;
2017-01-22 01:10:02 +01:00
2017-12-13 09:15:21 +01:00
SPLIT ( interval ) ; // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
2017-01-22 01:10:02 +01:00
_NEXT_ISR ( ocr_val ) ;
2017-12-09 05:40:07 +01:00
deceleration_time + = interval ;
2015-12-10 14:05:38 +01:00
2016-09-22 00:28:54 +02:00
# if ENABLED(LIN_ADVANCE)
2016-06-29 00:06:56 +02:00
2016-09-22 00:28:54 +02:00
if ( current_block - > use_advance_lead ) {
2016-06-29 00:06:56 +02:00
# if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP ( j )
2016-10-31 16:17:30 +01:00
current_estep_rate [ j ] = ( ( uint32_t ) step_rate * current_block - > abs_adv_steps_multiplier8 * current_block - > step_event_count / current_block - > mix_event_count [ j ] ) > > 17 ;
2016-06-29 00:06:56 +02:00
# else
2016-10-31 16:17:30 +01:00
current_estep_rate [ TOOL_E_INDEX ] = ( ( uint32_t ) step_rate * current_block - > abs_adv_steps_multiplier8 ) > > 17 ;
2016-06-29 00:06:56 +02:00
# endif
2016-09-22 00:28:54 +02:00
}
2017-12-09 05:40:07 +01:00
eISR_Rate = adv_rate ( e_steps [ TOOL_E_INDEX ] , interval , step_loops ) ;
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2016-09-22 00:28:54 +02:00
}
else {
2016-05-08 21:16:26 +02:00
2016-09-22 00:28:54 +02:00
# if ENABLED(LIN_ADVANCE)
2016-05-08 21:16:26 +02:00
2016-09-22 00:28:54 +02:00
if ( current_block - > use_advance_lead )
current_estep_rate [ TOOL_E_INDEX ] = final_estep_rate ;
2016-05-04 21:10:42 +02:00
2017-06-19 12:14:05 +02:00
eISR_Rate = adv_rate ( e_steps [ TOOL_E_INDEX ] , OCR1A_nominal , step_loops_nominal ) ;
2011-12-02 17:45:05 +01:00
2016-09-22 00:28:54 +02:00
# endif
2015-09-05 00:59:19 +02:00
2017-12-13 09:15:21 +01:00
SPLIT ( OCR1A_nominal ) ; // split step into multiple ISRs if larger than ENDSTOP_NOMINAL_OCR_VAL
2017-01-22 01:10:02 +01:00
_NEXT_ISR ( ocr_val ) ;
2016-09-22 00:28:54 +02:00
// ensure we're running at the correct step rate, even if we just came off an acceleration
step_loops = step_loops_nominal ;
}
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2016-12-12 20:30:02 +01:00
NOLESS ( OCR1A , TCNT1 + 16 ) ;
# endif
2016-09-22 00:28:54 +02:00
// If current block is finished, reset pointer
if ( all_steps_done ) {
current_block = NULL ;
planner . discard_current_block ( ) ;
2013-08-01 15:06:39 +02:00
}
2017-10-09 11:13:43 +02:00
# if DISABLED(LIN_ADVANCE)
2016-12-12 20:30:02 +01:00
_ENABLE_ISRs ( ) ; // re-enable ISRs
2016-11-20 13:09:12 +01:00
# endif
2011-11-13 20:42:08 +01:00
}
2017-10-09 11:13:43 +02:00
# if ENABLED(LIN_ADVANCE)
2016-05-04 21:10:42 +02:00
2017-04-11 18:11:17 +02:00
# define CYCLES_EATEN_E (E_STEPPERS * 5)
# define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E))
2011-11-13 20:42:08 +01:00
// Timer interrupt for E. e_steps is set in the main routine;
2016-04-27 16:15:20 +02:00
void Stepper : : advance_isr ( ) {
2017-01-22 01:10:02 +01:00
2016-12-12 20:30:02 +01:00
nextAdvanceISR = eISR_Rate ;
2017-01-22 01:10:02 +01:00
2017-06-02 20:57:31 +02:00
# if ENABLED(MK2_MULTIPLEXER)
// Even-numbered steppers are reversed
# define SET_E_STEP_DIR(INDEX) \
if ( e_steps [ INDEX ] ) E # # INDEX # # _DIR_WRITE ( e_steps [ INDEX ] < 0 ? ! INVERT_E # # INDEX # # _DIR ^ TEST ( INDEX , 0 ) : INVERT_E # # INDEX # # _DIR ^ TEST ( INDEX , 0 ) )
# else
# define SET_E_STEP_DIR(INDEX) \
if ( e_steps [ INDEX ] ) E # # INDEX # # _DIR_WRITE ( e_steps [ INDEX ] < 0 ? INVERT_E # # INDEX # # _DIR : ! INVERT_E # # INDEX # # _DIR )
# endif
2016-10-01 11:51:45 +02:00
2016-08-30 21:22:42 +02:00
# define START_E_PULSE(INDEX) \
2016-09-19 14:05:22 +02:00
if ( e_steps [ INDEX ] ) E # # INDEX # # _STEP_WRITE ( ! INVERT_E_STEP_PIN )
2016-08-30 21:22:42 +02:00
# define STOP_E_PULSE(INDEX) \
if ( e_steps [ INDEX ] ) { \
2016-10-01 11:51:45 +02:00
e_steps [ INDEX ] < 0 ? + + e_steps [ INDEX ] : - - e_steps [ INDEX ] ; \
2016-09-19 14:05:22 +02:00
E # # INDEX # # _STEP_WRITE ( INVERT_E_STEP_PIN ) ; \
2011-12-12 19:34:37 +01:00
}
2016-03-10 10:42:58 +01:00
2016-10-01 11:51:45 +02:00
SET_E_STEP_DIR ( 0 ) ;
# if E_STEPPERS > 1
SET_E_STEP_DIR ( 1 ) ;
# if E_STEPPERS > 2
SET_E_STEP_DIR ( 2 ) ;
# if E_STEPPERS > 3
SET_E_STEP_DIR ( 3 ) ;
2017-06-15 22:15:11 +02:00
# if E_STEPPERS > 4
SET_E_STEP_DIR ( 4 ) ;
# endif
2016-10-01 11:51:45 +02:00
# endif
# endif
# endif
2016-05-06 20:03:56 +02:00
// Step all E steppers that have steps
2017-04-11 18:11:17 +02:00
for ( uint8_t i = step_loops ; i - - ; ) {
2016-08-30 21:22:42 +02:00
2017-04-11 18:11:17 +02:00
# if EXTRA_CYCLES_E > 20
2017-03-24 06:50:05 +01:00
uint32_t pulse_start = TCNT0 ;
2016-08-30 21:22:58 +02:00
# endif
2016-08-30 21:22:42 +02:00
START_E_PULSE ( 0 ) ;
# if E_STEPPERS > 1
START_E_PULSE ( 1 ) ;
# if E_STEPPERS > 2
START_E_PULSE ( 2 ) ;
# if E_STEPPERS > 3
START_E_PULSE ( 3 ) ;
2017-06-15 22:15:11 +02:00
# if E_STEPPERS > 4
START_E_PULSE ( 4 ) ;
# endif
2016-08-30 21:22:42 +02:00
# endif
# endif
# endif
2017-04-11 18:11:17 +02:00
// For minimum pulse time wait before stopping pulses
# if EXTRA_CYCLES_E > 20
while ( EXTRA_CYCLES_E > ( uint32_t ) ( TCNT0 - pulse_start ) * ( INT0_PRESCALER ) ) { /* nada */ }
pulse_start = TCNT0 ;
# elif EXTRA_CYCLES_E > 0
DELAY_NOPS ( EXTRA_CYCLES_E ) ;
2016-08-30 21:22:58 +02:00
# endif
2016-08-30 21:22:42 +02:00
STOP_E_PULSE ( 0 ) ;
2016-06-29 00:06:56 +02:00
# if E_STEPPERS > 1
2016-08-30 21:22:42 +02:00
STOP_E_PULSE ( 1 ) ;
2016-06-29 00:06:56 +02:00
# if E_STEPPERS > 2
2016-08-30 21:22:42 +02:00
STOP_E_PULSE ( 2 ) ;
2016-06-29 00:06:56 +02:00
# if E_STEPPERS > 3
2016-08-30 21:22:42 +02:00
STOP_E_PULSE ( 3 ) ;
2017-06-15 22:15:11 +02:00
# if E_STEPPERS > 4
STOP_E_PULSE ( 4 ) ;
# endif
2016-06-22 18:32:01 +02:00
# endif
2016-03-10 10:42:58 +01:00
# endif
2015-10-03 08:08:58 +02:00
# endif
2016-04-27 16:15:20 +02:00
2017-04-11 18:11:17 +02:00
// For minimum pulse time wait before looping
# if EXTRA_CYCLES_E > 20
if ( i ) while ( EXTRA_CYCLES_E > ( uint32_t ) ( TCNT0 - pulse_start ) * ( INT0_PRESCALER ) ) { /* nada */ }
# elif EXTRA_CYCLES_E > 0
if ( i ) DELAY_NOPS ( EXTRA_CYCLES_E ) ;
# endif
} // steps_loop
2016-05-04 18:53:17 +02:00
}
2016-12-12 20:30:02 +01:00
void Stepper : : advance_isr_scheduler ( ) {
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
CBI ( TIMSK0 , OCIE0B ) ; // Temperature ISR
DISABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
sei ( ) ;
// Run main stepping ISR if flagged
if ( ! nextMainISR ) isr ( ) ;
// Run Advance stepping ISR if flagged
if ( ! nextAdvanceISR ) advance_isr ( ) ;
2017-01-22 01:10:02 +01:00
2016-12-12 20:30:02 +01:00
// Is the next advance ISR scheduled before the next main ISR?
if ( nextAdvanceISR < = nextMainISR ) {
// Set up the next interrupt
OCR1A = nextAdvanceISR ;
// New interval for the next main ISR
if ( nextMainISR ) nextMainISR - = nextAdvanceISR ;
// Will call Stepper::advance_isr on the next interrupt
nextAdvanceISR = 0 ;
}
else {
// The next main ISR comes first
OCR1A = nextMainISR ;
// New interval for the next advance ISR, if any
2016-12-24 03:43:23 +01:00
if ( nextAdvanceISR & & nextAdvanceISR ! = ADV_NEVER )
2016-12-12 20:30:02 +01:00
nextAdvanceISR - = nextMainISR ;
// Will call Stepper::isr on the next interrupt
nextMainISR = 0 ;
}
2017-01-22 01:10:02 +01:00
2016-12-12 20:30:02 +01:00
// Don't run the ISR faster than possible
NOLESS ( OCR1A , TCNT1 + 16 ) ;
// Restore original ISR settings
2017-02-14 13:00:17 +01:00
_ENABLE_ISRs ( ) ;
2016-12-12 20:30:02 +01:00
}
2017-10-09 11:13:43 +02:00
# endif // LIN_ADVANCE
2016-05-04 18:53:17 +02:00
2016-04-27 16:15:20 +02:00
void Stepper : : init ( ) {
2016-05-12 00:24:24 +02:00
2016-09-25 13:32:58 +02:00
// Init Digipot Motor Current
# if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
digipot_init ( ) ;
# endif
2013-08-01 15:06:39 +02:00
2016-09-25 13:32:58 +02:00
// Init Microstepping Pins
# if HAS_MICROSTEPS
microstep_init ( ) ;
# endif
// Init TMC Steppers
2015-07-31 07:28:11 +02:00
# if ENABLED(HAVE_TMCDRIVER)
2015-03-14 12:28:22 +01:00
tmc_init ( ) ;
2015-02-23 17:45:29 +01:00
# endif
2016-09-25 13:32:58 +02:00
2016-09-14 08:48:47 +02:00
// Init TMC2130 Steppers
2017-03-07 06:00:43 +01:00
# if ENABLED(HAVE_TMC2130)
2016-09-14 08:48:47 +02:00
tmc2130_init ( ) ;
# endif
2017-12-15 22:02:39 +01:00
// Init TMC2208 Steppers
# if ENABLED(HAVE_TMC2208)
tmc2208_init ( ) ;
# endif
// TRAMS, TMC2130 and TMC2208 advanced settings
# if HAS_TRINAMIC
TMC_ADV ( )
# endif
2016-09-25 13:32:58 +02:00
// Init L6470 Steppers
2015-07-31 07:28:11 +02:00
# if ENABLED(HAVE_L6470DRIVER)
2015-03-14 12:28:22 +01:00
L6470_init ( ) ;
2015-02-27 12:43:23 +01:00
# endif
2015-04-24 08:03:17 +02:00
2016-09-25 13:32:58 +02:00
// Init Dir Pins
2015-04-04 00:31:35 +02:00
# if HAS_X_DIR
2015-02-23 16:12:35 +01:00
X_DIR_INIT ;
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_X2_DIR
2015-02-23 16:12:35 +01:00
X2_DIR_INIT ;
2013-07-17 14:44:45 +02:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_Y_DIR
2015-02-23 16:12:35 +01:00
Y_DIR_INIT ;
2015-07-31 07:28:11 +02:00
# if ENABLED(Y_DUAL_STEPPER_DRIVERS) && HAS_Y2_DIR
2015-03-14 12:28:22 +01:00
Y2_DIR_INIT ;
# endif
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_Z_DIR
2015-02-23 16:12:35 +01:00
Z_DIR_INIT ;
2015-07-31 07:28:11 +02:00
# if ENABLED(Z_DUAL_STEPPER_DRIVERS) && HAS_Z2_DIR
2015-02-23 16:12:35 +01:00
Z2_DIR_INIT ;
2012-08-04 08:32:26 +02:00
# endif
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E0_DIR
2015-02-23 16:12:35 +01:00
E0_DIR_INIT ;
2011-12-06 05:33:33 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E1_DIR
2015-02-23 16:12:35 +01:00
E1_DIR_INIT ;
2011-12-06 05:33:33 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E2_DIR
2015-02-23 16:12:35 +01:00
E2_DIR_INIT ;
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E3_DIR
2015-02-23 16:12:35 +01:00
E3_DIR_INIT ;
2015-01-23 23:13:06 +01:00
# endif
2017-04-09 10:23:05 +02:00
# if HAS_E4_DIR
E4_DIR_INIT ;
# endif
2011-11-13 20:42:08 +01:00
2016-09-25 13:32:58 +02:00
// Init Enable Pins - steppers default to disabled.
2015-04-04 00:31:35 +02:00
# if HAS_X_ENABLE
2015-02-23 16:12:35 +01:00
X_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! X_ENABLE_ON ) X_ENABLE_WRITE ( HIGH ) ;
2016-05-17 23:56:49 +02:00
# if ENABLED(DUAL_X_CARRIAGE) && HAS_X2_ENABLE
X2_ENABLE_INIT ;
if ( ! X_ENABLE_ON ) X2_ENABLE_WRITE ( HIGH ) ;
# endif
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_Y_ENABLE
2015-02-23 16:12:35 +01:00
Y_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! Y_ENABLE_ON ) Y_ENABLE_WRITE ( HIGH ) ;
2016-05-17 23:56:49 +02:00
# if ENABLED(Y_DUAL_STEPPER_DRIVERS) && HAS_Y2_ENABLE
Y2_ENABLE_INIT ;
if ( ! Y_ENABLE_ON ) Y2_ENABLE_WRITE ( HIGH ) ;
# endif
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_Z_ENABLE
2015-02-23 16:12:35 +01:00
Z_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! Z_ENABLE_ON ) Z_ENABLE_WRITE ( HIGH ) ;
2015-07-31 07:28:11 +02:00
# if ENABLED(Z_DUAL_STEPPER_DRIVERS) && HAS_Z2_ENABLE
2015-02-23 16:12:35 +01:00
Z2_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! Z_ENABLE_ON ) Z2_ENABLE_WRITE ( HIGH ) ;
2012-08-04 08:32:26 +02:00
# endif
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E0_ENABLE
2015-02-23 16:12:35 +01:00
E0_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! E_ENABLE_ON ) E0_ENABLE_WRITE ( HIGH ) ;
2011-12-06 05:33:33 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E1_ENABLE
2015-02-23 16:12:35 +01:00
E1_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! E_ENABLE_ON ) E1_ENABLE_WRITE ( HIGH ) ;
2011-12-06 05:33:33 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E2_ENABLE
2015-02-23 16:12:35 +01:00
E2_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! E_ENABLE_ON ) E2_ENABLE_WRITE ( HIGH ) ;
2011-11-13 20:42:08 +01:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E3_ENABLE
2015-02-23 16:12:35 +01:00
E3_ENABLE_INIT ;
2015-03-14 12:28:22 +01:00
if ( ! E_ENABLE_ON ) E3_ENABLE_WRITE ( HIGH ) ;
2015-01-23 23:13:06 +01:00
# endif
2017-04-09 10:23:05 +02:00
# if HAS_E4_ENABLE
E4_ENABLE_INIT ;
if ( ! E_ENABLE_ON ) E4_ENABLE_WRITE ( HIGH ) ;
# endif
2011-11-13 20:42:08 +01:00
2016-09-25 13:32:58 +02:00
// Init endstops and pullups
2016-04-27 16:15:20 +02:00
endstops . init ( ) ;
2015-03-28 10:31:51 +01:00
2015-04-24 08:03:17 +02:00
# define _STEP_INIT(AXIS) AXIS ##_STEP_INIT
2015-05-07 18:55:47 +02:00
# define _WRITE_STEP(AXIS, HIGHLOW) AXIS ##_STEP_WRITE(HIGHLOW)
2017-04-11 18:10:26 +02:00
# define _DISABLE(AXIS) disable_## AXIS()
2015-04-24 08:03:17 +02:00
2017-04-11 18:10:26 +02:00
# define AXIS_INIT(AXIS, PIN) \
2015-04-24 08:03:17 +02:00
_STEP_INIT ( AXIS ) ; \
_WRITE_STEP ( AXIS , _INVERT_STEP_PIN ( PIN ) ) ; \
2017-04-11 18:10:26 +02:00
_DISABLE ( AXIS )
2011-11-13 20:42:08 +01:00
2017-04-11 18:10:26 +02:00
# define E_AXIS_INIT(NUM) AXIS_INIT(E## NUM, E)
2015-03-14 12:28:22 +01:00
2016-09-25 13:32:58 +02:00
// Init Step Pins
2015-04-04 00:31:35 +02:00
# if HAS_X_STEP
2016-07-11 19:19:07 +02:00
# if ENABLED(X_DUAL_STEPPER_DRIVERS) || ENABLED(DUAL_X_CARRIAGE)
X2_STEP_INIT ;
X2_STEP_WRITE ( INVERT_X_STEP_PIN ) ;
2016-05-17 23:56:49 +02:00
# endif
2017-04-11 18:10:26 +02:00
AXIS_INIT ( X , X ) ;
2013-08-01 15:06:39 +02:00
# endif
2016-05-17 23:56:49 +02:00
2015-04-04 00:31:35 +02:00
# if HAS_Y_STEP
2016-07-11 19:19:07 +02:00
# if ENABLED(Y_DUAL_STEPPER_DRIVERS)
2015-02-23 16:12:35 +01:00
Y2_STEP_INIT ;
Y2_STEP_WRITE ( INVERT_Y_STEP_PIN ) ;
2013-09-17 20:19:20 +02:00
# endif
2017-04-11 18:10:26 +02:00
AXIS_INIT ( Y , Y ) ;
2013-08-01 15:06:39 +02:00
# endif
2016-05-17 23:56:49 +02:00
2015-04-04 00:31:35 +02:00
# if HAS_Z_STEP
2016-07-11 19:19:07 +02:00
# if ENABLED(Z_DUAL_STEPPER_DRIVERS)
2015-02-23 16:12:35 +01:00
Z2_STEP_INIT ;
Z2_STEP_WRITE ( INVERT_Z_STEP_PIN ) ;
2012-08-04 08:32:26 +02:00
# endif
2017-04-11 18:10:26 +02:00
AXIS_INIT ( Z , Z ) ;
2013-08-01 15:06:39 +02:00
# endif
2016-05-17 23:56:49 +02:00
2015-04-04 00:31:35 +02:00
# if HAS_E0_STEP
2015-03-14 12:28:22 +01:00
E_AXIS_INIT ( 0 ) ;
2013-08-01 15:06:39 +02:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E1_STEP
2015-03-14 12:28:22 +01:00
E_AXIS_INIT ( 1 ) ;
2013-08-01 15:06:39 +02:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E2_STEP
2015-03-14 12:28:22 +01:00
E_AXIS_INIT ( 2 ) ;
2013-08-01 15:06:39 +02:00
# endif
2015-04-04 00:31:35 +02:00
# if HAS_E3_STEP
2015-03-14 12:28:22 +01:00
E_AXIS_INIT ( 3 ) ;
2015-01-23 23:13:06 +01:00
# endif
2017-04-15 00:14:14 +02:00
# if HAS_E4_STEP
E_AXIS_INIT ( 4 ) ;
# endif
2011-11-13 20:42:08 +01:00
// waveform generation = 0100 = CTC
2017-04-24 21:04:46 +02:00
SET_WGM ( 1 , CTC_OCRnA ) ;
2011-11-13 20:42:08 +01:00
// output mode = 00 (disconnected)
2017-04-26 06:14:16 +02:00
SET_COMA ( 1 , NORMAL ) ;
2016-10-09 17:06:31 +02:00
2012-03-07 23:58:35 +01:00
// Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py
2017-04-24 21:04:46 +02:00
SET_CS ( 1 , PRESCALER_8 ) ; // CS 2 = 1/8 prescaler
2011-11-13 20:42:08 +01:00
2016-10-09 17:06:31 +02:00
// Init Stepper ISR to 122 Hz for quick starting
2011-11-13 20:42:08 +01:00
OCR1A = 0x4000 ;
2011-11-18 18:59:17 +01:00
TCNT1 = 0 ;
2013-08-01 15:06:39 +02:00
ENABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
2016-05-04 21:10:42 +02:00
2017-10-09 11:13:43 +02:00
# if ENABLED(LIN_ADVANCE)
2017-05-01 05:24:03 +02:00
for ( uint8_t i = 0 ; i < COUNT ( e_steps ) ; i + + ) e_steps [ i ] = 0 ;
2017-10-09 11:13:43 +02:00
ZERO ( current_adv_steps ) ;
# endif
2013-08-01 15:06:39 +02:00
2016-04-27 16:15:20 +02:00
endstops . enable ( true ) ; // Start with endstops active. After homing they can be disabled
2011-11-13 20:42:08 +01:00
sei ( ) ;
2015-10-03 08:08:58 +02:00
2016-04-27 16:15:20 +02:00
set_directions ( ) ; // Init directions to last_direction_bits = 0
2011-11-13 20:42:08 +01:00
}
2011-12-09 12:32:31 +01:00
2015-05-27 05:08:21 +02:00
/**
2017-12-08 05:38:40 +01:00
* Block until all buffered steps are executed / cleaned
2015-05-27 05:08:21 +02:00
*/
2017-12-08 05:38:40 +01:00
void Stepper : : synchronize ( ) { while ( planner . blocks_queued ( ) | | cleaning_buffer_counter ) idle ( ) ; }
2011-11-20 14:50:08 +01:00
2016-04-11 10:03:50 +02:00
/**
* Set the stepper positions directly in steps
*
* The input is based on the typical per - axis XYZ steps .
* For CORE machines XYZ needs to be translated to ABC .
*
2016-04-27 16:15:20 +02:00
* This allows get_axis_position_mm to correctly
2016-04-11 10:03:50 +02:00
* derive the current XYZ position later on .
*/
2016-10-09 20:25:25 +02:00
void Stepper : : set_position ( const long & a , const long & b , const long & c , const long & e ) {
2016-09-22 00:37:05 +02:00
synchronize ( ) ; // Bad to set stepper counts in the middle of a move
2011-11-20 14:50:08 +01:00
CRITICAL_SECTION_START ;
2016-04-11 10:03:50 +02:00
2016-11-06 05:47:38 +01:00
# if CORE_IS_XY
2016-04-11 10:03:50 +02:00
// corexy positioning
// these equations follow the form of the dA and dB equations on http://www.corexy.com/theory.html
2016-10-09 20:25:25 +02:00
count_position [ A_AXIS ] = a + b ;
2016-11-06 05:47:38 +01:00
count_position [ B_AXIS ] = CORESIGN ( a - b ) ;
2016-10-09 20:25:25 +02:00
count_position [ Z_AXIS ] = c ;
2016-11-06 05:47:38 +01:00
# elif CORE_IS_XZ
2016-04-11 10:03:50 +02:00
// corexz planning
2016-10-09 20:25:25 +02:00
count_position [ A_AXIS ] = a + c ;
count_position [ Y_AXIS ] = b ;
2016-11-06 05:47:38 +01:00
count_position [ C_AXIS ] = CORESIGN ( a - c ) ;
# elif CORE_IS_YZ
2016-05-20 22:27:49 +02:00
// coreyz planning
2016-10-09 20:25:25 +02:00
count_position [ X_AXIS ] = a ;
2016-11-03 22:41:55 +01:00
count_position [ B_AXIS ] = b + c ;
2016-11-06 05:47:38 +01:00
count_position [ C_AXIS ] = CORESIGN ( b - c ) ;
2016-04-11 10:03:50 +02:00
# else
// default non-h-bot planning
2016-10-09 20:25:25 +02:00
count_position [ X_AXIS ] = a ;
count_position [ Y_AXIS ] = b ;
count_position [ Z_AXIS ] = c ;
2016-04-11 10:03:50 +02:00
# endif
2011-11-20 14:50:08 +01:00
count_position [ E_AXIS ] = e ;
CRITICAL_SECTION_END ;
}
2016-10-09 20:25:25 +02:00
void Stepper : : set_position ( const AxisEnum & axis , const long & v ) {
2016-09-28 21:01:29 +02:00
CRITICAL_SECTION_START ;
count_position [ axis ] = v ;
CRITICAL_SECTION_END ;
}
2016-10-09 20:25:25 +02:00
void Stepper : : set_e_position ( const long & e ) {
2011-11-25 13:43:06 +01:00
CRITICAL_SECTION_START ;
count_position [ E_AXIS ] = e ;
CRITICAL_SECTION_END ;
}
2016-04-11 10:03:10 +02:00
/**
* Get a stepper ' s position in steps .
*/
2017-12-09 13:43:38 +01:00
long Stepper : : position ( const AxisEnum axis ) {
2011-11-20 14:50:08 +01:00
CRITICAL_SECTION_START ;
2017-04-13 13:20:23 +02:00
const long count_pos = count_position [ axis ] ;
2011-11-20 14:50:08 +01:00
CRITICAL_SECTION_END ;
return count_pos ;
}
2011-11-26 11:50:23 +01:00
2016-04-11 10:03:10 +02:00
/**
* Get an axis position according to stepper position ( s )
* For CORE machines apply translation from ABC to XYZ .
*/
2017-12-09 13:43:38 +01:00
float Stepper : : get_axis_position_mm ( const AxisEnum axis ) {
2016-04-11 10:03:10 +02:00
float axis_steps ;
2016-11-06 05:47:38 +01:00
# if IS_CORE
2016-05-20 22:27:49 +02:00
// Requesting one of the "core" axes?
if ( axis = = CORE_AXIS_1 | | axis = = CORE_AXIS_2 ) {
2016-02-12 03:17:17 +01:00
CRITICAL_SECTION_START ;
// ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1
// ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2
2016-11-06 05:47:38 +01:00
axis_steps = 0.5f * (
axis = = CORE_AXIS_2 ? CORESIGN ( count_position [ CORE_AXIS_1 ] - count_position [ CORE_AXIS_2 ] )
: count_position [ CORE_AXIS_1 ] + count_position [ CORE_AXIS_2 ]
) ;
CRITICAL_SECTION_END ;
2016-02-12 03:17:17 +01:00
}
else
2016-04-27 16:15:20 +02:00
axis_steps = position ( axis ) ;
2016-02-12 03:17:17 +01:00
# else
2016-04-27 16:15:20 +02:00
axis_steps = position ( axis ) ;
2016-02-12 03:17:17 +01:00
# endif
2016-07-24 04:36:26 +02:00
return axis_steps * planner . steps_to_mm [ axis ] ;
2016-02-12 03:17:17 +01:00
}
2013-09-29 18:20:06 +02:00
2016-04-27 16:15:20 +02:00
void Stepper : : finish_and_disable ( ) {
synchronize ( ) ;
2015-04-04 04:25:22 +02:00
disable_all_steppers ( ) ;
2011-11-26 11:50:23 +01:00
}
2011-12-11 22:10:06 +01:00
2016-04-27 16:15:20 +02:00
void Stepper : : quick_stop ( ) {
2017-12-06 23:19:11 +01:00
cleaning_buffer_counter = 5000 ;
2011-12-11 22:10:06 +01:00
DISABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
2016-04-28 03:06:32 +02:00
while ( planner . blocks_queued ( ) ) planner . discard_current_block ( ) ;
2012-03-03 20:40:46 +01:00
current_block = NULL ;
2011-12-11 22:10:06 +01:00
ENABLE_STEPPER_DRIVER_INTERRUPT ( ) ;
2016-12-12 14:35:02 +01:00
# if ENABLED(ULTRA_LCD)
planner . clear_block_buffer_runtime ( ) ;
# endif
2011-12-11 22:10:06 +01:00
}
2016-04-27 16:15:20 +02:00
void Stepper : : endstop_triggered ( AxisEnum axis ) {
2016-11-06 05:47:38 +01:00
# if IS_CORE
2016-04-27 16:15:20 +02:00
2016-11-06 05:47:38 +01:00
endstops_trigsteps [ axis ] = 0.5f * (
axis = = CORE_AXIS_2 ? CORESIGN ( count_position [ CORE_AXIS_1 ] - count_position [ CORE_AXIS_2 ] )
: count_position [ CORE_AXIS_1 ] + count_position [ CORE_AXIS_2 ]
) ;
2016-04-27 16:15:20 +02:00
2016-05-20 22:27:49 +02:00
# else // !COREXY && !COREXZ && !COREYZ
2016-04-27 16:15:20 +02:00
endstops_trigsteps [ axis ] = count_position [ axis ] ;
2016-05-20 22:27:49 +02:00
# endif // !COREXY && !COREXZ && !COREYZ
2016-04-27 16:15:20 +02:00
kill_current_block ( ) ;
2017-12-08 05:38:40 +01:00
cleaning_buffer_counter = - 1 ; // Discard the rest of the move
2016-04-27 16:15:20 +02:00
}
void Stepper : : report_positions ( ) {
CRITICAL_SECTION_START ;
2017-04-13 13:20:23 +02:00
const long xpos = count_position [ X_AXIS ] ,
ypos = count_position [ Y_AXIS ] ,
zpos = count_position [ Z_AXIS ] ;
2016-04-27 16:15:20 +02:00
CRITICAL_SECTION_END ;
2016-11-06 05:47:38 +01:00
# if CORE_IS_XY || CORE_IS_XZ || IS_SCARA
2016-04-27 16:15:20 +02:00
SERIAL_PROTOCOLPGM ( MSG_COUNT_A ) ;
# else
SERIAL_PROTOCOLPGM ( MSG_COUNT_X ) ;
# endif
SERIAL_PROTOCOL ( xpos ) ;
2016-11-06 05:47:38 +01:00
# if CORE_IS_XY || CORE_IS_YZ || IS_SCARA
2016-04-27 16:15:20 +02:00
SERIAL_PROTOCOLPGM ( " B: " ) ;
# else
SERIAL_PROTOCOLPGM ( " Y: " ) ;
# endif
SERIAL_PROTOCOL ( ypos ) ;
2016-11-06 05:47:38 +01:00
# if CORE_IS_XZ || CORE_IS_YZ
2016-04-27 16:15:20 +02:00
SERIAL_PROTOCOLPGM ( " C: " ) ;
# else
SERIAL_PROTOCOLPGM ( " Z: " ) ;
# endif
SERIAL_PROTOCOL ( zpos ) ;
2017-06-09 17:51:23 +02:00
SERIAL_EOL ( ) ;
2016-04-27 16:15:20 +02:00
}
2015-07-31 07:28:11 +02:00
# if ENABLED(BABYSTEPPING)
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2017-04-11 18:11:17 +02:00
# if ENABLED(DELTA)
# define CYCLES_EATEN_BABYSTEP (2 * 15)
# else
# define CYCLES_EATEN_BABYSTEP 0
# endif
# define EXTRA_CYCLES_BABYSTEP (STEP_PULSE_CYCLES - (CYCLES_EATEN_BABYSTEP))
2017-03-24 06:50:05 +01:00
2017-04-11 18:10:26 +02:00
# define _ENABLE(AXIS) enable_## AXIS()
2016-11-03 22:42:44 +01:00
# define _READ_DIR(AXIS) AXIS ##_DIR_READ
# define _INVERT_DIR(AXIS) INVERT_## AXIS ##_DIR
# define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true)
2017-04-11 18:11:17 +02:00
# if EXTRA_CYCLES_BABYSTEP > 20
2017-04-13 13:20:23 +02:00
# define _SAVE_START const uint32_t pulse_start = TCNT0
2017-04-11 18:11:17 +02:00
# define _PULSE_WAIT while (EXTRA_CYCLES_BABYSTEP > (uint32_t)(TCNT0 - pulse_start) * (INT0_PRESCALER)) { /* nada */ }
2017-03-24 06:50:05 +01:00
# else
# define _SAVE_START NOOP
2017-04-11 18:11:17 +02:00
# if EXTRA_CYCLES_BABYSTEP > 0
# define _PULSE_WAIT DELAY_NOPS(EXTRA_CYCLES_BABYSTEP)
# elif STEP_PULSE_CYCLES > 0
# define _PULSE_WAIT NOOP
# elif ENABLED(DELTA)
# define _PULSE_WAIT delayMicroseconds(2);
# else
# define _PULSE_WAIT delayMicroseconds(4);
# endif
2017-03-24 06:50:05 +01:00
# endif
2017-04-11 18:11:17 +02:00
# define BABYSTEP_AXIS(AXIS, INVERT) { \
const uint8_t old_dir = _READ_DIR ( AXIS ) ; \
_ENABLE ( AXIS ) ; \
_SAVE_START ; \
2016-11-03 22:42:44 +01:00
_APPLY_DIR ( AXIS , _INVERT_DIR ( AXIS ) ^ direction ^ INVERT ) ; \
2017-04-11 18:11:17 +02:00
_APPLY_STEP ( AXIS ) ( ! _INVERT_STEP_PIN ( AXIS ) , true ) ; \
_PULSE_WAIT ; \
_APPLY_STEP ( AXIS ) ( _INVERT_STEP_PIN ( AXIS ) , true ) ; \
_APPLY_DIR ( AXIS , old_dir ) ; \
2016-11-03 22:42:44 +01:00
}
2015-03-14 12:28:22 +01:00
// MUST ONLY BE CALLED BY AN ISR,
// No other ISR should ever interrupt this!
2016-11-04 00:23:31 +01:00
void Stepper : : babystep ( const AxisEnum axis , const bool direction ) {
2017-03-21 18:05:44 +01:00
cli ( ) ;
2017-04-11 18:11:17 +02:00
2015-10-03 08:08:58 +02:00
switch ( axis ) {
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2017-04-11 18:11:17 +02:00
# if ENABLED(BABYSTEP_XY)
case X_AXIS :
BABYSTEP_AXIS ( X , false ) ;
break ;
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2017-04-11 18:11:17 +02:00
case Y_AXIS :
BABYSTEP_AXIS ( Y , false ) ;
break ;
# endif
2015-10-03 08:08:58 +02:00
2015-03-14 12:28:22 +01:00
case Z_AXIS : {
2015-01-23 12:24:45 +01:00
2015-07-31 07:28:11 +02:00
# if DISABLED(DELTA)
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2017-04-11 18:11:17 +02:00
BABYSTEP_AXIS ( Z , BABYSTEP_INVERT_Z ) ;
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2015-03-14 12:28:22 +01:00
# else // DELTA
2015-01-23 12:24:45 +01:00
2017-04-13 13:20:23 +02:00
const bool z_direction = direction ^ BABYSTEP_INVERT_Z ;
2015-01-23 12:24:45 +01:00
2017-04-11 18:10:26 +02:00
enable_X ( ) ;
enable_Y ( ) ;
enable_Z ( ) ;
2017-04-13 13:20:23 +02:00
const uint8_t old_x_dir_pin = X_DIR_READ ,
old_y_dir_pin = Y_DIR_READ ,
old_z_dir_pin = Z_DIR_READ ;
2017-04-11 18:11:17 +02:00
2015-10-03 08:08:58 +02:00
X_DIR_WRITE ( INVERT_X_DIR ^ z_direction ) ;
Y_DIR_WRITE ( INVERT_Y_DIR ^ z_direction ) ;
Z_DIR_WRITE ( INVERT_Z_DIR ^ z_direction ) ;
2017-04-11 18:11:17 +02:00
_SAVE_START ;
2015-03-14 12:28:22 +01:00
X_STEP_WRITE ( ! INVERT_X_STEP_PIN ) ;
Y_STEP_WRITE ( ! INVERT_Y_STEP_PIN ) ;
Z_STEP_WRITE ( ! INVERT_Z_STEP_PIN ) ;
2017-04-11 18:11:17 +02:00
_PULSE_WAIT ;
2015-10-03 08:08:58 +02:00
X_STEP_WRITE ( INVERT_X_STEP_PIN ) ;
Y_STEP_WRITE ( INVERT_Y_STEP_PIN ) ;
2015-03-14 12:28:22 +01:00
Z_STEP_WRITE ( INVERT_Z_STEP_PIN ) ;
2017-04-11 18:11:17 +02:00
// Restore direction bits
2015-03-14 12:28:22 +01:00
X_DIR_WRITE ( old_x_dir_pin ) ;
Y_DIR_WRITE ( old_y_dir_pin ) ;
Z_DIR_WRITE ( old_z_dir_pin ) ;
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2015-03-14 12:28:22 +01:00
# endif
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2015-03-14 12:28:22 +01:00
} break ;
2015-10-03 08:08:58 +02:00
2015-03-14 12:28:22 +01:00
default : break ;
}
2017-03-21 18:05:44 +01:00
sei ( ) ;
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
}
2013-10-07 09:14:04 +02:00
2017-03-24 06:50:05 +01:00
# endif // BABYSTEPPING
Add the socalled "Babystepping" feature.
It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *
It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.
Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.
say goodby to fuddling around with the z-axis.
2013-10-06 21:14:51 +02:00
2016-04-27 16:15:20 +02:00
/**
* Software - controlled Stepper Motor Current
*/
2016-03-20 02:44:08 +01:00
# if HAS_DIGIPOTSS
// From Arduino DigitalPotControl example
2017-06-25 05:23:45 +02:00
void Stepper : : digitalPotWrite ( const int16_t address , const int16_t value ) {
WRITE ( DIGIPOTSS_PIN , LOW ) ; // Take the SS pin low to select the chip
SPI . transfer ( address ) ; // Send the address and value via SPI
2012-08-30 09:16:57 +02:00
SPI . transfer ( value ) ;
2017-06-25 05:23:45 +02:00
WRITE ( DIGIPOTSS_PIN , HIGH ) ; // Take the SS pin high to de-select the chip
2012-08-30 09:16:57 +02:00
//delay(10);
2016-03-20 02:44:08 +01:00
}
2017-05-09 19:35:43 +02:00
# endif // HAS_DIGIPOTSS
2012-08-30 09:16:57 +02:00
2017-06-03 07:38:07 +02:00
# if HAS_MOTOR_CURRENT_PWM
2013-08-01 15:06:39 +02:00
2017-06-03 07:38:07 +02:00
void Stepper : : refresh_motor_power ( ) {
for ( uint8_t i = 0 ; i < COUNT ( motor_current_setting ) ; + + i ) {
switch ( i ) {
# if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
case 0 :
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
case 1 :
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
case 2 :
# endif
digipot_current ( i , motor_current_setting [ i ] ) ;
default : break ;
2016-09-25 13:32:58 +02:00
}
2017-06-03 07:38:07 +02:00
}
2016-09-25 13:32:58 +02:00
}
2012-08-30 09:16:57 +02:00
2017-06-03 07:38:07 +02:00
# endif // HAS_MOTOR_CURRENT_PWM
# if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
2017-06-25 05:23:45 +02:00
void Stepper : : digipot_current ( const uint8_t driver , const int current ) {
2016-09-25 13:32:58 +02:00
# if HAS_DIGIPOTSS
2017-06-25 05:23:45 +02:00
2016-09-25 13:32:58 +02:00
const uint8_t digipot_ch [ ] = DIGIPOT_CHANNELS ;
digitalPotWrite ( digipot_ch [ driver ] , current ) ;
2017-06-25 05:23:45 +02:00
2016-09-25 13:32:58 +02:00
# elif HAS_MOTOR_CURRENT_PWM
2017-06-03 07:38:07 +02:00
if ( WITHIN ( driver , 0 , 2 ) )
motor_current_setting [ driver ] = current ; // update motor_current_setting
2017-06-25 05:23:45 +02:00
# define _WRITE_CURRENT_PWM(P) analogWrite(MOTOR_CURRENT_PWM_## P ##_PIN, 255L * current / (MOTOR_CURRENT_PWM_RANGE))
2016-09-25 13:32:58 +02:00
switch ( driver ) {
# if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
2017-06-25 05:23:45 +02:00
case 0 : _WRITE_CURRENT_PWM ( XY ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
2017-06-25 05:23:45 +02:00
case 1 : _WRITE_CURRENT_PWM ( Z ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
2017-06-25 05:23:45 +02:00
case 2 : _WRITE_CURRENT_PWM ( E ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
}
# endif
}
2014-04-25 06:57:11 +02:00
2017-06-03 07:38:07 +02:00
void Stepper : : digipot_init ( ) {
# if HAS_DIGIPOTSS
static const uint8_t digipot_motor_current [ ] = DIGIPOT_MOTOR_CURRENT ;
SPI . begin ( ) ;
SET_OUTPUT ( DIGIPOTSS_PIN ) ;
for ( uint8_t i = 0 ; i < COUNT ( digipot_motor_current ) ; i + + ) {
//digitalPotWrite(digipot_ch[i], digipot_motor_current[i]);
digipot_current ( i , digipot_motor_current [ i ] ) ;
}
# elif HAS_MOTOR_CURRENT_PWM
# if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
SET_OUTPUT ( MOTOR_CURRENT_PWM_XY_PIN ) ;
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
SET_OUTPUT ( MOTOR_CURRENT_PWM_Z_PIN ) ;
# endif
# if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
SET_OUTPUT ( MOTOR_CURRENT_PWM_E_PIN ) ;
# endif
refresh_motor_power ( ) ;
// Set Timer5 to 31khz so the PWM of the motor power is as constant as possible. (removes a buzzing noise)
SET_CS5 ( PRESCALER_1 ) ;
# endif
}
2016-09-25 13:32:58 +02:00
# endif
2012-08-30 09:16:57 +02:00
2016-09-25 13:32:58 +02:00
# if HAS_MICROSTEPS
/**
* Software - controlled Microstepping
*/
2016-04-27 16:15:20 +02:00
2016-09-25 13:32:58 +02:00
void Stepper : : microstep_init ( ) {
SET_OUTPUT ( X_MS1_PIN ) ;
SET_OUTPUT ( X_MS2_PIN ) ;
2017-04-15 01:00:33 +02:00
# if HAS_Y_MICROSTEPS
2016-09-25 13:32:58 +02:00
SET_OUTPUT ( Y_MS1_PIN ) ;
SET_OUTPUT ( Y_MS2_PIN ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_Z_MICROSTEPS
2016-09-25 13:32:58 +02:00
SET_OUTPUT ( Z_MS1_PIN ) ;
SET_OUTPUT ( Z_MS2_PIN ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E0_MICROSTEPS
2016-09-25 13:32:58 +02:00
SET_OUTPUT ( E0_MS1_PIN ) ;
SET_OUTPUT ( E0_MS2_PIN ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E1_MICROSTEPS
2016-09-25 13:32:58 +02:00
SET_OUTPUT ( E1_MS1_PIN ) ;
SET_OUTPUT ( E1_MS2_PIN ) ;
2014-04-25 06:57:11 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E2_MICROSTEPS
2017-04-15 00:14:14 +02:00
SET_OUTPUT ( E2_MS1_PIN ) ;
SET_OUTPUT ( E2_MS2_PIN ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E3_MICROSTEPS
2017-04-15 00:14:14 +02:00
SET_OUTPUT ( E3_MS1_PIN ) ;
SET_OUTPUT ( E3_MS2_PIN ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E4_MICROSTEPS
2017-04-15 00:14:14 +02:00
SET_OUTPUT ( E4_MS1_PIN ) ;
SET_OUTPUT ( E4_MS2_PIN ) ;
# endif
2016-09-25 13:32:58 +02:00
static const uint8_t microstep_modes [ ] = MICROSTEP_MODES ;
for ( uint16_t i = 0 ; i < COUNT ( microstep_modes ) ; i + + )
microstep_mode ( i , microstep_modes [ i ] ) ;
2012-08-30 09:16:57 +02:00
}
2016-09-25 13:32:58 +02:00
2017-06-25 05:23:45 +02:00
void Stepper : : microstep_ms ( const uint8_t driver , const int8_t ms1 , const int8_t ms2 ) {
2016-09-25 13:32:58 +02:00
if ( ms1 > = 0 ) switch ( driver ) {
2017-04-14 23:36:12 +02:00
case 0 : WRITE ( X_MS1_PIN , ms1 ) ; break ;
2017-04-15 01:00:33 +02:00
# if HAS_Y_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 1 : WRITE ( Y_MS1_PIN , ms1 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_Z_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 2 : WRITE ( Z_MS1_PIN , ms1 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E0_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 3 : WRITE ( E0_MS1_PIN , ms1 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E1_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 4 : WRITE ( E1_MS1_PIN , ms1 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E2_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 5 : WRITE ( E2_MS1_PIN , ms1 ) ; break ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E3_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 6 : WRITE ( E3_MS1_PIN , ms1 ) ; break ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E4_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 7 : WRITE ( E4_MS1_PIN , ms1 ) ; break ;
# endif
2016-09-25 13:32:58 +02:00
}
if ( ms2 > = 0 ) switch ( driver ) {
2017-04-14 23:36:12 +02:00
case 0 : WRITE ( X_MS2_PIN , ms2 ) ; break ;
2017-04-15 01:00:33 +02:00
# if HAS_Y_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 1 : WRITE ( Y_MS2_PIN , ms2 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_Z_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 2 : WRITE ( Z_MS2_PIN , ms2 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E0_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 3 : WRITE ( E0_MS2_PIN , ms2 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E1_MICROSTEPS
2017-04-14 23:36:12 +02:00
case 4 : WRITE ( E1_MS2_PIN , ms2 ) ; break ;
2016-09-25 13:32:58 +02:00
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E2_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 5 : WRITE ( E2_MS2_PIN , ms2 ) ; break ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E3_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 6 : WRITE ( E3_MS2_PIN , ms2 ) ; break ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E4_MICROSTEPS
2017-04-15 00:14:14 +02:00
case 7 : WRITE ( E4_MS2_PIN , ms2 ) ; break ;
# endif
2016-09-25 13:32:58 +02:00
}
2012-08-30 09:16:57 +02:00
}
2017-06-25 05:23:45 +02:00
void Stepper : : microstep_mode ( const uint8_t driver , const uint8_t stepping_mode ) {
2016-09-25 13:32:58 +02:00
switch ( stepping_mode ) {
case 1 : microstep_ms ( driver , MICROSTEP1 ) ; break ;
case 2 : microstep_ms ( driver , MICROSTEP2 ) ; break ;
case 4 : microstep_ms ( driver , MICROSTEP4 ) ; break ;
case 8 : microstep_ms ( driver , MICROSTEP8 ) ; break ;
case 16 : microstep_ms ( driver , MICROSTEP16 ) ; break ;
}
2012-08-30 09:16:57 +02:00
}
2016-09-25 13:32:58 +02:00
void Stepper : : microstep_readings ( ) {
SERIAL_PROTOCOLLNPGM ( " MS1,MS2 Pins " ) ;
SERIAL_PROTOCOLPGM ( " X: " ) ;
SERIAL_PROTOCOL ( READ ( X_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( X_MS2_PIN ) ) ;
2017-04-15 01:00:33 +02:00
# if HAS_Y_MICROSTEPS
2016-09-25 13:32:58 +02:00
SERIAL_PROTOCOLPGM ( " Y: " ) ;
SERIAL_PROTOCOL ( READ ( Y_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( Y_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_Z_MICROSTEPS
2016-09-25 13:32:58 +02:00
SERIAL_PROTOCOLPGM ( " Z: " ) ;
SERIAL_PROTOCOL ( READ ( Z_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( Z_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E0_MICROSTEPS
2016-09-25 13:32:58 +02:00
SERIAL_PROTOCOLPGM ( " E0: " ) ;
SERIAL_PROTOCOL ( READ ( E0_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( E0_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E1_MICROSTEPS
2016-09-25 13:32:58 +02:00
SERIAL_PROTOCOLPGM ( " E1: " ) ;
SERIAL_PROTOCOL ( READ ( E1_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( E1_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E2_MICROSTEPS
2017-04-15 00:14:14 +02:00
SERIAL_PROTOCOLPGM ( " E2: " ) ;
SERIAL_PROTOCOL ( READ ( E2_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( E2_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E3_MICROSTEPS
2017-04-15 00:14:14 +02:00
SERIAL_PROTOCOLPGM ( " E3: " ) ;
SERIAL_PROTOCOL ( READ ( E3_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( E3_MS2_PIN ) ) ;
# endif
2017-04-15 01:00:33 +02:00
# if HAS_E4_MICROSTEPS
2017-04-15 00:14:14 +02:00
SERIAL_PROTOCOLPGM ( " E4: " ) ;
SERIAL_PROTOCOL ( READ ( E4_MS1_PIN ) ) ;
SERIAL_PROTOCOLLN ( READ ( E4_MS2_PIN ) ) ;
# endif
2016-09-25 13:32:58 +02:00
}
# endif // HAS_MICROSTEPS