Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize stepper ISRs, plus cleanup, shorthand #4738

Merged
merged 10 commits into from
Sep 1, 2016
7 changes: 6 additions & 1 deletion Marlin/Conditionals_post.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@
#endif

/**
* Axis lengths
* Axis lengths and center
*/
#define X_MAX_LENGTH (X_MAX_POS - (X_MIN_POS))
#define Y_MAX_LENGTH (Y_MAX_POS - (Y_MIN_POS))
#define Z_MAX_LENGTH (Z_MAX_POS - (Z_MIN_POS))
#define X_CENTER float((X_MIN_POS + X_MAX_POS) * 0.5)
#define Y_CENTER float((Y_MIN_POS + Y_MAX_POS) * 0.5)
#define Z_CENTER float((Z_MIN_POS + Z_MAX_POS) * 0.5)

/**
* CoreXY and CoreXZ
Expand Down Expand Up @@ -127,6 +130,8 @@
*/
#define HAS_PROBING_PROCEDURE (ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST))

#define HOMING_Z_WITH_PROBE (HAS_BED_PROBE && Z_HOME_DIR < 0 && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN))

// Boundaries for probing based on set limits
#define MIN_PROBE_X (max(X_MIN_POS, X_MIN_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
#define MAX_PROBE_X (min(X_MAX_POS, X_MAX_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
Expand Down
29 changes: 12 additions & 17 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1586,7 +1586,7 @@ static void set_axis_is_at_home(AxisEnum axis) {

if (axis == Z_AXIS) {
#if HAS_BED_PROBE && Z_HOME_DIR < 0
#if DISABLED(Z_MIN_PROBE_ENDSTOP)
#if HOMING_Z_WITH_PROBE
current_position[Z_AXIS] -= zprobe_zoffset;
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) {
Expand Down Expand Up @@ -2049,8 +2049,8 @@ static void clean_up_after_endstop_or_probe_move() {
#endif
#endif

#define DEPLOY_PROBE() set_probe_deployed( true )
#define STOW_PROBE() set_probe_deployed( false )
#define DEPLOY_PROBE() set_probe_deployed(true)
#define STOW_PROBE() set_probe_deployed(false)

// returns false for ok and true for failure
static bool set_probe_deployed(bool deploy) {
Expand All @@ -2073,8 +2073,8 @@ static void clean_up_after_endstop_or_probe_move() {
if (axis_unhomed_error(true, true, true )) { stop(); return true; }
#endif

float oldXpos = current_position[X_AXIS]; // save x position
float oldYpos = current_position[Y_AXIS]; // save y position
float oldXpos = current_position[X_AXIS],
oldYpos = current_position[Y_AXIS];

#ifdef _TRIGGERED_WHEN_STOWED_TEST

Expand Down Expand Up @@ -2430,10 +2430,10 @@ static void do_homing_move(AxisEnum axis, float where, float fr_mm_s = 0.0) {
#define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS)

static void homeaxis(AxisEnum axis) {
#define HOMEAXIS_DO(LETTER) \
((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
#define CAN_HOME(A) \
(axis == A##_AXIS && ((A##_MIN_PIN > -1 && A##_HOME_DIR < 0) || (A##_MAX_PIN > -1 && A##_HOME_DIR > 0)))

if (!(axis == X_AXIS ? HOMEAXIS_DO(X) : axis == Y_AXIS ? HOMEAXIS_DO(Y) : axis == Z_AXIS ? HOMEAXIS_DO(Z) : false)) return;
if (!CAN_HOME(X) && !CAN_HOME(Y) && !CAN_HOME(Z)) return;

#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) {
Expand All @@ -2449,7 +2449,7 @@ static void homeaxis(AxisEnum axis) {
home_dir(axis);

// Homing Z towards the bed? Deploy the Z probe or endstop.
#if HAS_BED_PROBE && Z_HOME_DIR < 0 && DISABLED(Z_MIN_PROBE_ENDSTOP)
#if HOMING_Z_WITH_PROBE
if (axis == Z_AXIS) {
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) SERIAL_ECHOPGM("> ");
Expand Down Expand Up @@ -2532,7 +2532,7 @@ static void homeaxis(AxisEnum axis) {
#endif

// Put away the Z probe
#if HAS_BED_PROBE && Z_HOME_DIR < 0 && DISABLED(Z_MIN_PROBE_ENDSTOP)
#if HOMING_Z_WITH_PROBE
if (axis == Z_AXIS) {
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) SERIAL_ECHOPGM("> ");
Expand Down Expand Up @@ -3104,9 +3104,7 @@ inline void gcode_G28() {
#if ENABLED(Z_SAFE_HOMING)

#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) {
SERIAL_ECHOLNPGM("> Z_SAFE_HOMING >>>");
}
if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> Z_SAFE_HOMING >>>");
#endif

if (home_all_axis) {
Expand All @@ -3127,10 +3125,7 @@ inline void gcode_G28() {
destination[Z_AXIS] = current_position[Z_AXIS]; // Z is already at the right height

#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) {
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
}
if (DEBUGGING(LEVELING)) DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
#endif

// Move in the XY plane
Expand Down
12 changes: 5 additions & 7 deletions Marlin/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,8 @@ void Planner::calculate_trapezoid_for_block(block_t* block, float entry_factor,


// The kernel called by recalculate() when scanning the plan from last to first entry.
void Planner::reverse_pass_kernel(block_t* previous, block_t* current, block_t* next) {
void Planner::reverse_pass_kernel(block_t* current, block_t* next) {
if (!current) return;
UNUSED(previous);

if (next) {
// If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
Expand Down Expand Up @@ -250,15 +249,14 @@ void Planner::reverse_pass() {
block[2] = block[1];
block[1] = block[0];
block[0] = &block_buffer[b];
reverse_pass_kernel(block[0], block[1], block[2]);
reverse_pass_kernel(block[1], block[2]);
}
}
}

// The kernel called by recalculate() when scanning the plan from first to last entry.
void Planner::forward_pass_kernel(block_t* previous, block_t* current, block_t* next) {
void Planner::forward_pass_kernel(block_t* previous, block_t* current) {
if (!previous) return;
UNUSED(next);

// If the previous block is an acceleration block, but it is not long enough to complete the
// full speed change within the block, we need to adjust the entry speed accordingly. Entry
Expand Down Expand Up @@ -288,9 +286,9 @@ void Planner::forward_pass() {
block[0] = block[1];
block[1] = block[2];
block[2] = &block_buffer[b];
forward_pass_kernel(block[0], block[1], block[2]);
forward_pass_kernel(block[0], block[1]);
}
forward_pass_kernel(block[1], block[2], NULL);
forward_pass_kernel(block[1], block[2]);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions Marlin/planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,8 @@ class Planner {

static void calculate_trapezoid_for_block(block_t* block, float entry_factor, float exit_factor);

static void reverse_pass_kernel(block_t* previous, block_t* current, block_t* next);
static void forward_pass_kernel(block_t* previous, block_t* current, block_t* next);
static void reverse_pass_kernel(block_t* current, block_t* next);
static void forward_pass_kernel(block_t* previous, block_t* current);

static void reverse_pass();
static void forward_pass();
Expand Down
102 changes: 71 additions & 31 deletions Marlin/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ long Stepper::counter_X = 0,
Stepper::counter_Z = 0,
Stepper::counter_E = 0;

volatile unsigned long Stepper::step_events_completed = 0; // The number of step events executed in the current block
volatile uint32_t Stepper::step_events_completed = 0; // The number of step events executed in the current block

#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)

Expand Down Expand Up @@ -372,6 +372,7 @@ void Stepper::isr() {
) endstops.update();

// Take multiple steps per interrupt (For high speed moves)
bool all_steps_done = false;
for (int8_t i = 0; i < step_loops; i++) {
#ifndef USBCON
customizedSerial.checkRx(); // Check for serial chars.
Expand All @@ -385,7 +386,7 @@ void Stepper::isr() {
#if DISABLED(MIXING_EXTRUDER)
// Don't step E here for mixing extruder
count_position[E_AXIS] += count_direction[E_AXIS];
e_steps[TOOL_E_INDEX] += motor_direction(E_AXIS) ? -1 : 1;
motor_direction(E_AXIS) ? --e_steps[TOOL_E_INDEX] : ++e_steps[TOOL_E_INDEX];
#endif
}

Expand Down Expand Up @@ -449,17 +450,20 @@ void Stepper::isr() {
#define _APPLY_STEP(AXIS) AXIS ##_APPLY_STEP
#define _INVERT_STEP_PIN(AXIS) INVERT_## AXIS ##_STEP_PIN

// 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); }

// 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); \
}

// If a minimum pulse time was specified get the CPU clock
#if MINIMUM_STEPPER_PULSE > 0
static uint32_t pulse_start;
pulse_start = TCNT0;
Expand All @@ -475,6 +479,7 @@ void Stepper::isr() {
PULSE_START(Z);
#endif

// For non-advance use linear interpolation for E also
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
// Keep updating the single E axis
Expand All @@ -491,6 +496,7 @@ void Stepper::isr() {
#endif
#endif // !ADVANCE && !LIN_ADVANCE

// For a minimum pulse time wait before stopping pulses
#if MINIMUM_STEPPER_PULSE > 0
#define CYCLES_EATEN_BY_CODE 10
while ((uint32_t)(TCNT0 - pulse_start) < (MINIMUM_STEPPER_PULSE * (F_CPU / 1000000UL)) - CYCLES_EATEN_BY_CODE) { /* nada */ }
Expand Down Expand Up @@ -524,18 +530,20 @@ void Stepper::isr() {
#endif
#endif // !ADVANCE && !LIN_ADVANCE

step_events_completed++;
if (step_events_completed >= current_block->step_event_count) break;
if (++step_events_completed >= current_block->step_event_count) {
all_steps_done = true;
break;
}
}

#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
// If we have esteps to execute, fire the next ISR "now"
// If we have esteps to execute, fire the next advance_isr "now"
if (e_steps[TOOL_E_INDEX]) OCR0A = TCNT0 + 2;
#endif

// Calculate new timer value
unsigned short timer, step_rate;
if (step_events_completed <= (unsigned long)current_block->accelerate_until) {
uint16_t timer, step_rate;
if (step_events_completed <= (uint32_t)current_block->accelerate_until) {

MultiU24X32toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
acc_step_rate += current_block->initial_rate;
Expand All @@ -551,14 +559,14 @@ void Stepper::isr() {
#if ENABLED(LIN_ADVANCE)

if (current_block->use_advance_lead)
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
current_estep_rate[TOOL_E_INDEX] = ((uint32_t)acc_step_rate * current_block->e_speed_multiplier8) >> 8;

if (current_block->use_advance_lead) {
#if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP(j)
current_estep_rate[j] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
current_estep_rate[j] = ((uint32_t)acc_step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
#else
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
current_estep_rate[TOOL_E_INDEX] = ((uint32_t)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
#endif
}

Expand Down Expand Up @@ -588,10 +596,10 @@ void Stepper::isr() {
eISR_Rate = (timer >> 2) * step_loops / abs(e_steps[TOOL_E_INDEX]);
#endif
}
else if (step_events_completed > (unsigned long)current_block->decelerate_after) {
else if (step_events_completed > (uint32_t)current_block->decelerate_after) {
MultiU24X32toH16(step_rate, deceleration_time, current_block->acceleration_rate);

if (step_rate <= acc_step_rate) { // Still decelerating?
if (step_rate < acc_step_rate) { // Still decelerating?
step_rate = acc_step_rate - step_rate;
NOLESS(step_rate, current_block->final_rate);
}
Expand All @@ -608,9 +616,9 @@ void Stepper::isr() {
if (current_block->use_advance_lead) {
#if ENABLED(MIXING_EXTRUDER)
MIXING_STEPPERS_LOOP(j)
current_estep_rate[j] = ((unsigned long)step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
current_estep_rate[j] = ((uint32_t)step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
#else
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8;
current_estep_rate[TOOL_E_INDEX] = ((uint32_t)step_rate * current_block->e_speed_multiplier8) >> 8;
#endif
}

Expand Down Expand Up @@ -654,10 +662,10 @@ void Stepper::isr() {
step_loops = step_loops_nominal;
}

OCR1A = (OCR1A < (TCNT1 + 16)) ? (TCNT1 + 16) : OCR1A;
NOLESS(OCR1A, TCNT1 + 16);

// If current block is finished, reset pointer
if (step_events_completed >= current_block->step_event_count) {
if (all_steps_done) {
current_block = NULL;
planner.discard_current_block();
}
Expand All @@ -675,29 +683,61 @@ void Stepper::isr() {
old_OCR0A += eISR_Rate;
OCR0A = old_OCR0A;

#define STEP_E_ONCE(INDEX) \
if (e_steps[INDEX] != 0) { \
E## INDEX ##_STEP_WRITE(INVERT_E_STEP_PIN); \
if (e_steps[INDEX] < 0) { \
E## INDEX ##_DIR_WRITE(INVERT_E## INDEX ##_DIR); \
e_steps[INDEX]++; \
} \
else { \
E## INDEX ##_DIR_WRITE(!INVERT_E## INDEX ##_DIR); \
e_steps[INDEX]--; \
} \
#define SET_E_STEP_DIR(INDEX) \
E## INDEX ##_DIR_WRITE(e_steps[INDEX] <= 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)

#define START_E_PULSE(INDEX) \
if (e_steps[INDEX]) E## INDEX ##_STEP_WRITE(INVERT_E_STEP_PIN)

#define STOP_E_PULSE(INDEX) \
if (e_steps[INDEX]) { \
e_steps[INDEX] < 0 ? ++e_steps[INDEX] : --e_steps[INDEX]; \
E## INDEX ##_STEP_WRITE(!INVERT_E_STEP_PIN); \
}

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);
#endif
#endif
#endif

// Step all E steppers that have steps
for (uint8_t i = 0; i < step_loops; i++) {
STEP_E_ONCE(0);

#if MINIMUM_STEPPER_PULSE > 0
static uint32_t pulse_start;
pulse_start = TCNT0;
#endif

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);
#endif
#endif
#endif

// For a minimum pulse time wait before stopping pulses
#if MINIMUM_STEPPER_PULSE > 0
#define CYCLES_EATEN_BY_E 10
while ((uint32_t)(TCNT0 - pulse_start) < (MINIMUM_STEPPER_PULSE * (F_CPU / 1000000UL)) - CYCLES_EATEN_BY_E) { /* nada */ }
#endif

STOP_E_PULSE(0);
#if E_STEPPERS > 1
STEP_E_ONCE(1);
STOP_E_PULSE(1);
#if E_STEPPERS > 2
STEP_E_ONCE(2);
STOP_E_PULSE(2);
#if E_STEPPERS > 3
STEP_E_ONCE(3);
STOP_E_PULSE(3);
#endif
#endif
#endif
Expand Down
2 changes: 1 addition & 1 deletion Marlin/stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Stepper {

// Counter variables for the Bresenham line tracer
static long counter_X, counter_Y, counter_Z, counter_E;
static volatile unsigned long step_events_completed; // The number of step events executed in the current block
static volatile uint32_t step_events_completed; // The number of step events executed in the current block

#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
static unsigned char old_OCR0A;
Expand Down