️ Handle shared enable pins (#22824)

This commit is contained in:
Scott Lahteine
2021-09-28 01:07:51 -05:00
committed by Scott Lahteine
parent 25a131b942
commit 021ceeba0b
26 changed files with 523 additions and 252 deletions

View File

@@ -1375,13 +1375,13 @@ void Planner::check_axes_activity() {
// Disable inactive axes
//
LOGICAL_AXIS_CODE(
if (TERN0(DISABLE_E, !axis_active.e)) disable_e_steppers(),
if (TERN0(DISABLE_X, !axis_active.x)) DISABLE_AXIS_X(),
if (TERN0(DISABLE_Y, !axis_active.y)) DISABLE_AXIS_Y(),
if (TERN0(DISABLE_Z, !axis_active.z)) DISABLE_AXIS_Z(),
if (TERN0(DISABLE_I, !axis_active.i)) DISABLE_AXIS_I(),
if (TERN0(DISABLE_J, !axis_active.j)) DISABLE_AXIS_J(),
if (TERN0(DISABLE_K, !axis_active.k)) DISABLE_AXIS_K()
if (TERN0(DISABLE_E, !axis_active.e)) stepper.disable_e_steppers(),
if (TERN0(DISABLE_X, !axis_active.x)) stepper.disable_axis(X_AXIS),
if (TERN0(DISABLE_Y, !axis_active.y)) stepper.disable_axis(Y_AXIS),
if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS),
if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS),
if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS),
if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS)
);
//
@@ -1707,7 +1707,7 @@ float Planner::triggered_position_mm(const AxisEnum axis) {
void Planner::finish_and_disable() {
while (has_blocks_queued() || cleaning_buffer_counter) idle();
disable_all_steppers();
stepper.disable_all_steppers();
}
/**
@@ -2144,7 +2144,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->e_to_p_pressure = baricuda_e_to_p_pressure;
#endif
TERN_(HAS_MULTI_EXTRUDER, block->extruder = extruder);
E_TERN_(block->extruder = extruder);
#if ENABLED(AUTO_POWER_CONTROL)
if (LINEAR_AXIS_GANG(
@@ -2160,43 +2160,43 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Enable active axes
#if EITHER(CORE_IS_XY, MARKFORGED_XY)
if (block->steps.a || block->steps.b) {
ENABLE_AXIS_X();
ENABLE_AXIS_Y();
stepper.enable_axis(X_AXIS);
stepper.enable_axis(Y_AXIS);
}
#if DISABLED(Z_LATE_ENABLE)
if (block->steps.z) ENABLE_AXIS_Z();
if (block->steps.z) stepper.enable_axis(Z_AXIS);
#endif
#elif CORE_IS_XZ
if (block->steps.a || block->steps.c) {
ENABLE_AXIS_X();
ENABLE_AXIS_Z();
stepper.enable_axis(X_AXIS);
stepper.enable_axis(Z_AXIS);
}
if (block->steps.y) ENABLE_AXIS_Y();
if (block->steps.y) stepper.enable_axis(Y_AXIS);
#elif CORE_IS_YZ
if (block->steps.b || block->steps.c) {
ENABLE_AXIS_Y();
ENABLE_AXIS_Z();
stepper.enable_axis(Y_AXIS);
stepper.enable_axis(Z_AXIS);
}
if (block->steps.x) ENABLE_AXIS_X();
if (block->steps.x) stepper.enable_axis(X_AXIS);
#else
LINEAR_AXIS_CODE(
if (block->steps.x) ENABLE_AXIS_X(),
if (block->steps.y) ENABLE_AXIS_Y(),
if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) ENABLE_AXIS_Z(),
if (block->steps.i) ENABLE_AXIS_I(),
if (block->steps.j) ENABLE_AXIS_J(),
if (block->steps.k) ENABLE_AXIS_K()
if (block->steps.x) stepper.enable_axis(X_AXIS),
if (block->steps.y) stepper.enable_axis(Y_AXIS),
if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) stepper.enable_axis(Z_AXIS),
if (block->steps.i) stepper.enable_axis(I_AXIS),
if (block->steps.j) stepper.enable_axis(J_AXIS),
if (block->steps.k) stepper.enable_axis(K_AXIS)
);
#endif
#if EITHER(IS_CORE, MARKFORGED_XY)
#if LINEAR_AXES >= 4
if (block->steps.i) ENABLE_AXIS_I();
if (block->steps.i) stepper.enable_axis(I_AXIS);
#endif
#if LINEAR_AXES >= 5
if (block->steps.j) ENABLE_AXIS_J();
if (block->steps.j) stepper.enable_axis(J_AXIS);
#endif
#if LINEAR_AXES >= 6
if (block->steps.k) ENABLE_AXIS_K();
if (block->steps.k) stepper.enable_axis(K_AXIS);
#endif
#endif
@@ -2214,27 +2214,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#define ENABLE_ONE_E(N) do{ \
if (E_STEPPER_INDEX(extruder) == N) { \
ENABLE_AXIS_E##N(); \
stepper.ENABLE_EXTRUDER(N); \
g_uc_extruder_last_move[N] = (BLOCK_BUFFER_SIZE) * 2; \
if ((N) == 0 && TERN0(HAS_DUPLICATION_MODE, extruder_duplication_enabled)) \
ENABLE_AXIS_E1(); \
stepper.ENABLE_EXTRUDER(1); \
} \
else if (!g_uc_extruder_last_move[N]) { \
DISABLE_AXIS_E##N(); \
stepper.DISABLE_EXTRUDER(N); \
if ((N) == 0 && TERN0(HAS_DUPLICATION_MODE, extruder_duplication_enabled)) \
DISABLE_AXIS_E1(); \
stepper.DISABLE_EXTRUDER(1); \
} \
}while(0);
#else
#define ENABLE_ONE_E(N) ENABLE_AXIS_E##N();
#define ENABLE_ONE_E(N) stepper.ENABLE_EXTRUDER(N);
#endif
REPEAT(E_STEPPERS, ENABLE_ONE_E); // (ENABLE_ONE_E must end with semicolon)
}
#endif // EXTRUDERS
#endif // HAS_EXTRUDERS
if (esteps)
NOLESS(fr_mm_s, settings.min_feedrate_mm_s);
@@ -3049,7 +3049,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons
FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i];
#endif
TERN_(HAS_MULTI_EXTRUDER, block->extruder = extruder);
E_TERN_(block->extruder = extruder);
block->page_idx = page_idx;
@@ -3085,7 +3085,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons
// Move buffer head
block_buffer_head = next_buffer_head;
enable_all_steppers();
stepper.enable_all_steppers();
stepper.wake_up();
}

View File

@@ -251,17 +251,17 @@ xyz_pos_t Probe::offset; // Initialized by settings.load()
void Probe::set_probing_paused(const bool dopause) {
TERN_(PROBING_HEATERS_OFF, thermalManager.pause_heaters(dopause));
TERN_(PROBING_FANS_OFF, thermalManager.set_fans_paused(dopause));
TERN_(PROBING_ESTEPPERS_OFF, if (dopause) disable_e_steppers());
TERN_(PROBING_ESTEPPERS_OFF, if (dopause) stepper.disable_e_steppers());
#if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA)
static uint8_t old_trusted;
if (dopause) {
old_trusted = axis_trusted;
DISABLE_AXIS_X();
DISABLE_AXIS_Y();
stepper.disable_axis(X_AXIS);
stepper.disable_axis(Y_AXIS);
}
else {
if (TEST(old_trusted, X_AXIS)) ENABLE_AXIS_X();
if (TEST(old_trusted, Y_AXIS)) ENABLE_AXIS_Y();
if (TEST(old_trusted, X_AXIS)) stepper.enable_axis(X_AXIS);
if (TEST(old_trusted, Y_AXIS)) stepper.enable_axis(Y_AXIS);
axis_trusted = old_trusted;
}
#endif

View File

@@ -3278,7 +3278,7 @@ void MarlinSettings::reset() {
//
// Tool-changing Parameters
//
TERN_(HAS_MULTI_EXTRUDER, gcode.M217_report(forReplay));
E_TERN_(gcode.M217_report(forReplay));
//
// Backlash Compensation

View File

@@ -123,6 +123,10 @@ Stepper stepper; // Singleton
bool L64XX_OK_to_power_up = false; // flag to keep L64xx steppers powered down after a reset or power up
#endif
#if ENABLED(AUTO_POWER_CONTROL)
#include "../feature/power.h"
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
#include "../feature/powerloss.h"
#endif
@@ -131,6 +135,10 @@ Stepper stepper; // Singleton
#include "../feature/spindle_laser.h"
#endif
#if ENABLED(EXTENSIBLE_UI)
#include "../lcd/extui/ui_api.h"
#endif
// public:
#if EITHER(HAS_EXTRA_ENDSTOPS, Z_STEPPER_AUTO_ALIGN)
@@ -145,6 +153,8 @@ Stepper stepper; // Singleton
#endif
#endif
axis_flags_t Stepper::axis_enabled; // {0}
// private:
block_t* Stepper::current_block; // (= nullptr) A pointer to the block currently being traced
@@ -473,6 +483,89 @@ xyze_int8_t Stepper::count_direction{0};
#define DIR_WAIT_AFTER()
#endif
void Stepper::enable_axis(const AxisEnum axis) {
#define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break;
switch (axis) {
LINEAR_AXIS_CODE(
_CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z),
_CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K)
);
default: break;
}
mark_axis_enabled(axis);
}
bool Stepper::disable_axis(const AxisEnum axis) {
mark_axis_disabled(axis);
// If all the axes that share the enabled bit are disabled
const bool can_disable = can_axis_disable(axis);
if (can_disable) {
#define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break;
switch (axis) {
LINEAR_AXIS_CODE(
_CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z),
_CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K)
);
default: break;
}
}
return can_disable;
}
#if HAS_EXTRUDERS
void Stepper::enable_extruder(E_TERN_(const uint8_t eindex)) {
IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr uint8_t eindex = 0);
#define _CASE_ENA_E(N) case N: ENABLE_AXIS_E##N(); mark_axis_enabled(E_AXIS E_OPTARG(eindex)); break;
switch (eindex) {
REPEAT(E_STEPPERS, _CASE_ENA_E)
}
}
bool Stepper::disable_extruder(E_TERN_(const uint8_t eindex)) {
IF_DISABLED(HAS_MULTI_EXTRUDER, constexpr uint8_t eindex = 0);
mark_axis_disabled(E_AXIS E_OPTARG(eindex));
const bool can_disable = can_axis_disable(E_AXIS E_OPTARG(eindex));
if (can_disable) {
#define _CASE_DIS_E(N) case N: DISABLE_AXIS_E##N(); break;
switch (eindex) { REPEAT(E_STEPPERS, _CASE_DIS_E) }
}
return can_disable;
}
void Stepper::enable_e_steppers() {
#define _ENA_E(N) ENABLE_EXTRUDER(N);
REPEAT(EXTRUDERS, _ENA_E)
}
void Stepper::disable_e_steppers() {
#define _DIS_E(N) DISABLE_EXTRUDER(N);
REPEAT(EXTRUDERS, _DIS_E)
}
#endif
void Stepper::enable_all_steppers() {
TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
LINEAR_AXIS_CODE(
enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
);
enable_e_steppers();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersEnabled());
}
void Stepper::disable_all_steppers() {
LINEAR_AXIS_CODE(
disable_axis(X_AXIS), disable_axis(Y_AXIS), disable_axis(Z_AXIS),
disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS)
);
disable_e_steppers();
TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled());
}
/**
* Set the stepper direction of each axis
*
@@ -494,24 +587,12 @@ void Stepper::set_directions() {
count_direction[_AXIS(A)] = 1; \
}
#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
#if HAS_I_DIR
SET_STEP_DIR(I);
#endif
#if HAS_J_DIR
SET_STEP_DIR(J);
#endif
#if HAS_K_DIR
SET_STEP_DIR(K);
#endif
TERN_(HAS_X_DIR, SET_STEP_DIR(X)); // A
TERN_(HAS_Y_DIR, SET_STEP_DIR(Y)); // B
TERN_(HAS_Z_DIR, SET_STEP_DIR(Z)); // C
TERN_(HAS_I_DIR, SET_STEP_DIR(I));
TERN_(HAS_J_DIR, SET_STEP_DIR(J));
TERN_(HAS_K_DIR, SET_STEP_DIR(K));
#if DISABLED(LIN_ADVANCE)
#if ENABLED(MIXING_EXTRUDER)
@@ -2204,7 +2285,7 @@ uint32_t Stepper::block_phase_isr() {
TERN_(MIXING_EXTRUDER, mixer.stepper_setup(current_block->b_color));
TERN_(HAS_MULTI_EXTRUDER, stepper_extruder = current_block->extruder);
E_TERN_(stepper_extruder = current_block->extruder);
// Initialize the trapezoid generator from the current block.
#if ENABLED(LIN_ADVANCE)
@@ -2227,7 +2308,7 @@ uint32_t Stepper::block_phase_isr() {
|| current_block->direction_bits != last_direction_bits
|| TERN(MIXING_EXTRUDER, false, stepper_extruder != last_moved_extruder)
) {
TERN_(HAS_MULTI_EXTRUDER, last_moved_extruder = stepper_extruder);
E_TERN_(last_moved_extruder = stepper_extruder);
TERN_(HAS_L64XX, L64XX_OK_to_power_up = true);
set_directions(current_block->direction_bits);
}
@@ -2276,7 +2357,7 @@ uint32_t Stepper::block_phase_isr() {
// If delayed Z enable, enable it now. This option will severely interfere with
// timing between pulses when chaining motion between blocks, and it could lead
// to lost steps in both X and Y axis, so avoid using it unless strictly necessary!!
if (current_block->steps.z) ENABLE_AXIS_Z();
if (current_block->steps.z) enable_axis(Z_AXIS);
#endif
// Mark the time_nominal as not calculated yet
@@ -2872,7 +2953,7 @@ void Stepper::report_positions() {
#if ENABLED(BABYSTEPPING)
#define _ENABLE_AXIS(AXIS) ENABLE_AXIS_## AXIS()
#define _ENABLE_AXIS(A) enable_axis(_AXIS(A))
#define _READ_DIR(AXIS) AXIS ##_DIR_READ()
#define _INVERT_DIR(AXIS) INVERT_## AXIS ##_DIR
#define _APPLY_DIR(AXIS, INVERT) AXIS ##_APPLY_DIR(INVERT, true)
@@ -3000,8 +3081,10 @@ void Stepper::report_positions() {
const bool z_direction = direction ^ BABYSTEP_INVERT_Z;
ENABLE_AXIS_X(); ENABLE_AXIS_Y(); ENABLE_AXIS_Z();
ENABLE_AXIS_I(); ENABLE_AXIS_J(); ENABLE_AXIS_K();
LINEAR_AXIS_CODE(
enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS),
enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS)
);
DIR_WAIT_BEFORE();

View File

@@ -236,6 +236,71 @@
// Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING.
#define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2)
#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS)
typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t;
// Axis flags type, for enabled state or other simple state
typedef struct {
union {
ena_mask_t bits;
struct {
bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1);
#if HAS_EXTRUDERS
bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1);
#endif
};
};
constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; }
constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; }
} axis_flags_t;
// All the stepper enable pins
constexpr pin_t ena_pins[] = {
LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN),
LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN)
};
// Index of the axis or extruder element in a combined array
constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex));
}
//#define __IAX_N(N,V...) _IAX_##N(V)
//#define _IAX_N(N,V...) __IAX_N(N,V)
//#define _IAX_1(A) index_of_axis(A)
//#define _IAX_2(A,B) index_of_axis(A E_OPTARG(B))
//#define INDEX_OF_AXIS(V...) _IAX_N(TWO_ARGS(V),V)
#define INDEX_OF_AXIS(A,V...) index_of_axis(A E_OPTARG(V+0))
// Bit mask for a matching enable pin, or 0
constexpr ena_mask_t ena_same(const uint8_t a, const uint8_t b) {
return ena_pins[a] == ena_pins[b] ? _BV(b) : 0;
}
// Recursively get the enable overlaps mask for a given linear axis or extruder
constexpr ena_mask_t ena_overlap(const uint8_t a=0, const uint8_t b=0) {
return b >= ENABLE_COUNT ? 0 : (a == b ? 0 : ena_same(a, b)) | ena_overlap(a, b + 1);
}
// Recursively get whether there's any overlap at all
constexpr bool any_enable_overlap(const uint8_t a=0) {
return a >= ENABLE_COUNT ? false : ena_overlap(a) || any_enable_overlap(a + 1);
}
// Array of axes that overlap with each
// TODO: Consider cases where >=2 steppers are used by a linear axis or extruder
// (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.).
constexpr ena_mask_t enable_overlap[] = {
#define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))),
REPEAT(LINEAR_AXES, _OVERLAP)
#if HAS_EXTRUDERS
#define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)),
REPEAT(E_STEPPERS, _E_OVERLAP)
#endif
};
//static_assert(!any_enable_overlap(), "There is some overlap.");
//
// Stepper class definition
//
@@ -519,6 +584,43 @@ class Stepper {
static void refresh_motor_power();
#endif
static axis_flags_t axis_enabled; // Axis stepper(s) ENABLED states
static inline bool axis_is_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
return TEST(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
}
static inline void mark_axis_enabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
SBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
}
static inline void mark_axis_disabled(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
CBI(axis_enabled.bits, INDEX_OF_AXIS(axis, eindex));
}
static inline bool can_axis_disable(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) {
return !any_enable_overlap() || !(axis_enabled.bits & enable_overlap[INDEX_OF_AXIS(axis, eindex)]);
}
static void enable_axis(const AxisEnum axis);
static bool disable_axis(const AxisEnum axis);
#if HAS_EXTRUDERS
static void enable_extruder(E_TERN_(const uint8_t eindex=0));
static bool disable_extruder(E_TERN_(const uint8_t eindex=0));
static void enable_e_steppers();
static void disable_e_steppers();
#else
static inline void enable_extruder() {}
static inline bool disable_extruder() {}
static inline void enable_e_steppers() {}
static inline void disable_e_steppers() {}
#endif
#define ENABLE_EXTRUDER(N) enable_extruder(E_TERN_(N))
#define DISABLE_EXTRUDER(N) disable_extruder(E_TERN_(N))
#define AXIS_IS_ENABLED(N,V...) axis_is_enabled(N E_OPTARG(#V))
static void enable_all_steppers();
static void disable_all_steppers();
// Update direction states for all steppers
static void set_directions();