Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 29 additions & 85 deletions Marlin/endstops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
#endif

#if HAS_BED_PROBE
#define ENDSTOPS_ENABLED (endstops.enabled || endstops.z_probe_enabled)
#define ENDSTOPS_ENABLED (enabled || z_probe_enabled)
#else
#define ENDSTOPS_ENABLED endstops.enabled
#define ENDSTOPS_ENABLED enabled
#endif

Endstops endstops;
Expand Down Expand Up @@ -196,25 +196,25 @@ void Endstops::init() {
} // Endstops::init

// Called from ISR. A change was detected. Find out what happened!
void Endstops::check_possible_change() { if (ENDSTOPS_ENABLED) endstops.update(); }
void Endstops::check_possible_change() { if (ENDSTOPS_ENABLED) update(); }

// Called from ISR: Poll endstop state if required
void Endstops::poll() {

#if ENABLED(PINS_DEBUGGING)
endstops.run_monitor(); // report changes in endstop status
run_monitor(); // report changes in endstop status
#endif

#if DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
if (ENDSTOPS_ENABLED) endstops.update();
if (ENDSTOPS_ENABLED) update();
#endif
}

void Endstops::enable_globally(const bool onoff) {
enabled_globally = enabled = onoff;

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
if (onoff) endstops.update(); // If enabling, update state now
if (onoff) update(); // If enabling, update state now
#endif
}

Expand All @@ -223,17 +223,16 @@ void Endstops::enable(const bool onoff) {
enabled = onoff;

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
if (onoff) endstops.update(); // If enabling, update state now
if (onoff) update(); // If enabling, update state now
#endif
}


// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
void Endstops::not_homing() {
enabled = enabled_globally;

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
if (enabled) endstops.update(); // If enabling, update state now
if (enabled) update(); // If enabling, update state now
#endif
}

Expand All @@ -242,7 +241,7 @@ void Endstops::hit_on_purpose() {
hit_state = 0;

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
if (enabled) endstops.update(); // If enabling, update state now
if (enabled) update(); // If enabling, update state now
#endif
}

Expand All @@ -252,7 +251,7 @@ void Endstops::hit_on_purpose() {
z_probe_enabled = onoff;

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
if (enabled) endstops.update(); // If enabling, update state now
if (enabled) update(); // If enabling, update state now
#endif
}
#endif
Expand Down Expand Up @@ -379,7 +378,6 @@ void Endstops::M119() {
// Check endstops - Could be called from ISR!
void Endstops::update() {

#define SET_BIT(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
// UPDATE_ENDSTOP_BIT: set the current endstop bits for an endstop to its status
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
// COPY_BIT: copy the value of SRC_BIT to DST_BIT in DST
Expand All @@ -390,89 +388,37 @@ void Endstops::update() {
if (G38_move) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
#endif

/**
* Define conditions for checking endstops
*/

#if IS_CORE
#define S_(N) stepper.movement_non_null(CORE_AXIS_##N)
#define D_(N) stepper.motor_direction(CORE_AXIS_##N)
// With Dual X, endstops are only checked in the homing direction for the active extruder
#if ENABLED(DUAL_X_CARRIAGE)
#define E0_ACTIVE stepper.movement_extruder() == 0
#define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
#define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
#else
#define X_MIN_TEST true
#define X_MAX_TEST true
#endif

// Use HEAD for core axes, AXIS for others
#if CORE_IS_XY || CORE_IS_XZ
/**
* Head direction in -X axis for CoreXY and CoreXZ bots.
*
* If steps differ, both axes are moving.
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below)
* If DeltaA == DeltaB, the movement is only in the 1st axis (X)
*/
#if ENABLED(COREXY) || ENABLED(COREXZ)
#define X_CMP ==
#else
#define X_CMP !=
#endif
#define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
#define X_AXIS_HEAD X_HEAD
#else
#define X_MOVE_TEST stepper.movement_non_null(X_AXIS)
#define X_AXIS_HEAD X_AXIS
#endif

#if CORE_IS_XY || CORE_IS_YZ
/**
* Head direction in -Y axis for CoreXY / CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z)
*/
#if ENABLED(COREYX) || ENABLED(COREYZ)
#define Y_CMP ==
#else
#define Y_CMP !=
#endif
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
#define Y_AXIS_HEAD Y_HEAD
#else
#define Y_MOVE_TEST stepper.movement_non_null(Y_AXIS)
#define Y_AXIS_HEAD Y_AXIS
#endif

#if CORE_IS_XZ || CORE_IS_YZ
/**
* Head direction in -Z axis for CoreXZ or CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z)
*/
#if ENABLED(COREZX) || ENABLED(COREZY)
#define Z_CMP ==
#else
#define Z_CMP !=
#endif
#define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
#define Z_AXIS_HEAD Z_HEAD
#else
#define Z_MOVE_TEST stepper.movement_non_null(Z_AXIS)
#define Z_AXIS_HEAD Z_AXIS
#endif

// With Dual X, endstops are only checked in the homing direction for the active extruder
#if ENABLED(DUAL_X_CARRIAGE)
#define E0_ACTIVE stepper.movement_extruder() == 0
#define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
#define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
#else
#define X_MIN_TEST true
#define X_MAX_TEST true
#endif

/**
* Check and update endstops according to conditions
*/
if (X_MOVE_TEST) {
if (stepper.axis_is_moving(X_AXIS)) {
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
#if HAS_X_MIN
#if ENABLED(X_DUAL_ENDSTOPS)
Expand Down Expand Up @@ -503,7 +449,7 @@ void Endstops::update() {
}
}

if (Y_MOVE_TEST) {
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN
#if ENABLED(Y_DUAL_ENDSTOPS)
Expand Down Expand Up @@ -534,7 +480,7 @@ void Endstops::update() {
}
}

if (Z_MOVE_TEST) {
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN
#if ENABLED(Z_DUAL_ENDSTOPS)
Expand All @@ -555,9 +501,7 @@ void Endstops::update() {

// When closing the gap check the enabled probe
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
if (z_probe_enabled) {
UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
}
if (z_probe_enabled) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
#endif
}
else { // Z +direction. Gantry up, bed down.
Expand Down Expand Up @@ -633,16 +577,16 @@ void Endstops::update() {
// If G38 command is active check Z_MIN_PROBE for ALL movement
if (G38_move) {
if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
if (stepper.movement_non_null(_AXIS(X))) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(_AXIS(X)); }
else if (stepper.movement_non_null(_AXIS(Y))) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(_AXIS(Y)); }
else if (stepper.movement_non_null(_AXIS(Z))) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(_AXIS(Z)); }
if (stepper.axis_is_moving(_AXIS(X))) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(_AXIS(X)); }
else if (stepper.axis_is_moving(_AXIS(Y))) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(_AXIS(Y)); }
else if (stepper.axis_is_moving(_AXIS(Z))) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(_AXIS(Z)); }
G38_endstop_hit = true;
}
}
#endif

// Now, we must signal, after validation, if an endstop limit is pressed or not
if (X_MOVE_TEST) {
if (stepper.axis_is_moving(X_AXIS)) {
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
#if HAS_X_MIN
#if ENABLED(X_DUAL_ENDSTOPS)
Expand All @@ -663,7 +607,7 @@ void Endstops::update() {
}
}

if (Y_MOVE_TEST) {
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN
#if ENABLED(Y_DUAL_ENDSTOPS)
Expand All @@ -684,7 +628,7 @@ void Endstops::update() {
}
}

if (Z_MOVE_TEST) {
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN
#if ENABLED(Z_DUAL_ENDSTOPS)
Expand Down
1 change: 1 addition & 0 deletions Marlin/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#define TEST(n,b) !!((n)&_BV(b))
#define SBI(n,b) (n |= _BV(b))
#define CBI(n,b) (n &= ~_BV(b))
#define SET_BIT(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)

#define _BV32(b) (1UL << (b))
#define TEST32(n,b) !!((n)&_BV32(b))
Expand Down
83 changes: 73 additions & 10 deletions Marlin/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ block_t* Stepper::current_block = NULL; // A pointer to the block currently bei

// private:

uint8_t Stepper::last_direction_bits = 0, // The next stepping-bits to be output
Stepper::last_movement_extruder = 0xFF; // Last movement extruder, as computed when the last movement was fetched from planner
bool Stepper::abort_current_block, // Signals to the stepper that current block should be aborted
Stepper::last_movement_non_null[NUM_AXIS]; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
uint8_t Stepper::last_direction_bits = 0,
Stepper::last_movement_extruder = 0xFF,
Stepper::axis_did_move;
bool Stepper::abort_current_block;

#if ENABLED(X_DUAL_ENDSTOPS)
bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
Expand Down Expand Up @@ -367,10 +367,6 @@ void Stepper::set_directions() {
#endif // !LIN_ADVANCE
}

#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
extern volatile uint8_t e_hit;
#endif

#if ENABLED(BEZIER_JERK_CONTROL)
/**
* We are using a quintic (fifth-degree) Bézier polynomial for the velocity curve.
Expand Down Expand Up @@ -1533,8 +1529,75 @@ uint32_t Stepper::stepper_block_phase_isr() {
return interval; // No more queued movements!
}

// Compute movement direction for proper endstop handling
LOOP_NA(i) last_movement_non_null[i] = !!current_block->steps[i];
// Flag all moving axes for proper endstop handling

#if IS_CORE
// Define conditions for checking endstops
#define S_(N) current_block->steps[CORE_AXIS_##N]
#define D_(N) motor_direction(CORE_AXIS_##N)
#endif

#if CORE_IS_XY || CORE_IS_XZ
/**
* Head direction in -X axis for CoreXY and CoreXZ bots.
*
* If steps differ, both axes are moving.
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below)
* If DeltaA == DeltaB, the movement is only in the 1st axis (X)
*/
#if ENABLED(COREXY) || ENABLED(COREXZ)
#define X_CMP ==
#else
#define X_CMP !=
#endif
#define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
#else
#define X_MOVE_TEST !!current_block->steps[X_AXIS]
#endif

#if CORE_IS_XY || CORE_IS_YZ
/**
* Head direction in -Y axis for CoreXY / CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z)
*/
#if ENABLED(COREYX) || ENABLED(COREYZ)
#define Y_CMP ==
#else
#define Y_CMP !=
#endif
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
#else
#define Y_MOVE_TEST !!current_block->steps[Y_AXIS]
#endif

#if CORE_IS_XZ || CORE_IS_YZ
/**
* Head direction in -Z axis for CoreXZ or CoreYZ bots.
*
* If steps differ, both axes are moving
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above)
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z)
*/
#if ENABLED(COREZX) || ENABLED(COREZY)
#define Z_CMP ==
#else
#define Z_CMP !=
#endif
#define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
#else
#define Z_MOVE_TEST !!current_block->steps[Z_AXIS]
#endif

SET_BIT(axis_did_move, X_AXIS, X_MOVE_TEST);
SET_BIT(axis_did_move, Y_AXIS, Y_MOVE_TEST);
SET_BIT(axis_did_move, Z_AXIS, Z_MOVE_TEST);
SET_BIT(axis_did_move, E_AXIS, !!current_block->steps[E_AXIS]);
SET_BIT(axis_did_move, X_HEAD, !!current_block->steps[X_HEAD]);
SET_BIT(axis_did_move, Y_HEAD, !!current_block->steps[Y_HEAD]);
SET_BIT(axis_did_move, Z_HEAD, !!current_block->steps[Z_HEAD]);

// Initialize the trapezoid generator from the current block.
#if ENABLED(LIN_ADVANCE)
Expand Down
10 changes: 5 additions & 5 deletions Marlin/stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ class Stepper {

private:

static uint8_t last_direction_bits, // The next stepping-bits to be output
last_movement_extruder; // Last movement extruder, as computed when the last movement was fetched from planner
static bool abort_current_block, // Signals to the stepper that current block should be aborted
last_movement_non_null[NUM_AXIS]; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
static uint8_t last_direction_bits, // The next stepping-bits to be output
last_movement_extruder, // Last movement extruder, as computed when the last movement was fetched from planner
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
static bool abort_current_block; // Signals to the stepper that current block should be aborted

#if ENABLED(X_DUAL_ENDSTOPS)
static bool locked_x_motor, locked_x2_motor;
Expand Down Expand Up @@ -219,7 +219,7 @@ class Stepper {
FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return TEST(last_direction_bits, axis); }

// The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same.
FORCE_INLINE static bool movement_non_null(const AxisEnum axis) { return last_movement_non_null[axis]; }
FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); }

// The extruder associated to the last movement
FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; }
Expand Down