MarkForged YX kinematics (#23163)

x301
John Robertson 3 years ago committed by Scott Lahteine
parent 018c7b1cf4
commit 0e60c8b7e0

@ -756,6 +756,7 @@
//#define COREZX //#define COREZX
//#define COREZY //#define COREZY
//#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042 //#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042
//#define MARKFORGED_YX
// Enable for a belt style printer with endless "Z" motion // Enable for a belt style printer with endless "Z" motion
//#define BELTPRINTER //#define BELTPRINTER

@ -82,7 +82,7 @@ enum AxisEnum : uint8_t {
#undef _EN_ITEM #undef _EN_ITEM
// Core also keeps toolhead directions // Core also keeps toolhead directions
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
, X_HEAD, Y_HEAD, Z_HEAD , X_HEAD, Y_HEAD, Z_HEAD
#endif #endif

@ -60,7 +60,8 @@ void safe_delay(millis_t ms) {
TERN_(DELTA, "Delta") TERN_(DELTA, "Delta")
TERN_(IS_SCARA, "SCARA") TERN_(IS_SCARA, "SCARA")
TERN_(IS_CORE, "Core") TERN_(IS_CORE, "Core")
TERN_(MARKFORGED_XY, "MarkForged") TERN_(MARKFORGED_XY, "MarkForgedXY")
TERN_(MARKFORGED_YX, "MarkForgedYX")
TERN_(IS_CARTESIAN, "Cartesian") TERN_(IS_CARTESIAN, "Cartesian")
); );

@ -64,7 +64,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const
static axis_bits_t last_direction_bits; static axis_bits_t last_direction_bits;
axis_bits_t changed_dir = last_direction_bits ^ dm; axis_bits_t changed_dir = last_direction_bits ^ dm;
// Ignore direction change unless steps are taken in that direction // Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || ENABLED(MARKFORGED_XY) #if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX)
if (!da) CBI(changed_dir, X_AXIS); if (!da) CBI(changed_dir, X_AXIS);
if (!db) CBI(changed_dir, Y_AXIS); if (!db) CBI(changed_dir, Y_AXIS);
if (!dc) CBI(changed_dir, Z_AXIS); if (!dc) CBI(changed_dir, Z_AXIS);

@ -162,7 +162,8 @@ void GcodeSuite::M360() {
TERN_(DELTA, "Delta") TERN_(DELTA, "Delta")
TERN_(IS_SCARA, "SCARA") TERN_(IS_SCARA, "SCARA")
TERN_(IS_CORE, "Core") TERN_(IS_CORE, "Core")
TERN_(MARKFORGED_XY, "MarkForged") TERN_(MARKFORGED_XY, "MarkForgedXY")
TERN_(MARKFORGED_YX, "MarkForgedYX")
TERN_(IS_CARTESIAN, "Cartesian") TERN_(IS_CARTESIAN, "Cartesian")
); );

@ -1079,7 +1079,7 @@
#define CORE_AXIS_2 C_AXIS #define CORE_AXIS_2 C_AXIS
#endif #endif
#define CORESIGN(n) (ANY(COREYX, COREZX, COREZY) ? (-(n)) : (n)) #define CORESIGN(n) (ANY(COREYX, COREZX, COREZY) ? (-(n)) : (n))
#elif ENABLED(MARKFORGED_XY) #elif EITHER(MARKFORGED_XY, MARKFORGED_YX)
// Markforged kinematics // Markforged kinematics
#define CORE_AXIS_1 A_AXIS #define CORE_AXIS_1 A_AXIS
#define CORE_AXIS_2 B_AXIS #define CORE_AXIS_2 B_AXIS

@ -193,7 +193,7 @@
// Calibration codes only for non-core axes // Calibration codes only for non-core axes
#if EITHER(BACKLASH_GCODE, CALIBRATION_GCODE) #if EITHER(BACKLASH_GCODE, CALIBRATION_GCODE)
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
#define CAN_CALIBRATE(A,B) (_AXIS(A) == B) #define CAN_CALIBRATE(A,B) (_AXIS(A) == B)
#else #else
#define CAN_CALIBRATE(A,B) true #define CAN_CALIBRATE(A,B) true

@ -914,7 +914,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#if ENABLED(BABYSTEPPING) #if ENABLED(BABYSTEPPING)
#if ENABLED(SCARA) #if ENABLED(SCARA)
#error "BABYSTEPPING is not implemented for SCARA yet." #error "BABYSTEPPING is not implemented for SCARA yet."
#elif BOTH(MARKFORGED_XY, BABYSTEP_XY) #elif ENABLED(BABYSTEP_XY) && EITHER(MARKFORGED_XY, MARKFORGED_YX)
#error "BABYSTEPPING only implemented for Z axis on MarkForged." #error "BABYSTEPPING only implemented for Z axis on MarkForged."
#elif BOTH(DELTA, BABYSTEP_XY) #elif BOTH(DELTA, BABYSTEP_XY)
#error "BABYSTEPPING only implemented for Z axis on deltabots." #error "BABYSTEPPING only implemented for Z axis on deltabots."
@ -1461,8 +1461,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
/** /**
* Allow only one kinematic type to be defined * Allow only one kinematic type to be defined
*/ */
#if MANY(DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, FOAMCUTTER_XYUV) #if MANY(DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, FOAMCUTTER_XYUV)
#error "Please enable only one of DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, or FOAMCUTTER_XYUV." #error "Please enable only one of DELTA, MORGAN_SCARA, MP_SCARA, AXEL_TPARA, COREXY, COREXZ, COREYZ, COREYX, COREZX, COREZY, MARKFORGED_XY, MARKFORGED_YX, or FOAMCUTTER_XYUV."
#endif #endif
/** /**
@ -1960,8 +1960,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
#if EXTRUDERS < 2 #if EXTRUDERS < 2
#error "DUAL_X_CARRIAGE requires 2 (or more) extruders." #error "DUAL_X_CARRIAGE requires 2 (or more) extruders."
#elif ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY) #elif ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX)
#error "DUAL_X_CARRIAGE cannot be used with COREXY, COREYX, COREXZ, COREZX, or MARKFORGED_XY." #error "DUAL_X_CARRIAGE cannot be used with COREXY, COREYX, COREXZ, COREZX, MARKFORGED_YX, or MARKFORGED_XY."
#elif !GOOD_AXIS_PINS(X2) #elif !GOOD_AXIS_PINS(X2)
#error "DUAL_X_CARRIAGE requires X2 stepper pins to be defined." #error "DUAL_X_CARRIAGE requires X2 stepper pins to be defined."
#elif !HAS_X_MAX #elif !HAS_X_MAX
@ -3203,8 +3203,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "CoreXZ requires both X and Z to use sensorless homing if either one does." #error "CoreXZ requires both X and Z to use sensorless homing if either one does."
#elif CORE_IS_YZ && Y_SENSORLESS != Z_SENSORLESS && !HOMING_Z_WITH_PROBE #elif CORE_IS_YZ && Y_SENSORLESS != Z_SENSORLESS && !HOMING_Z_WITH_PROBE
#error "CoreYZ requires both Y and Z to use sensorless homing if either one does." #error "CoreYZ requires both Y and Z to use sensorless homing if either one does."
#elif ENABLED(MARKFORGED_XY) && X_SENSORLESS != Y_SENSORLESS #elif EITHER(MARKFORGED_XY, MARKFORGED_YX) && X_SENSORLESS != Y_SENSORLESS
#error "MARKFORGED_XY requires both X and Y to use sensorless homing if either one does." #error "MARKFORGED requires both X and Y to use sensorless homing if either one does."
#endif #endif
// Other TMC feature requirements // Other TMC feature requirements
@ -3464,7 +3464,7 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
#error "BACKLASH_COMPENSATION requires BACKLASH_DISTANCE_MM." #error "BACKLASH_COMPENSATION requires BACKLASH_DISTANCE_MM."
#elif !defined(BACKLASH_CORRECTION) #elif !defined(BACKLASH_CORRECTION)
#error "BACKLASH_COMPENSATION requires BACKLASH_CORRECTION." #error "BACKLASH_COMPENSATION requires BACKLASH_CORRECTION."
#elif ENABLED(MARKFORGED_XY) #elif EITHER(MARKFORGED_XY, MARKFORGED_YX)
constexpr float backlash_arr[] = BACKLASH_DISTANCE_MM; constexpr float backlash_arr[] = BACKLASH_DISTANCE_MM;
static_assert(!backlash_arr[CORE_AXIS_1] && !backlash_arr[CORE_AXIS_2], static_assert(!backlash_arr[CORE_AXIS_1] && !backlash_arr[CORE_AXIS_2],
"BACKLASH_COMPENSATION can only apply to " STRINGIFY(NORMAL_AXIS) " on a MarkForged system."); "BACKLASH_COMPENSATION can only apply to " STRINGIFY(NORMAL_AXIS) " on a MarkForged system.");

@ -38,7 +38,7 @@ void menu_backlash() {
EDIT_ITEM_FAST(percent, MSG_BACKLASH_CORRECTION, &backlash.correction, all_off, all_on); EDIT_ITEM_FAST(percent, MSG_BACKLASH_CORRECTION, &backlash.correction, all_off, all_on);
#if DISABLED(CORE_BACKLASH) || ENABLED(MARKFORGED_XY) #if DISABLED(CORE_BACKLASH) || EITHER(MARKFORGED_XY, MARKFORGED_YX)
#define _CAN_CALI AXIS_CAN_CALIBRATE #define _CAN_CALI AXIS_CAN_CALIBRATE
#else #else
#define _CAN_CALI(A) true #define _CAN_CALI(A) true

@ -617,7 +617,7 @@ void Endstops::update() {
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX))) #define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
#define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT)) #define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
#if ENABLED(G38_PROBE_TARGET) && NONE(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY) #if ENABLED(G38_PROBE_TARGET) && NONE(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_XY)
#define HAS_G38_PROBE 1 #define HAS_G38_PROBE 1
// For G38 moves check the probe's pin for ALL movement // For G38 moves check the probe's pin for ALL movement
if (G38_move) UPDATE_ENDSTOP_BIT(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN)); if (G38_move) UPDATE_ENDSTOP_BIT(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN));
@ -628,12 +628,12 @@ void Endstops::update() {
#define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, TERN0(X_HOME_TO_MAX, stepper.last_moved_extruder == 0) || TERN0(X2_HOME_TO_MAX, stepper.last_moved_extruder != 0)) #define X_MAX_TEST() TERN1(DUAL_X_CARRIAGE, TERN0(X_HOME_TO_MAX, stepper.last_moved_extruder == 0) || TERN0(X2_HOME_TO_MAX, stepper.last_moved_extruder != 0))
// Use HEAD for core axes, AXIS for others // Use HEAD for core axes, AXIS for others
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY) #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_XY)
#define X_AXIS_HEAD X_HEAD #define X_AXIS_HEAD X_HEAD
#else #else
#define X_AXIS_HEAD X_AXIS #define X_AXIS_HEAD X_AXIS
#endif #endif
#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY) #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX)
#define Y_AXIS_HEAD Y_HEAD #define Y_AXIS_HEAD Y_HEAD
#else #else
#define Y_AXIS_HEAD Y_AXIS #define Y_AXIS_HEAD Y_AXIS
@ -1111,7 +1111,7 @@ void Endstops::update() {
bool hit = false; bool hit = false;
#if X_SPI_SENSORLESS #if X_SPI_SENSORLESS
if (tmc_spi_homing.x && (stepperX.test_stall_status() if (tmc_spi_homing.x && (stepperX.test_stall_status()
#if ANY(CORE_IS_XY, MARKFORGED_XY) && Y_SPI_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SPI_SENSORLESS
|| stepperY.test_stall_status() || stepperY.test_stall_status()
#elif CORE_IS_XZ && Z_SPI_SENSORLESS #elif CORE_IS_XZ && Z_SPI_SENSORLESS
|| stepperZ.test_stall_status() || stepperZ.test_stall_status()
@ -1123,7 +1123,7 @@ void Endstops::update() {
#endif #endif
#if Y_SPI_SENSORLESS #if Y_SPI_SENSORLESS
if (tmc_spi_homing.y && (stepperY.test_stall_status() if (tmc_spi_homing.y && (stepperY.test_stall_status()
#if ANY(CORE_IS_XY, MARKFORGED_XY) && X_SPI_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SPI_SENSORLESS
|| stepperX.test_stall_status() || stepperX.test_stall_status()
#elif CORE_IS_YZ && Z_SPI_SENSORLESS #elif CORE_IS_YZ && Z_SPI_SENSORLESS
|| stepperZ.test_stall_status() || stepperZ.test_stall_status()

@ -1367,7 +1367,7 @@ void prepare_line_to_destination() {
#if AXIS_HAS_STALLGUARD(X2) #if AXIS_HAS_STALLGUARD(X2)
stealth_states.x2 = tmc_enable_stallguard(stepperX2); stealth_states.x2 = tmc_enable_stallguard(stepperX2);
#endif #endif
#if EITHER(CORE_IS_XY, MARKFORGED_XY) && Y_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SENSORLESS
stealth_states.y = tmc_enable_stallguard(stepperY); stealth_states.y = tmc_enable_stallguard(stepperY);
#elif CORE_IS_XZ && Z_SENSORLESS #elif CORE_IS_XZ && Z_SENSORLESS
stealth_states.z = tmc_enable_stallguard(stepperZ); stealth_states.z = tmc_enable_stallguard(stepperZ);
@ -1380,7 +1380,7 @@ void prepare_line_to_destination() {
#if AXIS_HAS_STALLGUARD(Y2) #if AXIS_HAS_STALLGUARD(Y2)
stealth_states.y2 = tmc_enable_stallguard(stepperY2); stealth_states.y2 = tmc_enable_stallguard(stepperY2);
#endif #endif
#if EITHER(CORE_IS_XY, MARKFORGED_XY) && X_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SENSORLESS
stealth_states.x = tmc_enable_stallguard(stepperX); stealth_states.x = tmc_enable_stallguard(stepperX);
#elif CORE_IS_YZ && Z_SENSORLESS #elif CORE_IS_YZ && Z_SENSORLESS
stealth_states.z = tmc_enable_stallguard(stepperZ); stealth_states.z = tmc_enable_stallguard(stepperZ);
@ -1444,7 +1444,7 @@ void prepare_line_to_destination() {
#if AXIS_HAS_STALLGUARD(X2) #if AXIS_HAS_STALLGUARD(X2)
tmc_disable_stallguard(stepperX2, enable_stealth.x2); tmc_disable_stallguard(stepperX2, enable_stealth.x2);
#endif #endif
#if EITHER(CORE_IS_XY, MARKFORGED_XY) && Y_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SENSORLESS
tmc_disable_stallguard(stepperY, enable_stealth.y); tmc_disable_stallguard(stepperY, enable_stealth.y);
#elif CORE_IS_XZ && Z_SENSORLESS #elif CORE_IS_XZ && Z_SENSORLESS
tmc_disable_stallguard(stepperZ, enable_stealth.z); tmc_disable_stallguard(stepperZ, enable_stealth.z);
@ -1457,7 +1457,7 @@ void prepare_line_to_destination() {
#if AXIS_HAS_STALLGUARD(Y2) #if AXIS_HAS_STALLGUARD(Y2)
tmc_disable_stallguard(stepperY2, enable_stealth.y2); tmc_disable_stallguard(stepperY2, enable_stealth.y2);
#endif #endif
#if EITHER(CORE_IS_XY, MARKFORGED_XY) && X_SENSORLESS #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SENSORLESS
tmc_disable_stallguard(stepperX, enable_stealth.x); tmc_disable_stallguard(stepperX, enable_stealth.x);
#elif CORE_IS_YZ && Z_SENSORLESS #elif CORE_IS_YZ && Z_SENSORLESS
tmc_disable_stallguard(stepperZ, enable_stealth.z); tmc_disable_stallguard(stepperZ, enable_stealth.z);
@ -2011,7 +2011,7 @@ void prepare_line_to_destination() {
do_homing_move(axis, adjDistance, get_homing_bump_feedrate(axis)); do_homing_move(axis, adjDistance, get_homing_bump_feedrate(axis));
} }
#else // CARTESIAN / CORE / MARKFORGED_XY #else // CARTESIAN / CORE / MARKFORGED_XY / MARKFORGED_YX
set_axis_is_at_home(axis); set_axis_is_at_home(axis);
sync_plan_position(); sync_plan_position();
@ -2041,7 +2041,7 @@ void prepare_line_to_destination() {
#if ENABLED(SENSORLESS_HOMING) #if ENABLED(SENSORLESS_HOMING)
planner.synchronize(); planner.synchronize();
if (false if (false
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
|| axis != NORMAL_AXIS || axis != NORMAL_AXIS
#endif #endif
) safe_delay(200); // Short delay to allow belts to spring back ) safe_delay(200); // Short delay to allow belts to spring back

@ -1743,7 +1743,7 @@ float Planner::get_axis_position_mm(const AxisEnum axis) {
else else
axis_steps = stepper.position(axis); axis_steps = stepper.position(axis);
#elif ENABLED(MARKFORGED_XY) #elif EITHER(MARKFORGED_XY, MARKFORGED_YX)
// Requesting one of the joined axes? // Requesting one of the joined axes?
if (axis == CORE_AXIS_1 || axis == CORE_AXIS_2) { if (axis == CORE_AXIS_1 || axis == CORE_AXIS_2) {
@ -1917,30 +1917,43 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
// Compute direction bit-mask for this block // Compute direction bit-mask for this block
axis_bits_t dm = 0; axis_bits_t dm = 0;
#if CORE_IS_XY #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 (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X
if (db < 0) SBI(dm, Y_HEAD); // ...and Y if (db < 0) SBI(dm, Y_HEAD); // ...and Y
if (dc < 0) SBI(dm, Z_AXIS); if (dc < 0) SBI(dm, Z_AXIS);
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction #endif
if (CORESIGN(da - db) < 0) SBI(dm, B_AXIS); // Motor B direction #if IS_CORE
#elif CORE_IS_XZ #if CORE_IS_XY
if (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, Y_AXIS); if (CORESIGN(da - db) < 0) SBI(dm, B_AXIS); // Motor B direction
if (dc < 0) SBI(dm, Z_HEAD); // ...and Z #elif CORE_IS_XZ
if (da + dc < 0) SBI(dm, A_AXIS); // Motor A direction if (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X
if (CORESIGN(da - dc) < 0) SBI(dm, C_AXIS); // Motor C direction if (db < 0) SBI(dm, Y_AXIS);
#elif CORE_IS_YZ if (dc < 0) SBI(dm, Z_HEAD); // ...and Z
if (da < 0) SBI(dm, X_AXIS); if (da + dc < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, Y_HEAD); // Save the toolhead's true direction in Y if (CORESIGN(da - dc) < 0) SBI(dm, C_AXIS); // Motor C direction
if (dc < 0) SBI(dm, Z_HEAD); // ...and Z #elif CORE_IS_YZ
if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction if (da < 0) SBI(dm, X_AXIS);
if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction 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
#endif
#if LINEAR_AXES >= 4
if (di < 0) SBI(dm, I_AXIS);
#endif
#if LINEAR_AXES >= 5
if (dj < 0) SBI(dm, J_AXIS);
#endif
#if LINEAR_AXES >= 6
if (dk < 0) SBI(dm, K_AXIS);
#endif
#elif ENABLED(MARKFORGED_XY) #elif ENABLED(MARKFORGED_XY)
if (da < 0) SBI(dm, X_HEAD); // Save the toolhead's true direction in X if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, Y_HEAD); // ...and Y if (db < 0) SBI(dm, B_AXIS); // Motor B direction
if (dc < 0) SBI(dm, Z_AXIS); #elif ENABLED(MARKFORGED_YX)
if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction if (da < 0) SBI(dm, A_AXIS); // Motor A direction
if (db < 0) SBI(dm, B_AXIS); // Motor B direction if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction
#else #else
LINEAR_AXIS_CODE( LINEAR_AXIS_CODE(
if (da < 0) SBI(dm, X_AXIS), if (da < 0) SBI(dm, X_AXIS),
@ -1952,21 +1965,8 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
); );
#endif #endif
#if IS_CORE
#if LINEAR_AXES >= 4
if (di < 0) SBI(dm, I_AXIS);
#endif
#if LINEAR_AXES >= 5
if (dj < 0) SBI(dm, J_AXIS);
#endif
#if LINEAR_AXES >= 6
if (dk < 0) SBI(dm, K_AXIS);
#endif
#endif
TERN_(HAS_EXTRUDERS, if (de < 0) SBI(dm, E_AXIS));
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
if (de < 0) SBI(dm, E_AXIS);
const float esteps_float = de * e_factor[extruder]; const float esteps_float = de * e_factor[extruder];
const uint32_t esteps = ABS(esteps_float) + 0.5f; const uint32_t esteps = ABS(esteps_float) + 0.5f;
#else #else
@ -1996,6 +1996,8 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk))); block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk)));
#elif ENABLED(MARKFORGED_XY) #elif ENABLED(MARKFORGED_XY)
block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#elif ENABLED(MARKFORGED_YX)
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#elif IS_SCARA #elif IS_SCARA
block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk)));
#else #else
@ -2012,15 +2014,18 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
* Having the real displacement of the head, we can calculate the total movement length and apply the desired speed. * Having the real displacement of the head, we can calculate the total movement length and apply the desired speed.
*/ */
struct DistanceMM : abce_float_t { struct DistanceMM : abce_float_t {
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
struct { float x, y, z; } head; struct { float x, y, z; } head;
#endif #endif
} steps_dist_mm; } steps_dist_mm;
#if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
steps_dist_mm.head.x = da * mm_per_step[A_AXIS];
steps_dist_mm.head.y = db * mm_per_step[B_AXIS];
steps_dist_mm.z = dc * mm_per_step[Z_AXIS];
#endif
#if IS_CORE #if IS_CORE
#if CORE_IS_XY #if CORE_IS_XY
steps_dist_mm.head.x = da * mm_per_step[A_AXIS];
steps_dist_mm.head.y = db * mm_per_step[B_AXIS];
steps_dist_mm.z = dc * mm_per_step[Z_AXIS];
steps_dist_mm.a = (da + db) * mm_per_step[A_AXIS]; steps_dist_mm.a = (da + db) * mm_per_step[A_AXIS];
steps_dist_mm.b = CORESIGN(da - db) * mm_per_step[B_AXIS]; steps_dist_mm.b = CORESIGN(da - db) * mm_per_step[B_AXIS];
#elif CORE_IS_XZ #elif CORE_IS_XZ
@ -2046,11 +2051,11 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
steps_dist_mm.k = dk * mm_per_step[K_AXIS]; steps_dist_mm.k = dk * mm_per_step[K_AXIS];
#endif #endif
#elif ENABLED(MARKFORGED_XY) #elif ENABLED(MARKFORGED_XY)
steps_dist_mm.head.x = da * mm_per_step[A_AXIS];
steps_dist_mm.head.y = db * mm_per_step[B_AXIS];
steps_dist_mm.z = dc * mm_per_step[Z_AXIS];
steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS]; steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS];
steps_dist_mm.b = db * mm_per_step[B_AXIS]; steps_dist_mm.b = db * mm_per_step[B_AXIS];
#elif ENABLED(MARKFORGED_YX)
steps_dist_mm.a = da * mm_per_step[A_AXIS];
steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS];
#else #else
LINEAR_AXIS_CODE( LINEAR_AXIS_CODE(
steps_dist_mm.a = da * mm_per_step[A_AXIS], steps_dist_mm.a = da * mm_per_step[A_AXIS],
@ -2082,7 +2087,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
block->millimeters = millimeters; block->millimeters = millimeters;
else { else {
block->millimeters = SQRT( block->millimeters = SQRT(
#if EITHER(CORE_IS_XY, MARKFORGED_XY) #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
LINEAR_AXIS_GANG( LINEAR_AXIS_GANG(
sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z), sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z),
+ sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k)
@ -2161,7 +2166,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
#endif #endif
// Enable active axes // Enable active axes
#if EITHER(CORE_IS_XY, MARKFORGED_XY) #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
if (block->steps.a || block->steps.b) { if (block->steps.a || block->steps.b) {
stepper.enable_axis(X_AXIS); stepper.enable_axis(X_AXIS);
stepper.enable_axis(Y_AXIS); stepper.enable_axis(Y_AXIS);
@ -2191,7 +2196,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
if (block->steps.k) stepper.enable_axis(K_AXIS) if (block->steps.k) stepper.enable_axis(K_AXIS)
); );
#endif #endif
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX)
#if LINEAR_AXES >= 4 #if LINEAR_AXES >= 4
if (block->steps.i) stepper.enable_axis(I_AXIS); if (block->steps.i) stepper.enable_axis(I_AXIS);
#endif #endif
@ -2549,7 +2554,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
* => normalize the complete junction vector. * => normalize the complete junction vector.
* Elsewise, when needed JD will factor-in the E component * Elsewise, when needed JD will factor-in the E component
*/ */
if (EITHER(IS_CORE, MARKFORGED_XY) || esteps > 0) if (ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) || esteps > 0)
normalize_junction_vector(unit_vec); // Normalize with XYZE components normalize_junction_vector(unit_vec); // Normalize with XYZE components
else else
unit_vec *= inverse_millimeters; // Use pre-calculated (1 / SQRT(x^2 + y^2 + z^2)) unit_vec *= inverse_millimeters; // Use pre-calculated (1 / SQRT(x^2 + y^2 + z^2))

@ -2212,6 +2212,8 @@ uint32_t Stepper::block_phase_isr() {
#define Y_CMP(A,B) ((A)!=(B)) #define Y_CMP(A,B) ((A)!=(B))
#endif #endif
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) ) #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) )
#elif ENABLED(MARKFORGED_YX)
#define Y_MOVE_TEST (current_block->steps.a != current_block->steps.b)
#else #else
#define Y_MOVE_TEST !!current_block->steps.b #define Y_MOVE_TEST !!current_block->steps.b
#endif #endif
@ -2800,7 +2802,7 @@ void Stepper::init() {
* derive the current XYZE position later on. * derive the current XYZE position later on.
*/ */
void Stepper::_set_position(const abce_long_t &spos) { void Stepper::_set_position(const abce_long_t &spos) {
#if EITHER(IS_CORE, MARKFORGED_XY) #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
#if CORE_IS_XY #if CORE_IS_XY
// corexy positioning // corexy positioning
// these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html // these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html
@ -2813,6 +2815,8 @@ void Stepper::_set_position(const abce_long_t &spos) {
count_position.set(spos.a, spos.b + spos.c, CORESIGN(spos.b - spos.c)); count_position.set(spos.a, spos.b + spos.c, CORESIGN(spos.b - spos.c));
#elif ENABLED(MARKFORGED_XY) #elif ENABLED(MARKFORGED_XY)
count_position.set(spos.a - spos.b, spos.b, spos.c); count_position.set(spos.a - spos.b, spos.b, spos.c);
#elif ENABLED(MARKFORGED_YX)
count_position.set(spos.a, spos.b - spos.a, spos.c);
#endif #endif
TERN_(HAS_EXTRUDERS, count_position.e = spos.e); TERN_(HAS_EXTRUDERS, count_position.e = spos.e);
#else #else
@ -2884,6 +2888,10 @@ void Stepper::endstop_triggered(const AxisEnum axis) {
axis == CORE_AXIS_1 axis == CORE_AXIS_1
? count_position[CORE_AXIS_1] - count_position[CORE_AXIS_2] ? count_position[CORE_AXIS_1] - count_position[CORE_AXIS_2]
: count_position[CORE_AXIS_2] : count_position[CORE_AXIS_2]
#elif ENABLED(MARKFORGED_YX)
axis == CORE_AXIS_1
? count_position[CORE_AXIS_1]
: count_position[CORE_AXIS_2] - count_position[CORE_AXIS_1]
#else // !IS_CORE #else // !IS_CORE
count_position[axis] count_position[axis]
#endif #endif
@ -2912,10 +2920,10 @@ int32_t Stepper::triggered_position(const AxisEnum axis) {
return v; return v;
} }
#if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, IS_SCARA, DELTA) #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA)
#define SAYS_A 1 #define SAYS_A 1
#endif #endif
#if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, IS_SCARA, DELTA) #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX, IS_SCARA, DELTA)
#define SAYS_B 1 #define SAYS_B 1
#endif #endif
#if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA) #if ANY(CORE_IS_XZ, CORE_IS_YZ, DELTA)

Loading…
Cancel
Save