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

Stepper DIR rework #25761

Merged
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
152 changes: 150 additions & 2 deletions Marlin/src/core/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,6 @@ enum AxisEnum : uint8_t {
, ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
};

typedef bits_t(NUM_AXIS_ENUMS) axis_bits_t;

//
// Loop over axes
//
Expand Down Expand Up @@ -789,6 +787,156 @@ struct XYZEval {
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
};

#include <string.h> // for memset

class AxisBits;

class AxisBits {
public:
typedef bits_t(NUM_AXIS_ENUMS) el;
union {
el bits;
struct {
union {
bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1);
bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1);
bool NUM_AXIS_LIST(a:1, b:1, c:1, _i:1, _j:1, _k:1, _u:1, _v:1, _w:1);
bool NUM_AXIS_LIST(A:1, B:1, C:1, _I:1, _J:1, _K:1, _U:1, _V:1, _W:1);
};
#if HAS_EXTRUDERS
union { bool e:1; bool e0:1; };
#define _EN_ITEM(N) bool e##N:1;
REPEAT_S(1,EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM
#endif
#if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool hx:1, hy:1, hz:1;
#endif
};
};

AxisBits() { bits = 0; }

// Constructor, setter, and operator= for bit mask
AxisBits(const el p) { set(p); }
void set(const el p) { bits = el(p); }
FI AxisBits& operator=(const el p) { set(p); return *this; }

#define MSET(pE,pX,pY,pZ,pI,pJ,pK,pU,pV,pW) LOGICAL_AXIS_CODE(e=pE, x=pX, y=pY, z=pZ, i=pI, j=pJ, k=pK, u=pU, v=pV, w=pW)

// Constructor, setter, and operator= for XYZE type
AxisBits(const xyze_bool_t &p) { set(p); }
void set(const xyze_bool_t &p) {
MSET(p.e, p.x, p.y, p.z, p.i, p.j, p.k, p.u, p.v, p.w);
}
FI AxisBits& operator=(const xyze_bool_t &p) { set(p); return *this; }

// Constructor, setter, and operator= for bool array
AxisBits(const bool (&p)[LOGICAL_AXES]) { set(p); }
void set(const bool (&p)[LOGICAL_AXES]) {
MSET(p[E_AXIS], p[X_AXIS], p[Y_AXIS], p[Z_AXIS],
p[I_AXIS], p[J_AXIS], p[K_AXIS],
p[U_AXIS], p[V_AXIS], p[W_AXIS]);
}
FI AxisBits& operator=(const bool (&p)[LOGICAL_AXES]) { set(p); return *this; }

// Constructor, setter, and operator= for undersized bool arrays
#if LOGICAL_AXES > 1
AxisBits(const bool (&p)[1]) { set(p); }
FI void set(const bool (&p)[1]) {
MSET(0, p[X_AXIS], 0, 0, 0, 0, 0, 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[1]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 2
AxisBits(const bool (&p)[2]) { set(p); }
FI void set(const bool (&p)[2]) {
MSET(0, p[X_AXIS], p[Y_AXIS], 0, 0, 0, 0, 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[2]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 3
AxisBits(const bool (&p)[3]) { set(p); }
FI void set(const bool (&p)[3]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], 0, 0, 0, 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[3]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 4
AxisBits(const bool (&p)[4]) { set(p); }
FI void set(const bool (&p)[4]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], 0, 0, 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[4]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 5
AxisBits(const bool (&p)[5]) { set(p); }
FI void set(const bool (&p)[5]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], p[J_AXIS], 0, 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[5]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 6
AxisBits(const bool (&p)[6]) { set(p); }
FI void set(const bool (&p)[6]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], p[J_AXIS], p[K_AXIS], 0, 0, 0);
}
FI AxisBits& operator=(const bool (&p)[6]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 7
AxisBits(const bool (&p)[7]) { set(p); }
FI void set(const bool (&p)[7]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], p[J_AXIS], p[K_AXIS], p[U_AXIS], 0, 0);
}
FI AxisBits& operator=(const bool (&p)[7]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 8
AxisBits(const bool (&p)[8]) { set(p); }
FI void set(const bool (&p)[8]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], p[J_AXIS], p[K_AXIS], p[U_AXIS], p[V_AXIS], 0);
}
FI AxisBits& operator=(const bool (&p)[8]) { set(p); return *this; }
#endif
#if LOGICAL_AXES > 9
AxisBits(const bool (&p)[9]) { set(p); }
FI void set(const bool (&p)[9]) {
MSET(0, p[X_AXIS], p[Y_AXIS], p[Z_AXIS], p[I_AXIS], p[J_AXIS], p[K_AXIS], p[U_AXIS], p[V_AXIS], p[W_AXIS]);
}
FI AxisBits& operator=(const bool (&p)[9]) { set(p); return *this; }
#endif
#undef MSET

FI const bool toggle(const AxisEnum n) { return TBI(bits, n); }

// Accessor via an AxisEnum (or any integer) [index]
FI const bool operator[](const int n) const { return TEST(bits, n); }
FI const bool operator[](const AxisEnum n) const { return TEST(bits, n); }

FI AxisBits& operator|=(const el &p) { bits |= el(p); return *this; }
FI AxisBits& operator&=(const el &p) { bits &= el(p); return *this; }
FI AxisBits& operator^=(const el &p) { bits ^= el(p); return *this; }

FI AxisBits& operator|=(const AxisBits &p) { bits |= p.bits; return *this; }
FI AxisBits& operator&=(const AxisBits &p) { bits &= p.bits; return *this; }
FI AxisBits& operator^=(const AxisBits &p) { bits ^= p.bits; return *this; }

FI bool operator==(const AxisBits &p) const { return p.bits == bits; }
FI bool operator!=(const AxisBits &p) const { return p.bits != bits; }

FI el operator|(const el &p) const { return bits | el(p); }
FI el operator&(const el &p) const { return bits & el(p); }
FI el operator^(const el &p) const { return bits ^ el(p); }

FI AxisBits operator|(const AxisBits &p) const { return AxisBits(bits | p.bits); }
FI AxisBits operator&(const AxisBits &p) const { return AxisBits(bits & p.bits); }
FI AxisBits operator^(const AxisBits &p) const { return AxisBits(bits ^ p.bits); }

FI operator bool() const { return !!bits; }
FI operator uint16_t() const { return uint16_t(bits & 0xFFFF); }
FI operator uint32_t() const { return uint32_t(bits); }

};

#undef _RECIP
#undef _ABS
#undef _LS
Expand Down
36 changes: 18 additions & 18 deletions Marlin/src/feature/backlash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "../module/motion.h"
#include "../module/planner.h"

axis_bits_t Backlash::last_direction_bits;
AxisBits Backlash::last_direction_bits;
xyz_long_t Backlash::residual_error{0};

#ifdef BACKLASH_DISTANCE_MM
Expand Down Expand Up @@ -63,25 +63,25 @@ Backlash backlash;
* spread over multiple segments, smoothing out artifacts even more.
*/

void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block) {
axis_bits_t changed_dir = last_direction_bits ^ dm;
void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block) {
AxisBits changed_dir = last_direction_bits ^ dm;
// Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX)
if (!da) CBI(changed_dir, X_AXIS);
if (!db) CBI(changed_dir, Y_AXIS);
if (!dc) CBI(changed_dir, Z_AXIS);
if (!da) changed_dir.x = false;
if (!db) changed_dir.y = false;
if (!dc) changed_dir.z = false;
#elif CORE_IS_XY
if (!(da + db)) CBI(changed_dir, X_AXIS);
if (!(da - db)) CBI(changed_dir, Y_AXIS);
if (!dc) CBI(changed_dir, Z_AXIS);
if (!(da + db)) changed_dir.x = false;
if (!(da - db)) changed_dir.y = false;
if (!dc) changed_dir.z = false;
#elif CORE_IS_XZ
if (!(da + dc)) CBI(changed_dir, X_AXIS);
if (!(da - dc)) CBI(changed_dir, Z_AXIS);
if (!db) CBI(changed_dir, Y_AXIS);
if (!(da + dc)) changed_dir.x = false;
if (!(da - dc)) changed_dir.z = false;
if (!db) changed_dir.y = false;
#elif CORE_IS_YZ
if (!(db + dc)) CBI(changed_dir, Y_AXIS);
if (!(db - dc)) CBI(changed_dir, Z_AXIS);
if (!da) CBI(changed_dir, X_AXIS);
if (!(db + dc)) changed_dir.y = false;
if (!(db - dc)) changed_dir.z = false;
if (!da) changed_dir.x = false;
#endif
last_direction_bits ^= changed_dir;

Expand All @@ -99,10 +99,10 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const

LOOP_NUM_AXES(axis) {
if (distance_mm[axis]) {
const bool reverse = TEST(dm, axis);
const bool reverse = dm[axis];

// When an axis changes direction, add axis backlash to the residual error
if (TEST(changed_dir, axis))
if (changed_dir[axis])
residual_error[axis] += (reverse ? -f_corr : f_corr) * distance_mm[axis] * planner.settings.axis_steps_per_mm[axis];

// Decide how much of the residual error to correct in this segment
Expand Down Expand Up @@ -147,7 +147,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
int32_t Backlash::get_applied_steps(const AxisEnum axis) {
if (axis >= NUM_AXES) return 0;

const bool reverse = TEST(last_direction_bits, axis);
const bool reverse = last_direction_bits[axis];

const int32_t residual_error_axis = residual_error[axis];

Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/feature/backlash.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Backlash {
static constexpr uint8_t all_on = 0xFF, all_off = 0x00;

private:
static axis_bits_t last_direction_bits;
static AxisBits last_direction_bits;
static xyz_long_t residual_error;

#if ENABLED(BACKLASH_GCODE)
Expand Down Expand Up @@ -72,7 +72,7 @@ class Backlash {
return has_measurement(X_AXIS) || has_measurement(Y_AXIS) || has_measurement(Z_AXIS);
}

static void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const axis_bits_t dm, block_t * const block);
static void add_correction_steps(const int32_t &da, const int32_t &db, const int32_t &dc, const AxisBits dm, block_t * const block);
static int32_t get_applied_steps(const AxisEnum axis);

#if ENABLED(BACKLASH_GCODE)
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/feature/runout.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ class FilamentSensorBase {
// Only trigger on extrusion with XYZ movement to allow filament change and retract/recover.
const uint8_t e = b->extruder;
const int32_t steps = b->steps.e;
const float mm = (TEST(b->direction_bits, E_AXIS) ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)];
const float mm = (b->direction_bits.e ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)];
if (e < NUM_RUNOUT_SENSORS) mm_countdown.runout[e] -= mm;
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) mm_countdown.motion[e] -= mm;
Expand Down
10 changes: 5 additions & 5 deletions Marlin/src/module/ft_motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,33 +484,33 @@ void FxdTiCtrl::loadBlockData(block_t * const current_block) {
const float totalLength = current_block->millimeters,
oneOverLength = 1.0f / totalLength;

const axis_bits_t direction = current_block->direction_bits;
const AxisBits direction = current_block->direction_bits;

#if HAS_X_AXIS
x_startPosn = x_endPosn_prevBlock;
float x_moveDist = current_block->steps.a / planner.settings.axis_steps_per_mm[X_AXIS];
if (TEST(direction, X_AXIS)) x_moveDist *= -1.0f;
if (direction.x) x_moveDist *= -1.0f;
x_Ratio = x_moveDist * oneOverLength;
#endif

#if HAS_Y_AXIS
y_startPosn = y_endPosn_prevBlock;
float y_moveDist = current_block->steps.b / planner.settings.axis_steps_per_mm[Y_AXIS];
if (TEST(direction, Y_AXIS)) y_moveDist *= -1.0f;
if (direction.y) y_moveDist *= -1.0f;
y_Ratio = y_moveDist * oneOverLength;
#endif

#if HAS_Z_AXIS
z_startPosn = z_endPosn_prevBlock;
float z_moveDist = current_block->steps.c / planner.settings.axis_steps_per_mm[Z_AXIS];
if (TEST(direction, Z_AXIS)) z_moveDist *= -1.0f;
if (direction.z) z_moveDist *= -1.0f;
z_Ratio = z_moveDist * oneOverLength;
#endif

#if HAS_EXTRUDERS
e_startPosn = e_endPosn_prevBlock;
float extrusion = current_block->steps.e / planner.settings.axis_steps_per_mm[E_AXIS_N(current_block->extruder)];
if (TEST(direction, E_AXIS_N(current_block->extruder))) extrusion *= -1.0f;
if (direction.e) extrusion *= -1.0f;
e_Ratio = extrusion * oneOverLength;
#endif

Expand Down
60 changes: 28 additions & 32 deletions Marlin/src/module/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1968,54 +1968,50 @@ bool Planner::_populate_block(
#endif // PREVENT_COLD_EXTRUSION || PREVENT_LENGTHY_EXTRUDE

// Compute direction bit-mask for this block
axis_bits_t dm = 0;
AxisBits dm;
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
if (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X
if (db < 0) SBI(dm, Y_HEAD); // ...and Y
TERN_(HAS_Z_AXIS, if (dc < 0) SBI(dm, Z_AXIS));
dm.hx = (da < 0); // Save the toolhead's true direction in X
dm.hy = (db < 0); // ...and Y
TERN_(HAS_Z_AXIS, dm.z = (dc < 0));
#endif
#if IS_CORE
#if CORE_IS_XY
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (CORESIGN(da - db) < 0) SBI(dm, B_AXIS); // Motor B direction
dm.a = (da + db < 0); // Motor A direction
dm.b = (CORESIGN(da - db) < 0); // Motor B direction
#elif CORE_IS_XZ
if (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X
if (db < 0) SBI(dm, Y_AXIS);
if (dc < 0) SBI(dm, Z_HEAD); // ...and Z
if (da + dc < 0) SBI(dm, A_AXIS); // Motor A direction
if (CORESIGN(da - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
dm.hx = (da < 0); // Save the toolhead's true direction in X
dm.y = (db < 0);
dm.hz = (dc < 0); // ...and Z
dm.a = (da + dc < 0); // Motor A direction
dm.c = (CORESIGN(da - dc) < 0); // Motor C direction
#elif CORE_IS_YZ
if (da < 0) SBI(dm, X_AXIS);
if (db < 0) SBI(dm, Y_HEAD); // Save the toolhead's true direction in Y
if (dc < 0) SBI(dm, Z_HEAD); // ...and Z
if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction
if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
dm.x = (da < 0);
dm.hy = (db < 0); // Save the toolhead's true direction in Y
dm.hz = (dc < 0); // ...and Z
dm.b = (db + dc < 0); // Motor B direction
dm.c = (CORESIGN(db - dc) < 0); // Motor C direction
#endif
#elif ENABLED(MARKFORGED_XY)
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, B_AXIS); // Motor B direction
dm.a = (da + db < 0); // Motor A direction
dm.b = (db < 0); // Motor B direction
#elif ENABLED(MARKFORGED_YX)
if (da < 0) SBI(dm, A_AXIS); // Motor A direction
if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction
dm.a = (da < 0); // Motor A direction
dm.b = (db + da < 0); // Motor B direction
#else
XYZ_CODE(
if (da < 0) SBI(dm, X_AXIS),
if (db < 0) SBI(dm, Y_AXIS),
if (dc < 0) SBI(dm, Z_AXIS)
dm.x = (da < 0),
dm.y = (db < 0),
dm.z = (dc < 0)
);
#endif

SECONDARY_AXIS_CODE(
if (di < 0) SBI(dm, I_AXIS),
if (dj < 0) SBI(dm, J_AXIS),
if (dk < 0) SBI(dm, K_AXIS),
if (du < 0) SBI(dm, U_AXIS),
if (dv < 0) SBI(dm, V_AXIS),
if (dw < 0) SBI(dm, W_AXIS)
dm.i = (di < 0), dm.j = (dj < 0), dm.k = (dk < 0),
dm.u = (du < 0), dm.v = (dv < 0), dm.w = (dw < 0)
);

#if HAS_EXTRUDERS
if (de < 0) SBI(dm, E_AXIS);
dm.e = (de < 0);
const float esteps_float = de * e_factor[extruder];
const uint32_t esteps = ABS(esteps_float) + 0.5f;
#else
Expand Down Expand Up @@ -2435,11 +2431,11 @@ bool Planner::_populate_block(

#ifdef XY_FREQUENCY_LIMIT

static axis_bits_t old_direction_bits; // = 0
static AxisBits old_direction_bits; // = 0

if (xy_freq_limit_hz) {
// Check and limit the xy direction change frequency
const axis_bits_t direction_change = block->direction_bits ^ old_direction_bits;
const AxisBits direction_change = block->direction_bits ^ old_direction_bits;
old_direction_bits = block->direction_bits;
segment_time_us = LROUND(float(segment_time_us) / speed_factor);

Expand Down
Loading