diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 56aa21cada..ad06763d45 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -350,7 +350,7 @@ #define _LIST_N(N,V...) LIST_##N(V) #define LIST_N(N,V...) _LIST_N(N,V) -#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) +#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) #define ARRAY_N(N,V...) { _LIST_N(N,V) } #define ARRAY_N_1(N,K) { LIST_N_1(N,K) } diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index b8931f44f0..440b2bc053 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -66,6 +66,12 @@ struct IF { typedef L type; }; #define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K) +#define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V) +#define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V) + +#define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V) +#define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V) + #if HAS_EXTRUDERS #define LIST_ITEM_E(N) , N #define CODE_ITEM_E(N) ; N diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h index 91c9533ab0..2bbc07edb8 100644 --- a/Marlin/src/core/utility.h +++ b/Marlin/src/core/utility.h @@ -77,11 +77,14 @@ public: // in the range 0-100 while avoiding rounding artifacts constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; } +// Axis names for G-code parsing, reports, etc. const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME); -const xyze_char_t iaxis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', 'I', 'J', 'K'); #if LINEAR_AXES <= XYZ #define AXIS_CHAR(A) ((char)('X' + A)) + #define IAXIS_CHAR AXIS_CHAR #else + const xyze_char_t iaxis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', 'I', 'J', 'K'); #define AXIS_CHAR(A) axis_codes[A] + #define IAXIS_CHAR(A) iaxis_codes[A] #endif diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index b2096ace7e..d7d0c1c201 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -460,9 +460,11 @@ void GcodeSuite::G28() { } #endif - TERN_(HAS_I_AXIS, if (doI) homeaxis(I_AXIS)); - TERN_(HAS_J_AXIS, if (doJ) homeaxis(J_AXIS)); - TERN_(HAS_K_AXIS, if (doK) homeaxis(K_AXIS)); + SECONDARY_AXIS_CODE( + if (doI) homeaxis(I_AXIS), + if (doJ) homeaxis(J_AXIS), + if (doK) homeaxis(K_AXIS) + ); sync_plan_position(); diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index a2dec64bc3..11570c4a6f 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -88,7 +88,7 @@ enum side_t : uint8_t { TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES, - LIST_N(DOUBLE(SUB3(LINEAR_AXES)), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM) + LIST_N(DOUBLE(SECONDARY_AXES), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM) }; static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER; diff --git a/Marlin/src/gcode/calibrate/M425.cpp b/Marlin/src/gcode/calibrate/M425.cpp index 873d670322..d5eb3822c8 100644 --- a/Marlin/src/gcode/calibrate/M425.cpp +++ b/Marlin/src/gcode/calibrate/M425.cpp @@ -57,7 +57,7 @@ void GcodeSuite::M425() { LOOP_LINEAR_AXES(a) { if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) { planner.synchronize(); - backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a))); + backlash.set_distance_mm((AxisEnum)a, parser.has_value() ? parser.value_axis_units((AxisEnum)a) : backlash.get_measurement((AxisEnum)a)); noArgs = false; } } diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index 74932a64f8..69748f18de 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -174,14 +174,12 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) { #if HAS_Y_AXIS , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y) #endif - #if HAS_I_AXIS - , SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i) - #endif - #if HAS_J_AXIS - , SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j) - #endif - #if HAS_K_AXIS - , SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k) + #if SECONDARY_AXES >= 1 + , LIST_N(DOUBLE(SECONDARY_AXES), + SP_I_STR, I_AXIS_UNIT(toolchange_settings.change_point.i), + SP_J_STR, J_AXIS_UNIT(toolchange_settings.change_point.j), + SP_K_STR, K_AXIS_UNIT(toolchange_settings.change_point.k) + ) #endif ); } diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index 7630dcff46..739a692ba6 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -23,6 +23,7 @@ #include "../gcode.h" #include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers #include "../../lcd/marlinui.h" +#include "../../module/motion.h" // for e_axis_mask #include "../../module/stepper.h" #if ENABLED(AUTO_BED_LEVELING_UBL) @@ -43,7 +44,7 @@ inline stepper_flags_t selected_axis_bits() { selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e)); } else - selected.bits = selected.e_bits(); + selected.bits = e_axis_mask; } #endif selected.bits |= LINEAR_AXIS_GANG( diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp index 999a9b10bd..0113170f1d 100644 --- a/Marlin/src/gcode/feature/clean/G12.cpp +++ b/Marlin/src/gcode/feature/clean/G12.cpp @@ -45,9 +45,10 @@ * X, Y, Z : Specify axes to move during cleaning. Default: ALL. */ void GcodeSuite::G12() { + // Don't allow nozzle cleaning without homing first - if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS))) - return; + constexpr main_axes_bits_t clean_axis_mask = main_axes_mask & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS); + if (homing_needed_error(clean_axis_mask)) return; #ifdef WIPE_SEQUENCE_COMMANDS if (!parser.seen_any()) { diff --git a/Marlin/src/gcode/feature/digipot/M907-M910.cpp b/Marlin/src/gcode/feature/digipot/M907-M910.cpp index 95adde3ea5..e3b4a0c715 100644 --- a/Marlin/src/gcode/feature/digipot/M907-M910.cpp +++ b/Marlin/src/gcode/feature/digipot/M907-M910.cpp @@ -39,7 +39,7 @@ #endif /** - * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E] + * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [E] * B - Special case for 4th (E) axis * S - Special case to set first 3 axes */ @@ -49,15 +49,15 @@ void GcodeSuite::M907() { if (!parser.seen("BS" LOGICAL_AXES_STRING)) return M907_report(); - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int()); if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int()); if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int()); #elif HAS_MOTOR_CURRENT_PWM if (!parser.seen( - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) - "XY" + #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K) + "XY" SECONDARY_AXIS_GANG("I", "J", "K") #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) "Z" @@ -67,8 +67,11 @@ void GcodeSuite::M907() { #endif )) return M907_report(); - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) - if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int()); + #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K) + if (NUM_AXIS_GANG( + parser.seenval('X'), || parser.seenval('Y'), || false, + || parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K') + )) stepper.set_digipot_current(0, parser.value_int()); #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); @@ -81,7 +84,7 @@ void GcodeSuite::M907() { #if HAS_MOTOR_CURRENT_I2C // this one uses actual amps in floating point - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); // Additional extruders use B,C,D for channels 4,5,6. // TODO: Change these parameters because 'E' is used. B? #if HAS_EXTRUDERS @@ -95,7 +98,7 @@ void GcodeSuite::M907() { const float dac_percent = parser.value_float(); LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent); } - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float()); #endif } @@ -104,15 +107,15 @@ void GcodeSuite::M907() { void GcodeSuite::M907_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS)); #if HAS_MOTOR_CURRENT_PWM - SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: - PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y + SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: + PSTR(" M907 X"), stepper.motor_current_setting[0] // X, Y, (I, J, K) , SP_Z_STR, stepper.motor_current_setting[1] // Z , SP_E_STR, stepper.motor_current_setting[2] // E ); #elif HAS_MOTOR_CURRENT_SPI SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values: LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default) - SERIAL_CHAR(' ', axis_codes[q]); + SERIAL_CHAR(' ', IAXIS_CHAR(q)); SERIAL_ECHO(stepper.motor_current_setting[q]); } SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default) diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index 01b7d31e3e..9cd289d7b4 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -51,7 +51,7 @@ void GcodeSuite::G60() { DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :"); const xyze_pos_t &pos = stored_position[slot]; DEBUG_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), PSTR(" : X"), pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k) + LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k) #if HAS_EXTRUDERS , SP_E_LBL, pos.e #endif diff --git a/Marlin/src/gcode/feature/pause/M125.cpp b/Marlin/src/gcode/feature/pause/M125.cpp index 940e1b369b..7fa6bac6b5 100644 --- a/Marlin/src/gcode/feature/pause/M125.cpp +++ b/Marlin/src/gcode/feature/pause/M125.cpp @@ -74,7 +74,9 @@ void GcodeSuite::M125() { ); // Lift Z axis - if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); + #if HAS_Z_AXIS + if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); + #endif #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) park_point += hotend_offset[active_extruder]; diff --git a/Marlin/src/gcode/feature/pause/M600.cpp b/Marlin/src/gcode/feature/pause/M600.cpp index 9ba54ac448..a74a81e85d 100644 --- a/Marlin/src/gcode/feature/pause/M600.cpp +++ b/Marlin/src/gcode/feature/pause/M600.cpp @@ -54,8 +54,11 @@ * * E[distance] - Retract the filament this far * Z[distance] - Move the Z axis by this distance - * X[position] - Move to this X position, with Y - * Y[position] - Move to this Y position, with X + * X[position] - Move to this X position (instead of NOZZLE_PARK_POINT.x) + * Y[position] - Move to this Y position (instead of NOZZLE_PARK_POINT.y) + * I[position] - Move to this I position (instead of NOZZLE_PARK_POINT.i) + * J[position] - Move to this J position (instead of NOZZLE_PARK_POINT.j) + * K[position] - Move to this K position (instead of NOZZLE_PARK_POINT.k) * U[distance] - Retract distance for removal (manual reload) * L[distance] - Extrude distance for insertion (manual reload) * B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer) @@ -118,25 +121,21 @@ void GcodeSuite::M600() { // Move XY axes to filament change position or given position LINEAR_AXIS_CODE( - if (parser.seenval('X')) park_point.x = parser.linearval('X'), - if (parser.seenval('Y')) park_point.y = parser.linearval('Y'), - if (parser.seenval('Z')) park_point.z = parser.linearval('Z'), // Lift Z axis - if (parser.seenval(AXIS4_NAME)) park_point.i = parser.linearval(AXIS4_NAME), - if (parser.seenval(AXIS5_NAME)) park_point.j = parser.linearval(AXIS5_NAME), - if (parser.seenval(AXIS6_NAME)) park_point.k = parser.linearval(AXIS6_NAME) + if (parser.seenval('X')) park_point.x = parser.value_linear_units(), + if (parser.seenval('Y')) park_point.y = parser.value_linear_units(), + if (parser.seenval('Z')) park_point.z = parser.value_linear_units(), // Lift Z axis + if (parser.seenval('I')) park_point.i = parser.value_linear_units(), + if (parser.seenval('J')) park_point.j = parser.value_linear_units(), + if (parser.seenval('K')) park_point.k = parser.value_linear_units() ); #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) park_point += hotend_offset[active_extruder]; #endif - #if ENABLED(MMU2_MENUS) - // For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling - const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f; - #else - // Unload filament - const float unload_length = -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)); - #endif + // Unload filament + // For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling + const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f; const int beep_count = parser.intval('B', -1 #ifdef FILAMENT_CHANGE_ALERT_BEEPS diff --git a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp index 987c20b157..ece733cb67 100644 --- a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp +++ b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp @@ -137,7 +137,7 @@ /** * M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library - * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4 and E[index]. + * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4, A, B, C, and E[index]. * If no axes are given, clear all. * * Examples: diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp index 0397188a7f..238ad8cf47 100644 --- a/Marlin/src/gcode/motion/G2_G3.cpp +++ b/Marlin/src/gcode/motion/G2_G3.cpp @@ -168,12 +168,7 @@ void plan_arc( // Return if the move is near zero if (flat_mm < 0.0001f - GANG_N(SUB2(LINEAR_AXES), - && travel_L < 0.0001f, - && travel_I < 0.0001f, - && travel_J < 0.0001f, - && travel_K < 0.0001f - ) + GANG_N(SUB2(LINEAR_AXES), && travel_L < 0.0001f, && travel_I < 0.0001f, && travel_J < 0.0001f, && travel_K < 0.0001f) ) return; // Feedrate for the move, scaled by the feedrate multiplier diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index b31395493c..97c55b810c 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -666,7 +666,7 @@ #endif /** - * Number of Linear Axes (e.g., XYZ) + * Number of Linear Axes (e.g., XYZIJK) * All the logical axes except for the tool (E) axis */ #ifdef LINEAR_AXES @@ -821,7 +821,23 @@ #endif /** - * Number of Logical Axes (e.g., XYZE) + * Number of Primary Linear Axes (e.g., XYZ) + * X, XY, or XYZ axes. Excluding duplicate axes (X2, Y2. Z2. Z3, Z4) + */ +#if HAS_I_AXIS + #define PRIMARY_LINEAR_AXES 3 +#else + #define PRIMARY_LINEAR_AXES LINEAR_AXES +#endif + +/** + * Number of Secondary Axes (e.g., IJK) + * All linear/rotational axes between XYZ and E. + */ +#define SECONDARY_AXES SUB3(LINEAR_AXES) + +/** + * Number of Logical Axes (e.g., XYZIJKE) * All the logical axes that can be commanded directly by G-code. * Delta maps stepper-specific values to ABC steppers. */ @@ -1268,6 +1284,29 @@ #define HAS_ETHERNET 1 #endif +// Fallback axis inverting +#ifndef INVERT_X_DIR + #define INVERT_X_DIR false +#endif +#if HAS_Y_AXIS && !defined(INVERT_Y_DIR) + #define INVERT_Y_DIR false +#endif +#if HAS_Z_AXIS && !defined(INVERT_Z_DIR) + #define INVERT_Z_DIR false +#endif +#if HAS_I_AXIS && !defined(INVERT_I_DIR) + #define INVERT_I_DIR false +#endif +#if HAS_J_AXIS && !defined(INVERT_J_DIR) + #define INVERT_J_DIR false +#endif +#if HAS_K_AXIS && !defined(INVERT_K_DIR) + #define INVERT_K_DIR false +#endif +#if HAS_EXTRUDERS && !defined(INVERT_E_DIR) + #define INVERT_E_DIR false +#endif + /** * This setting is also used by M109 when trying to calculate * a ballpark safe margin to prevent wait-forever situation. diff --git a/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp b/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp index 56fd8cadc0..8024085ef7 100644 --- a/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp @@ -79,9 +79,9 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const dwin_string.set(); if (blink) dwin_string.add(value); - else if (!TEST(axis_homed, axis)) + else if (!TEST(axes_homed, axis)) while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); - else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axis_trusted, axis)) + else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axes_trusted, axis)) dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); else dwin_string.add(value); @@ -103,11 +103,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const if (blink) dwin_string.add(value); else { - if (!TEST(axis_homed, axis)) + if (!TEST(axes_homed, axis)) while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?'); else { #if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) - if (!TEST(axis_trusted, axis)) + if (!TEST(axes_trusted, axis)) dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" ")); else #endif diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 2dd631107f..e9bfbc5299 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -476,15 +476,11 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s #if HAS_Z_AXIS const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS); #endif - #if HAS_I_AXIS - const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS); - #endif - #if HAS_J_AXIS - const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS); - #endif - #if HAS_K_AXIS - const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS); - #endif + SECONDARY_AXIS_CODE( + const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS), + const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS), + const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS) + ); #if IS_KINEMATIC if (!position_is_reachable(x, y)) return; @@ -678,11 +674,11 @@ void restore_feedrate_and_scaling() { // Software Endstops are based on the configured limits. #define _AMIN(A) A##_MIN_POS - #define _AMAX(A) (_AXIS(A) < Z_AXIS ? A##_MAX_BED : A##_MAX_POS) + #define _AMAX(A) A##_MAX_POS soft_endstops_t soft_endstop = { true, false, { MAPLIST(_AMIN, MAIN_AXIS_NAMES) }, - { MAPLIST(_AMAX, MAIN_AXIS_NAMES) } + { MAPLIST(_AMAX, MAIN_AXIS_NAMES) }, }; /** @@ -1291,10 +1287,10 @@ void prepare_line_to_destination() { #if HAS_ENDSTOPS - linear_axis_bits_t axis_homed, axis_trusted; // = 0 + main_axes_bits_t axes_homed, axes_trusted; // = 0 - linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits/*=linear_bits*/) { - auto set_should = [](linear_axis_bits_t &b, AxisEnum a) { + main_axes_bits_t axes_should_home(main_axes_bits_t axis_bits/*=main_axes_mask*/) { + auto set_should = [](main_axes_bits_t &b, AxisEnum a) { if (TEST(b, a) && TERN(HOME_AFTER_DEACTIVATE, axis_is_trusted, axis_was_homed)(a)) CBI(b, a); }; @@ -1306,20 +1302,12 @@ void prepare_line_to_destination() { return axis_bits; } - bool homing_needed_error(linear_axis_bits_t axis_bits/*=linear_bits*/) { + bool homing_needed_error(main_axes_bits_t axis_bits/*=main_axes_mask*/) { if ((axis_bits = axes_should_home(axis_bits))) { PGM_P home_first = GET_TEXT(MSG_HOME_FIRST); char msg[30]; - sprintf_P(msg, home_first, - LINEAR_AXIS_LIST( - TEST(axis_bits, X_AXIS) ? "X" : "", - TEST(axis_bits, Y_AXIS) ? "Y" : "", - TEST(axis_bits, Z_AXIS) ? "Z" : "", - TEST(axis_bits, I_AXIS) ? STR_I : "", - TEST(axis_bits, J_AXIS) ? STR_J : "", - TEST(axis_bits, K_AXIS) ? STR_K : "" - ) - ); + #define _AXIS_CHAR(N) TEST(axis_bits, _AXIS(N)) ? STR_##N : "" + sprintf_P(msg, home_first, MAPLIST(_AXIS_CHAR, MAIN_AXIS_NAMES)); SERIAL_ECHO_START(); SERIAL_ECHOLN(msg); ui.set_status(msg); diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 1dd6d8c4ed..0a43459765 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -374,38 +374,41 @@ void restore_feedrate_and_scaling(); /** * Homing and Trusted Axes */ -typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; -constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1; +typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type main_axes_bits_t; +constexpr main_axes_bits_t main_axes_mask = _BV(LINEAR_AXES) - 1; + +typedef IF<(LINEAR_AXES + EXTRUDERS > 8), uint16_t, uint8_t>::type e_axis_bits_t; +constexpr e_axis_bits_t e_axis_mask = (_BV(EXTRUDERS) - 1) << LINEAR_AXES; void set_axis_is_at_home(const AxisEnum axis); #if HAS_ENDSTOPS /** - * axis_homed + * axes_homed * Flags that each linear axis was homed. * XYZ on cartesian, ABC on delta, ABZ on SCARA. * - * axis_trusted + * axes_trusted * Flags that the position is trusted in each linear axis. Set when homed. * Cleared whenever a stepper powers off, potentially losing its position. */ - extern linear_axis_bits_t axis_homed, axis_trusted; + extern main_axes_bits_t axes_homed, axes_trusted; void homeaxis(const AxisEnum axis); void set_axis_never_homed(const AxisEnum axis); - linear_axis_bits_t axes_should_home(linear_axis_bits_t axis_bits=linear_bits); - bool homing_needed_error(linear_axis_bits_t axis_bits=linear_bits); - inline void set_axis_unhomed(const AxisEnum axis) { CBI(axis_homed, axis); } - inline void set_axis_untrusted(const AxisEnum axis) { CBI(axis_trusted, axis); } - inline void set_all_unhomed() { axis_homed = axis_trusted = 0; } - inline void set_axis_homed(const AxisEnum axis) { SBI(axis_homed, axis); } - inline void set_axis_trusted(const AxisEnum axis) { SBI(axis_trusted, axis); } - inline void set_all_homed() { axis_homed = axis_trusted = linear_bits; } + main_axes_bits_t axes_should_home(main_axes_bits_t axes_mask=main_axes_mask); + bool homing_needed_error(main_axes_bits_t axes_mask=main_axes_mask); + inline void set_axis_unhomed(const AxisEnum axis) { CBI(axes_homed, axis); } + inline void set_axis_untrusted(const AxisEnum axis) { CBI(axes_trusted, axis); } + inline void set_all_unhomed() { axes_homed = axes_trusted = 0; } + inline void set_axis_homed(const AxisEnum axis) { SBI(axes_homed, axis); } + inline void set_axis_trusted(const AxisEnum axis) { SBI(axes_trusted, axis); } + inline void set_all_homed() { axes_homed = axes_trusted = main_axes_mask; } #else - constexpr linear_axis_bits_t axis_homed = linear_bits, axis_trusted = linear_bits; // Zero-endstop machines are always homed and trusted + constexpr main_axes_bits_t axes_homed = main_axes_mask, axes_trusted = main_axes_mask; // Zero-endstop machines are always homed and trusted inline void homeaxis(const AxisEnum axis) {} inline void set_axis_never_homed(const AxisEnum) {} - inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return 0; } - inline bool homing_needed_error(linear_axis_bits_t=linear_bits) { return false; } + inline main_axes_bits_t axes_should_home(main_axes_bits_t=main_axes_mask) { return 0; } + inline bool homing_needed_error(main_axes_bits_t=main_axes_mask) { return false; } inline void set_axis_unhomed(const AxisEnum axis) {} inline void set_axis_untrusted(const AxisEnum axis) {} inline void set_all_unhomed() {} @@ -414,13 +417,13 @@ void set_axis_is_at_home(const AxisEnum axis); inline void set_all_homed() {} #endif -inline bool axis_was_homed(const AxisEnum axis) { return TEST(axis_homed, axis); } -inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axis_trusted, axis); } +inline bool axis_was_homed(const AxisEnum axis) { return TEST(axes_homed, axis); } +inline bool axis_is_trusted(const AxisEnum axis) { return TEST(axes_trusted, axis); } inline bool axis_should_home(const AxisEnum axis) { return (axes_should_home() & _BV(axis)) != 0; } -inline bool no_axes_homed() { return !axis_homed; } -inline bool all_axes_homed() { return linear_bits == (axis_homed & linear_bits); } +inline bool no_axes_homed() { return !axes_homed; } +inline bool all_axes_homed() { return main_axes_mask == (axes_homed & main_axes_mask); } inline bool homing_needed() { return !all_axes_homed(); } -inline bool all_axes_trusted() { return linear_bits == (axis_trusted & linear_bits); } +inline bool all_axes_trusted() { return main_axes_mask == (axes_trusted & main_axes_mask); } void home_if_needed(const bool keeplev=false); diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index dd7ae78afd..a7b6bf09fd 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1933,15 +1933,6 @@ bool Planner::_populate_block( 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 HAS_I_AXIS - if (di < 0) SBI(dm, I_AXIS); - #endif - #if HAS_J_AXIS - if (dj < 0) SBI(dm, J_AXIS); - #endif - #if HAS_K_AXIS - if (dk < 0) SBI(dm, K_AXIS); - #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 @@ -1949,16 +1940,19 @@ bool Planner::_populate_block( if (da < 0) SBI(dm, A_AXIS); // Motor A direction if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction #else - LINEAR_AXIS_CODE( + XYZ_CODE( if (da < 0) SBI(dm, X_AXIS), if (db < 0) SBI(dm, Y_AXIS), - if (dc < 0) SBI(dm, Z_AXIS), - if (di < 0) SBI(dm, I_AXIS), - if (dj < 0) SBI(dm, J_AXIS), - if (dk < 0) SBI(dm, K_AXIS) + if (dc < 0) SBI(dm, Z_AXIS) ); #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 HAS_EXTRUDERS if (de < 0) SBI(dm, E_AXIS); const float esteps_float = de * e_factor[extruder]; @@ -2045,16 +2039,19 @@ bool Planner::_populate_block( steps_dist_mm.a = da * mm_per_step[A_AXIS]; steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS]; #else - LINEAR_AXIS_CODE( + XYZ_CODE( steps_dist_mm.a = da * mm_per_step[A_AXIS], steps_dist_mm.b = db * mm_per_step[B_AXIS], - steps_dist_mm.c = dc * mm_per_step[C_AXIS], - steps_dist_mm.i = di * mm_per_step[I_AXIS], - steps_dist_mm.j = dj * mm_per_step[J_AXIS], - steps_dist_mm.k = dk * mm_per_step[K_AXIS] + steps_dist_mm.c = dc * mm_per_step[C_AXIS] ); #endif + SECONDARY_AXIS_CODE( + steps_dist_mm.i = di * mm_per_step[I_AXIS], + steps_dist_mm.j = dj * mm_per_step[J_AXIS], + steps_dist_mm.k = dk * mm_per_step[K_AXIS] + ); + TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]); TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e); @@ -2181,9 +2178,11 @@ bool Planner::_populate_block( ); #endif #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - TERN_(HAS_I_AXIS, if (block->steps.i) stepper.enable_axis(I_AXIS)); - TERN_(HAS_J_AXIS, if (block->steps.j) stepper.enable_axis(J_AXIS)); - TERN_(HAS_K_AXIS, if (block->steps.k) stepper.enable_axis(K_AXIS)); + SECONDARY_AXIS_CODE( + 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 // Enable extruder(s) diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 89bd8b8042..9847b9a7cf 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -274,14 +274,14 @@ xyz_pos_t Probe::offset; // Initialized by settings.load() #if ENABLED(PROBING_STEPPERS_OFF) && DISABLED(DELTA) static uint8_t old_trusted; if (dopause) { - old_trusted = axis_trusted; + old_trusted = axes_trusted; stepper.disable_axis(X_AXIS); stepper.disable_axis(Y_AXIS); } else { 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; + axes_trusted = old_trusted; } #endif if (dopause) safe_delay(_MAX(DELAY_BEFORE_PROBING, 25)); diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 7624359c87..1e86040db6 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -2812,6 +2812,7 @@ void Stepper::_set_position(const abce_long_t &spos) { #elif ENABLED(MARKFORGED_YX) count_position.set(spos.a, spos.b - spos.a, spos.c); #endif + SECONDARY_AXIS_CODE(count_position.i = spos.i, count_position.j = spos.j, count_position.k = spos.k); TERN_(HAS_EXTRUDERS, count_position.e = spos.e); #else // default non-h-bot planning diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 89ba7b0671..dac04d69b5 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -250,8 +250,6 @@ typedef struct { #endif }; }; - constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; } - constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; } } stepper_flags_t; // All the stepper enable pins