diff --git a/Marlin/macros.h b/Marlin/macros.h index a916908358..a943e9cb54 100644 --- a/Marlin/macros.h +++ b/Marlin/macros.h @@ -36,8 +36,9 @@ #define CRITICAL_SECTION_END SREG = _sreg; #endif -// Clock speed factor -#define CYCLES_PER_MICROSECOND (F_CPU / 1000000UL) // 16 or 20 +// Clock speed factors +#define CYCLES_PER_MICROSECOND (F_CPU / 1000000L) // 16 or 20 +#define INT0_PRESCALER 8 // Highly granular delays for step pulses, etc. #define DELAY_0_NOP NOOP diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 0ff0ec74d3..fb761aefcb 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -460,7 +460,7 @@ void Stepper::isr() { // Take multiple steps per interrupt (For high speed moves) bool all_steps_done = false; - for (int8_t i = 0; i < step_loops; i++) { + for (uint8_t i = step_loops; i--;) { #if ENABLED(LIN_ADVANCE) counter_E += current_block->steps[E_AXIS]; @@ -530,10 +530,34 @@ void Stepper::isr() { _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS),0); \ } - #define CYCLES_EATEN_BY_CODE 240 + #if HAS_X_STEP + #define _COUNT_STEPPERS_1 1 + #else + #define _COUNT_STEPPERS_1 0 + #endif + #if HAS_Y_STEP + #define _COUNT_STEPPERS_2 _COUNT_STEPPERS_1 + 1 + #else + #define _COUNT_STEPPERS_2 _COUNT_STEPPERS_1 + #endif + #if HAS_Z_STEP + #define _COUNT_STEPPERS_3 _COUNT_STEPPERS_2 + 1 + #else + #define _COUNT_STEPPERS_3 _COUNT_STEPPERS_2 + #endif + #if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE) + #define _COUNT_STEPPERS_4 _COUNT_STEPPERS_3 + 1 + #else + #define _COUNT_STEPPERS_4 _COUNT_STEPPERS_3 + #endif + + #define CYCLES_EATEN_XYZE ((_COUNT_STEPPERS_4) * 5) + #define EXTRA_CYCLES_XYZE (STEP_PULSE_CYCLES - (CYCLES_EATEN_XYZE)) - // If a minimum pulse time was specified get the CPU clock - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_CODE + // If a minimum pulse time was specified get the timer 0 value + // which increments every 4µs on 16MHz and every 3.2µs on 20MHz. + // Two or 3 counts of TCNT0 should be a sufficient delay. + #if EXTRA_CYCLES_XYZE > 20 uint32_t pulse_start = TCNT0; #endif @@ -564,9 +588,12 @@ void Stepper::isr() { #endif #endif // !ADVANCE && !LIN_ADVANCE - // For a minimum pulse time wait before stopping pulses - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_CODE - while ((uint32_t)(TCNT0 - pulse_start) < STEP_PULSE_CYCLES - CYCLES_EATEN_BY_CODE) { /* nada */ } + // 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); #endif #if HAS_X_STEP @@ -601,7 +628,15 @@ void Stepper::isr() { all_steps_done = true; break; } - } + + // For minimum pulse time wait before stopping pulses + #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 #if ENABLED(LIN_ADVANCE) if (current_block->use_advance_lead) { @@ -765,6 +800,9 @@ void Stepper::isr() { #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) + #define CYCLES_EATEN_E (E_STEPPERS * 5) + #define EXTRA_CYCLES_E (STEP_PULSE_CYCLES - (CYCLES_EATEN_E)) + // Timer interrupt for E. e_steps is set in the main routine; void Stepper::advance_isr() { @@ -794,12 +832,10 @@ void Stepper::isr() { #endif #endif - #define CYCLES_EATEN_BY_E 60 - // Step all E steppers that have steps - for (uint8_t i = 0; i < step_loops; i++) { + for (uint8_t i = step_loops; i--;) { - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_E + #if EXTRA_CYCLES_E > 20 uint32_t pulse_start = TCNT0; #endif @@ -814,9 +850,12 @@ void Stepper::isr() { #endif #endif - // For a minimum pulse time wait before stopping pulses - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_E - while ((uint32_t)(TCNT0 - pulse_start) < STEP_PULSE_CYCLES - CYCLES_EATEN_BY_E) { /* nada */ } + // 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); #endif STOP_E_PULSE(0); @@ -829,8 +868,15 @@ void Stepper::isr() { #endif #endif #endif - } + // 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 } void Stepper::advance_isr_scheduler() { @@ -1056,15 +1102,11 @@ void Stepper::init() { ENABLE_STEPPER_DRIVER_INTERRUPT(); #if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE) - - for (int i = 0; i < E_STEPPERS; i++) { - e_steps[i] = 0; - #if ENABLED(LIN_ADVANCE) - current_adv_steps[i] = 0; - #endif - } - - #endif // ADVANCE or LIN_ADVANCE + ZERO(e_steps); + #if ENABLED(LIN_ADVANCE) + ZERO(current_adv_steps); + #endif + #endif // ADVANCE || LIN_ADVANCE endstops.enable(true); // Start with endstops active. After homing they can be disabled sei(); @@ -1235,32 +1277,43 @@ void Stepper::report_positions() { #if ENABLED(BABYSTEPPING) - #define CYCLES_EATEN_BY_BABYSTEP 60 + #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)) #define _ENABLE(AXIS) enable_## AXIS() #define _READ_DIR(AXIS) AXIS ##_DIR_READ #define _INVERT_DIR(AXIS) INVERT_## AXIS ##_DIR #define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true) - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_BABYSTEP + #if EXTRA_CYCLES_BABYSTEP > 20 #define _SAVE_START (pulse_start = TCNT0) - #define _PULSE_WAIT while ((uint32_t)(TCNT0 - pulse_start) < STEP_PULSE_CYCLES - CYCLES_EATEN_BY_BABYSTEP) { /* nada */ } + #define _PULSE_WAIT while (EXTRA_CYCLES_BABYSTEP > (uint32_t)(TCNT0 - pulse_start) * (INT0_PRESCALER)) { /* nada */ } #else #define _SAVE_START NOOP - #define _PULSE_WAIT NOOP + #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 #endif - #define START_BABYSTEP_AXIS(AXIS, INVERT) { \ - old_dir = _READ_DIR(AXIS); \ - _SAVE_START; \ + #define BABYSTEP_AXIS(AXIS, INVERT) { \ + const uint8_t old_dir = _READ_DIR(AXIS); \ + _ENABLE(AXIS); \ + _SAVE_START; \ _APPLY_DIR(AXIS, _INVERT_DIR(AXIS)^direction^INVERT); \ - _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), true); \ - } - - #define STOP_BABYSTEP_AXIS(AXIS) { \ - _PULSE_WAIT; \ - _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS), true); \ - _APPLY_DIR(AXIS, old_dir); \ + _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), true); \ + _PULSE_WAIT; \ + _APPLY_STEP(AXIS)(_INVERT_STEP_PIN(AXIS), true); \ + _APPLY_DIR(AXIS, old_dir); \ } // MUST ONLY BE CALLED BY AN ISR, @@ -1268,31 +1321,30 @@ void Stepper::report_positions() { void Stepper::babystep(const AxisEnum axis, const bool direction) { cli(); uint8_t old_dir; - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_BABYSTEP + + #if EXTRA_CYCLES_BABYSTEP > 20 uint32_t pulse_start; #endif switch (axis) { - case X_AXIS: - _ENABLE(x); - START_BABYSTEP_AXIS(X, false); - STOP_BABYSTEP_AXIS(X); - break; + #if ENABLED(BABYSTEP_XY) + + case X_AXIS: + BABYSTEP_AXIS(X, false); + break; - case Y_AXIS: - _ENABLE(y); - START_BABYSTEP_AXIS(Y, false); - STOP_BABYSTEP_AXIS(Y); - break; + case Y_AXIS: + BABYSTEP_AXIS(Y, false); + break; + + #endif case Z_AXIS: { #if DISABLED(DELTA) - _ENABLE(z); - START_BABYSTEP_AXIS(Z, BABYSTEP_INVERT_Z); - STOP_BABYSTEP_AXIS(Z); + BABYSTEP_AXIS(Z, BABYSTEP_INVERT_Z); #else // DELTA @@ -1305,24 +1357,24 @@ void Stepper::report_positions() { uint8_t old_x_dir_pin = X_DIR_READ, old_y_dir_pin = Y_DIR_READ, old_z_dir_pin = Z_DIR_READ; - //setup new step + X_DIR_WRITE(INVERT_X_DIR ^ z_direction); Y_DIR_WRITE(INVERT_Y_DIR ^ z_direction); Z_DIR_WRITE(INVERT_Z_DIR ^ z_direction); - //perform step - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_BABYSTEP - pulse_start = TCNT0; - #endif + + _SAVE_START; + X_STEP_WRITE(!INVERT_X_STEP_PIN); Y_STEP_WRITE(!INVERT_Y_STEP_PIN); Z_STEP_WRITE(!INVERT_Z_STEP_PIN); - #if STEP_PULSE_CYCLES > CYCLES_EATEN_BY_BABYSTEP - while ((uint32_t)(TCNT0 - pulse_start) < STEP_PULSE_CYCLES - CYCLES_EATEN_BY_BABYSTEP) { /* nada */ } - #endif + + _PULSE_WAIT; + X_STEP_WRITE(INVERT_X_STEP_PIN); Y_STEP_WRITE(INVERT_Y_STEP_PIN); Z_STEP_WRITE(INVERT_Z_STEP_PIN); - //get old pin state back. + + // Restore direction bits X_DIR_WRITE(old_x_dir_pin); Y_DIR_WRITE(old_y_dir_pin); Z_DIR_WRITE(old_z_dir_pin);