diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index c2d5dced283b..9237818c2560 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -35,7 +35,7 @@ * * Advanced settings can be found in Configuration_adv.h */ -#define CONFIGURATION_H_VERSION 02000903 +#define CONFIGURATION_H_VERSION 02010000 //=========================================================================== //============================= Getting Started ============================= @@ -150,9 +150,9 @@ //#define MACHINE_UUID "00000000-0000-0000-0000-000000000000" /** - * Define the number of coordinated linear axes. + * Define the number of coordinated axes. * See https://github.com/DerAndere1/Marlin/wiki - * Each linear axis gets its own stepper control and endstop: + * Each axis gets its own stepper control and endstop: * * Steppers: *_STEP_PIN, *_ENABLE_PIN, *_DIR_PIN, *_ENABLE_ON * Endstops: *_STOP_PIN, USE_*MIN_PLUG, USE_*MAX_PLUG @@ -161,31 +161,50 @@ * DEFAULT_MAX_ACCELERATION, AXIS_RELATIVE_MODES, * MICROSTEP_MODES, MANUAL_FEEDRATE * - * :[3, 4, 5, 6] + * :[3, 4, 5, 6, 7, 8, 9] */ -//#define LINEAR_AXES 3 +//#define NUM_AXES 3 /** - * Axis codes for additional axes: - * This defines the axis code that is used in G-code commands to - * reference a specific axis. - * 'A' for rotational axis parallel to X - * 'B' for rotational axis parallel to Y - * 'C' for rotational axis parallel to Z - * 'U' for secondary linear axis parallel to X - * 'V' for secondary linear axis parallel to Y - * 'W' for secondary linear axis parallel to Z - * Regardless of the settings, firmware-internal axis IDs are - * I (AXIS4), J (AXIS5), K (AXIS6). + * Additional Axis Settings + * + * Define AXISn_ROTATES for all axes that rotate or pivot. + * Rotational axis coordinates are expressed in degrees. + * + * AXISn_NAME defines the letter used to refer to the axis in (most) G-code commands. + * By convention the names and roles are typically: + * 'A' : Rotational axis parallel to X + * 'B' : Rotational axis parallel to Y + * 'C' : Rotational axis parallel to Z + * 'U' : Secondary linear axis parallel to X + * 'V' : Secondary linear axis parallel to Y + * 'W' : Secondary linear axis parallel to Z + * + * Regardless of these settings the axes are internally named I, J, K, U, V, W. */ -#if LINEAR_AXES >= 4 +#if NUM_AXES >= 4 #define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W'] + #define AXIS4_ROTATES +#endif +#if NUM_AXES >= 5 + #define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W'] + #define AXIS5_ROTATES +#endif +#if NUM_AXES >= 6 + #define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W'] + #define AXIS6_ROTATES +#endif +#if NUM_AXES >= 7 + #define AXIS7_NAME 'U' // :['U', 'V', 'W'] + //#define AXIS7_ROTATES #endif -#if LINEAR_AXES >= 5 - #define AXIS5_NAME 'B' // :['A', 'B', 'C', 'U', 'V', 'W'] +#if NUM_AXES >= 8 + #define AXIS8_NAME 'V' // :['V', 'W'] + //#define AXIS8_ROTATES #endif -#if LINEAR_AXES >= 6 - #define AXIS6_NAME 'C' // :['A', 'B', 'C', 'U', 'V', 'W'] +#if NUM_AXES >= 9 + #define AXIS9_NAME 'W' // :['W'] + //#define AXIS9_ROTATES #endif // @section extruder @@ -793,12 +812,18 @@ //#define USE_IMIN_PLUG //#define USE_JMIN_PLUG //#define USE_KMIN_PLUG +//#define USE_UMIN_PLUG +//#define USE_VMIN_PLUG +//#define USE_WMIN_PLUG //#define USE_XMAX_PLUG //#define USE_YMAX_PLUG //#define USE_ZMAX_PLUG //#define USE_IMAX_PLUG //#define USE_JMAX_PLUG //#define USE_KMAX_PLUG +//#define USE_UMAX_PLUG +//#define USE_VMAX_PLUG +//#define USE_WMAX_PLUG // Enable pullup for all endstops to prevent a floating state #define ENDSTOPPULLUPS @@ -810,12 +835,18 @@ //#define ENDSTOPPULLUP_IMIN //#define ENDSTOPPULLUP_JMIN //#define ENDSTOPPULLUP_KMIN + //#define ENDSTOPPULLUP_UMIN + //#define ENDSTOPPULLUP_VMIN + //#define ENDSTOPPULLUP_WMIN //#define ENDSTOPPULLUP_XMAX //#define ENDSTOPPULLUP_YMAX //#define ENDSTOPPULLUP_ZMAX //#define ENDSTOPPULLUP_IMAX //#define ENDSTOPPULLUP_JMAX //#define ENDSTOPPULLUP_KMAX + //#define ENDSTOPPULLUP_UMAX + //#define ENDSTOPPULLUP_VMAX + //#define ENDSTOPPULLUP_WMAX //#define ENDSTOPPULLUP_ZMIN_PROBE #endif @@ -829,12 +860,18 @@ //#define ENDSTOPPULLDOWN_IMIN //#define ENDSTOPPULLDOWN_JMIN //#define ENDSTOPPULLDOWN_KMIN + //#define ENDSTOPPULLDOWN_UMIN + //#define ENDSTOPPULLDOWN_VMIN + //#define ENDSTOPPULLDOWN_WMIN //#define ENDSTOPPULLDOWN_XMAX //#define ENDSTOPPULLDOWN_YMAX //#define ENDSTOPPULLDOWN_ZMAX //#define ENDSTOPPULLDOWN_IMAX //#define ENDSTOPPULLDOWN_JMAX //#define ENDSTOPPULLDOWN_KMAX + //#define ENDSTOPPULLDOWN_UMAX + //#define ENDSTOPPULLDOWN_VMAX + //#define ENDSTOPPULLDOWN_WMAX //#define ENDSTOPPULLDOWN_ZMIN_PROBE #endif @@ -845,12 +882,18 @@ #define I_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define J_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define K_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define U_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define V_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define W_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define I_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define J_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define K_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define U_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define V_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. +#define W_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe. /** @@ -882,6 +925,9 @@ //#define I_DRIVER_TYPE A4988 //#define J_DRIVER_TYPE A4988 //#define K_DRIVER_TYPE A4988 +//#define U_DRIVER_TYPE A4988 +//#define V_DRIVER_TYPE A4988 +//#define W_DRIVER_TYPE A4988 #define E0_DRIVER_TYPE A4988 //#define E1_DRIVER_TYPE A4988 //#define E2_DRIVER_TYPE A4988 @@ -933,16 +979,16 @@ //#define DISTINCT_E_FACTORS /** - * Default Axis Steps Per Unit (steps/mm) + * Default Axis Steps Per Unit (linear=steps/mm, rotational=steps/°) * Override with M92 - * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]] + * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]] */ #define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 } /** - * Default Max Feed Rate (mm/s) + * Default Max Feed Rate (linear=mm/s, rotational=°/s) * Override with M203 - * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]] + * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]] */ #define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 } @@ -952,10 +998,10 @@ #endif /** - * Default Max Acceleration (change/s) change = mm/s + * Default Max Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2)) * (Maximum start speed for accelerated moves) * Override with M201 - * X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]] + * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]] */ #define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 } @@ -965,7 +1011,7 @@ #endif /** - * Default Acceleration (change/s) change = mm/s + * Default Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2)) * Override with M204 * * M204 P Acceleration @@ -978,7 +1024,7 @@ /** * Default Jerk limits (mm/s) - * Override with M205 X Y Z E + * Override with M205 X Y Z . . . E * * "Jerk" specifies the minimum speed change that requires acceleration. * When changing speed and direction, if the difference is less than the @@ -992,6 +1038,9 @@ //#define DEFAULT_IJERK 0.3 //#define DEFAULT_JJERK 0.3 //#define DEFAULT_KJERK 0.3 + //#define DEFAULT_UJERK 0.3 + //#define DEFAULT_VJERK 0.3 + //#define DEFAULT_WJERK 0.3 //#define TRAVEL_EXTRA_XYJERK 0.0 // Additional jerk allowance for all travel moves @@ -1330,6 +1379,9 @@ //#define I_ENABLE_ON 0 //#define J_ENABLE_ON 0 //#define K_ENABLE_ON 0 +//#define U_ENABLE_ON 0 +//#define V_ENABLE_ON 0 +//#define W_ENABLE_ON 0 // Disable axis steppers immediately when they're not being stepped. // WARNING: When motors turn off there is a chance of losing position accuracy! @@ -1339,6 +1391,9 @@ //#define DISABLE_I false //#define DISABLE_J false //#define DISABLE_K false +//#define DISABLE_U false +//#define DISABLE_V false +//#define DISABLE_W false // Turn off the display blinking that warns about possible accuracy reduction //#define DISABLE_REDUCED_ACCURACY_WARNING @@ -1357,6 +1412,9 @@ //#define INVERT_I_DIR false //#define INVERT_J_DIR false //#define INVERT_K_DIR false +//#define INVERT_U_DIR false +//#define INVERT_V_DIR false +//#define INVERT_W_DIR false // @section extruder @@ -1395,6 +1453,9 @@ //#define I_HOME_DIR -1 //#define J_HOME_DIR -1 //#define K_HOME_DIR -1 +//#define U_HOME_DIR -1 +//#define V_HOME_DIR -1 +//#define W_HOME_DIR -1 // @section machine @@ -1402,7 +1463,7 @@ #define X_BED_SIZE 200 #define Y_BED_SIZE 200 -// Travel limits (mm) after homing, corresponding to endstop positions. +// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions. #define X_MIN_POS 0 #define Y_MIN_POS 0 #define Z_MIN_POS 0 @@ -1415,6 +1476,12 @@ //#define J_MAX_POS 50 //#define K_MIN_POS 0 //#define K_MAX_POS 50 +//#define U_MIN_POS 0 +//#define U_MAX_POS 50 +//#define V_MIN_POS 0 +//#define V_MAX_POS 50 +//#define W_MIN_POS 0 +//#define W_MAX_POS 50 /** * Software Endstops @@ -1434,6 +1501,9 @@ #define MIN_SOFTWARE_ENDSTOP_I #define MIN_SOFTWARE_ENDSTOP_J #define MIN_SOFTWARE_ENDSTOP_K + #define MIN_SOFTWARE_ENDSTOP_U + #define MIN_SOFTWARE_ENDSTOP_V + #define MIN_SOFTWARE_ENDSTOP_W #endif // Max software endstops constrain movement within maximum coordinate bounds @@ -1445,6 +1515,9 @@ #define MAX_SOFTWARE_ENDSTOP_I #define MAX_SOFTWARE_ENDSTOP_J #define MAX_SOFTWARE_ENDSTOP_K + #define MAX_SOFTWARE_ENDSTOP_U + #define MAX_SOFTWARE_ENDSTOP_V + #define MAX_SOFTWARE_ENDSTOP_W #endif #if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS) @@ -1759,6 +1832,9 @@ //#define MANUAL_I_HOME_POS 0 //#define MANUAL_J_HOME_POS 0 //#define MANUAL_K_HOME_POS 0 +//#define MANUAL_U_HOME_POS 0 +//#define MANUAL_V_HOME_POS 0 +//#define MANUAL_W_HOME_POS 0 /** * Use "Z Safe Homing" to avoid homing with a Z probe outside the bed area. @@ -1774,7 +1850,7 @@ #define Z_SAFE_HOMING_Y_POINT Y_CENTER // Y point for Z homing #endif -// Homing speeds (mm/min) +// Homing speeds (linear=mm/min, rotational=°/min) #define HOMING_FEEDRATE_MM_M { (50*60), (50*60), (4*60) } // Validate that endstops are triggered on homing moves diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 957222e7f738..9c438e0406ca 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -30,7 +30,7 @@ * * Basic settings can be found in Configuration.h */ -#define CONFIGURATION_ADV_H_VERSION 02000903 +#define CONFIGURATION_ADV_H_VERSION 02010000 //=========================================================================== //============================= Thermal Settings ============================ @@ -843,12 +843,12 @@ * the position of the toolhead relative to the workspace. */ -//#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (mm) Backoff from endstops before sensorless homing +//#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (linear=mm, rotational=°) Backoff from endstops before sensorless homing -#define HOMING_BUMP_MM { 5, 5, 2 } // (mm) Backoff from endstops after first bump +#define HOMING_BUMP_MM { 5, 5, 2 } // (linear=mm, rotational=°) Backoff from endstops after first bump #define HOMING_BUMP_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate) -//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (mm) Backoff from endstops after homing +//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (linear=mm, rotational=°) Backoff from endstops after homing //#define QUICK_HOME // If G28 contains XY do a diagonal move first //#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X @@ -1034,6 +1034,9 @@ #define INVERT_I_STEP_PIN false #define INVERT_J_STEP_PIN false #define INVERT_K_STEP_PIN false +#define INVERT_U_STEP_PIN false +#define INVERT_V_STEP_PIN false +#define INVERT_W_STEP_PIN false #define INVERT_E_STEP_PIN false /** @@ -1048,11 +1051,14 @@ #define DISABLE_INACTIVE_I true #define DISABLE_INACTIVE_J true #define DISABLE_INACTIVE_K true +#define DISABLE_INACTIVE_U true +#define DISABLE_INACTIVE_V true +#define DISABLE_INACTIVE_W true #define DISABLE_INACTIVE_E true // Default Minimum Feedrates for printing and travel moves -#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S. -#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T. +#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum feedrate. Set with M205 S. +#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum travel feedrate. Set with M205 T. // Minimum time that a segment needs to take as the buffer gets emptied #define DEFAULT_MINSEGMENTTIME 20000 // (µs) Set with M205 B. @@ -1088,7 +1094,7 @@ #if ENABLED(BACKLASH_COMPENSATION) // Define values for backlash distance and correction. // If BACKLASH_GCODE is enabled these values are the defaults. - #define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm) One value for each linear axis + #define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (linear=mm, rotational=°) One value for each linear axis #define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction // Add steps for motor direction changes on CORE kinematics @@ -1165,6 +1171,12 @@ //#define CALIBRATION_MEASURE_JMAX //#define CALIBRATION_MEASURE_KMIN //#define CALIBRATION_MEASURE_KMAX + //#define CALIBRATION_MEASURE_UMIN + //#define CALIBRATION_MEASURE_UMAX + //#define CALIBRATION_MEASURE_VMIN + //#define CALIBRATION_MEASURE_VMAX + //#define CALIBRATION_MEASURE_WMIN + //#define CALIBRATION_MEASURE_WMAX // Probing at the exact top center only works if the center is flat. If // probing on a screwhead or hollow washer, probe near the edges. @@ -2012,6 +2024,21 @@ // @section leveling +/** + * Use Safe Bed Leveling coordinates to move axes to a useful position before bed probing. + * For example, after homing a rotational axis the Z probe might not be perpendicular to the bed. + * Choose values the orient the bed horizontally and the Z-probe vertically. + */ +//#define SAFE_BED_LEVELING_START_X 0.0 +//#define SAFE_BED_LEVELING_START_Y 0.0 +//#define SAFE_BED_LEVELING_START_Z 0.0 +//#define SAFE_BED_LEVELING_START_I 0.0 +//#define SAFE_BED_LEVELING_START_J 0.0 +//#define SAFE_BED_LEVELING_START_K 0.0 +//#define SAFE_BED_LEVELING_START_U 0.0 +//#define SAFE_BED_LEVELING_START_V 0.0 +//#define SAFE_BED_LEVELING_START_W 0.0 + /** * Points to probe for all 3-point Leveling procedures. * Override if the automatically selected points are inadequate. @@ -2423,7 +2450,7 @@ /** * Extra G-code to run while executing tool-change commands. Can be used to use an additional - * stepper motor (I axis, see option LINEAR_AXES in Configuration.h) to drive the tool-changer. + * stepper motor (I axis, see option NUM_AXES in Configuration.h) to drive the tool-changer. */ //#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0 //#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1 @@ -2626,6 +2653,24 @@ #define K_MICROSTEPS 16 #endif + #if AXIS_DRIVER_TYPE_U(TMC26X) + #define U_MAX_CURRENT 1000 + #define U_SENSE_RESISTOR 91 + #define U_MICROSTEPS 16 + #endif + + #if AXIS_DRIVER_TYPE_V(TMC26X) + #define V_MAX_CURRENT 1000 + #define V_SENSE_RESISTOR 91 + #define V_MICROSTEPS 16 + #endif + + #if AXIS_DRIVER_TYPE_W(TMC26X) + #define W_MAX_CURRENT 1000 + #define W_SENSE_RESISTOR 91 + #define W_MICROSTEPS 16 + #endif + #if AXIS_DRIVER_TYPE_E0(TMC26X) #define E0_MAX_CURRENT 1000 #define E0_SENSE_RESISTOR 91 @@ -2814,6 +2859,33 @@ //#define K_HOLD_MULTIPLIER 0.5 #endif + #if AXIS_IS_TMC(U) + #define U_CURRENT 800 + #define U_CURRENT_HOME U_CURRENT + #define U_MICROSTEPS 8 + #define U_RSENSE 0.11 + #define U_CHAIN_POS -1 + //#define U_INTERPOLATE true + #endif + + #if AXIS_IS_TMC(V) + #define V_CURRENT 800 + #define V_CURRENT_HOME V_CURRENT + #define V_MICROSTEPS 8 + #define V_RSENSE 0.11 + #define V_CHAIN_POS -1 + //#define V_INTERPOLATE true + #endif + + #if AXIS_IS_TMC(W) + #define W_CURRENT 800 + #define W_CURRENT_HOME W_CURRENT + #define W_MICROSTEPS 8 + #define W_RSENSE 0.11 + #define W_CHAIN_POS -1 + //#define W_INTERPOLATE true + #endif + #if AXIS_IS_TMC(E0) #define E0_CURRENT 800 #define E0_MICROSTEPS 16 @@ -2901,6 +2973,9 @@ //#define I_CS_PIN -1 //#define J_CS_PIN -1 //#define K_CS_PIN -1 + //#define U_CS_PIN -1 + //#define V_CS_PIN -1 + //#define W_CS_PIN -1 //#define E0_CS_PIN -1 //#define E1_CS_PIN -1 //#define E2_CS_PIN -1 @@ -2943,6 +3018,9 @@ //#define I_SLAVE_ADDRESS 0 //#define J_SLAVE_ADDRESS 0 //#define K_SLAVE_ADDRESS 0 + //#define U_SLAVE_ADDRESS 0 + //#define V_SLAVE_ADDRESS 0 + //#define W_SLAVE_ADDRESS 0 //#define E0_SLAVE_ADDRESS 0 //#define E1_SLAVE_ADDRESS 0 //#define E2_SLAVE_ADDRESS 0 @@ -2970,6 +3048,9 @@ #define STEALTHCHOP_I #define STEALTHCHOP_J #define STEALTHCHOP_K + #define STEALTHCHOP_U + #define STEALTHCHOP_V + #define STEALTHCHOP_W #define STEALTHCHOP_E /** @@ -2996,9 +3077,12 @@ //#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z //#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z //#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z - //#define CHOPPER_TIMING_I CHOPPER_TIMING - //#define CHOPPER_TIMING_J CHOPPER_TIMING - //#define CHOPPER_TIMING_K CHOPPER_TIMING + //#define CHOPPER_TIMING_I CHOPPER_TIMING // For I Axis + //#define CHOPPER_TIMING_J CHOPPER_TIMING // For J Axis + //#define CHOPPER_TIMING_K CHOPPER_TIMING // For K Axis + //#define CHOPPER_TIMING_U CHOPPER_TIMING // For U Axis + //#define CHOPPER_TIMING_V CHOPPER_TIMING // For V Axis + //#define CHOPPER_TIMING_W CHOPPER_TIMING // For W Axis //#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below) //#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E //#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E @@ -3044,9 +3128,12 @@ #define Z2_HYBRID_THRESHOLD 3 #define Z3_HYBRID_THRESHOLD 3 #define Z4_HYBRID_THRESHOLD 3 - #define I_HYBRID_THRESHOLD 3 - #define J_HYBRID_THRESHOLD 3 - #define K_HYBRID_THRESHOLD 3 + #define I_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s] + #define J_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s] + #define K_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s] + #define U_HYBRID_THRESHOLD 3 // [mm/s] + #define V_HYBRID_THRESHOLD 3 + #define W_HYBRID_THRESHOLD 3 #define E0_HYBRID_THRESHOLD 30 #define E1_HYBRID_THRESHOLD 30 #define E2_HYBRID_THRESHOLD 30 @@ -3096,6 +3183,9 @@ //#define I_STALL_SENSITIVITY 8 //#define J_STALL_SENSITIVITY 8 //#define K_STALL_SENSITIVITY 8 + //#define U_STALL_SENSITIVITY 8 + //#define V_STALL_SENSITIVITY 8 + //#define W_STALL_SENSITIVITY 8 //#define SPI_ENDSTOPS // TMC2130 only //#define IMPROVE_HOMING_RELIABILITY #endif @@ -3263,6 +3353,33 @@ #define K_SLEW_RATE 1 #endif + #if AXIS_IS_L64XX(U) + #define U_MICROSTEPS 128 + #define U_OVERCURRENT 2000 + #define U_STALLCURRENT 1500 + #define U_MAX_VOLTAGE 127 + #define U_CHAIN_POS -1 + #define U_SLEW_RATE 1 + #endif + + #if AXIS_IS_L64XX(V) + #define V_MICROSTEPS 128 + #define V_OVERCURRENT 2000 + #define V_STALLCURRENT 1500 + #define V_MAX_VOLTAGE 127 + #define V_CHAIN_POS -1 + #define V_SLEW_RATE 1 + #endif + + #if AXIS_IS_L64XX(W) + #define W_MICROSTEPS 128 + #define W_OVERCURRENT 2000 + #define W_STALLCURRENT 1500 + #define W_MAX_VOLTAGE 127 + #define W_CHAIN_POS -1 + #define W_SLEW_RATE 1 + #endif + #if AXIS_IS_L64XX(E0) #define E0_MICROSTEPS 128 #define E0_OVERCURRENT 2000 diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h index 0ce8574c53d9..5511aa406fec 100644 --- a/Marlin/src/HAL/AVR/endstop_interrupts.h +++ b/Marlin/src/HAL/AVR/endstop_interrupts.h @@ -213,6 +213,51 @@ void setup_endstop_interrupts() { pciSetup(K_MIN_PIN); #endif #endif + #if HAS_U_MAX + #if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(U_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable"); + pciSetup(U_MAX_PIN); + #endif + #elif HAS_U_MIN + #if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(U_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable"); + pciSetup(U_MIN_PIN); + #endif + #endif + #if HAS_V_MAX + #if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(V_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable"); + pciSetup(V_MAX_PIN); + #endif + #elif HAS_V_MIN + #if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(V_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable"); + pciSetup(V_MIN_PIN); + #endif + #endif + #if HAS_W_MAX + #if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(W_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable"); + pciSetup(W_MAX_PIN); + #endif + #elif HAS_W_MIN + #if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(W_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable"); + pciSetup(W_MIN_PIN); + #endif + #endif #if HAS_X2_MAX #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT) _ATTACH(X2_MAX_PIN); diff --git a/Marlin/src/HAL/DUE/endstop_interrupts.h b/Marlin/src/HAL/DUE/endstop_interrupts.h index 9c7e2104882e..c1bbcb121bdc 100644 --- a/Marlin/src/HAL/DUE/endstop_interrupts.h +++ b/Marlin/src/HAL/DUE/endstop_interrupts.h @@ -70,4 +70,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/ESP32/endstop_interrupts.h b/Marlin/src/HAL/ESP32/endstop_interrupts.h index 4725df921b1a..05368646101e 100644 --- a/Marlin/src/HAL/ESP32/endstop_interrupts.h +++ b/Marlin/src/HAL/ESP32/endstop_interrupts.h @@ -65,4 +65,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/LPC1768/endstop_interrupts.h b/Marlin/src/HAL/LPC1768/endstop_interrupts.h index 23bd0cc982b2..e4ac17f60815 100644 --- a/Marlin/src/HAL/LPC1768/endstop_interrupts.h +++ b/Marlin/src/HAL/LPC1768/endstop_interrupts.h @@ -155,4 +155,37 @@ void setup_endstop_interrupts() { #endif _ATTACH(K_MIN_PIN); #endif + #if HAS_U_MAX + #if !LPC1768_PIN_INTERRUPT_M(U_MAX_PIN) + #error "U_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(U_MAX_PIN); + #elif HAS_U_MIN + #if !LPC1768_PIN_INTERRUPT_M(U_MIN_PIN) + #error "U_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(U_MIN_PIN); + #endif + #if HAS_V_MAX + #if !LPC1768_PIN_INTERRUPT_M(V_MAX_PIN) + #error "V_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(V_MAX_PIN); + #elif HAS_V_MIN + #if !LPC1768_PIN_INTERRUPT_M(V_MIN_PIN) + #error "V_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(V_MIN_PIN); + #endif + #if HAS_W_MAX + #if !LPC1768_PIN_INTERRUPT_M(W_MAX_PIN) + #error "W_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(W_MAX_PIN); + #elif HAS_W_MIN + #if !LPC1768_PIN_INTERRUPT_M(W_MIN_PIN) + #error "W_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(W_MIN_PIN); + #endif } diff --git a/Marlin/src/HAL/SAMD51/endstop_interrupts.h b/Marlin/src/HAL/SAMD51/endstop_interrupts.h index 61a06c0d4b42..2f02f404f5f1 100644 --- a/Marlin/src/HAL/SAMD51/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD51/endstop_interrupts.h @@ -60,6 +60,12 @@ #define MATCH_J_MIN_EILINE(P) TERN0(HAS_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) #define MATCH_K_MAX_EILINE(P) TERN0(HAS_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) #define MATCH_K_MIN_EILINE(P) TERN0(HAS_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) +#define MATCH_U_MAX_EILINE(P) TERN0(HAS_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) +#define MATCH_U_MIN_EILINE(P) TERN0(HAS_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) +#define MATCH_V_MAX_EILINE(P) TERN0(HAS_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) +#define MATCH_V_MIN_EILINE(P) TERN0(HAS_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) +#define MATCH_W_MAX_EILINE(P) TERN0(HAS_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) +#define MATCH_W_MIN_EILINE(P) TERN0(HAS_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) #define MATCH_Z2_MAX_EILINE(P) TERN0(HAS_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) #define MATCH_Z2_MIN_EILINE(P) TERN0(HAS_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) #define MATCH_Z3_MAX_EILINE(P) TERN0(HAS_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) @@ -75,6 +81,9 @@ && !MATCH_I_MAX_EILINE(P) && !MATCH_I_MIN_EILINE(P) \ && !MATCH_J_MAX_EILINE(P) && !MATCH_J_MIN_EILINE(P) \ && !MATCH_K_MAX_EILINE(P) && !MATCH_K_MIN_EILINE(P) \ + && !MATCH_U_MAX_EILINE(P) && !MATCH_U_MIN_EILINE(P) \ + && !MATCH_V_MAX_EILINE(P) && !MATCH_V_MIN_EILINE(P) \ + && !MATCH_W_MAX_EILINE(P) && !MATCH_W_MIN_EILINE(P) \ && !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \ && !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \ && !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \ @@ -199,4 +208,40 @@ void setup_endstop_interrupts() { #endif attachInterrupt(K_MIN_PIN, endstop_ISR, CHANGE); #endif + #if HAS_U_MAX + #if !AVAILABLE_EILINE(U_MAX_PIN) + #error "U_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(U_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_U_MIN + #if !AVAILABLE_EILINE(U_MIN_PIN) + #error "U_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(U_MIN_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_V_MAX + #if !AVAILABLE_EILINE(V_MAX_PIN) + #error "V_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(V_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_V_MIN + #if !AVAILABLE_EILINE(V_MIN_PIN) + #error "V_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(V_MIN_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_W_MAX + #if !AVAILABLE_EILINE(W_MAX_PIN) + #error "W_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(W_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_W_MIN + #if !AVAILABLE_EILINE(W_MIN_PIN) + #error "W_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(W_MIN_PIN, endstop_ISR, CHANGE); + #endif } diff --git a/Marlin/src/HAL/STM32/endstop_interrupts.h b/Marlin/src/HAL/STM32/endstop_interrupts.h index 90870881fe66..d2f20ba1c711 100644 --- a/Marlin/src/HAL/STM32/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32/endstop_interrupts.h @@ -52,4 +52,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/STM32F1/endstop_interrupts.h b/Marlin/src/HAL/STM32F1/endstop_interrupts.h index 4d7edb9496c1..a1ef8a8c3a36 100644 --- a/Marlin/src/HAL/STM32F1/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32F1/endstop_interrupts.h @@ -77,4 +77,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h index 9c7e2104882e..c1bbcb121bdc 100644 --- a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h @@ -70,4 +70,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h index a30024888535..48d3bbbfa17d 100644 --- a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h @@ -69,4 +69,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index be93bfcfb9d7..2570e6ebde1f 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -436,6 +436,9 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS)); TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS)); TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS)); + TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS)); + TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS)); + TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS)); TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers()); TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled()); @@ -993,6 +996,15 @@ inline void tmc_standby_setup() { #if PIN_EXISTS(K_STDBY) SET_INPUT_PULLDOWN(K_STDBY_PIN); #endif + #if PIN_EXISTS(U_STDBY) + SET_INPUT_PULLDOWN(U_STDBY_PIN); + #endif + #if PIN_EXISTS(V_STDBY) + SET_INPUT_PULLDOWN(V_STDBY_PIN); + #endif + #if PIN_EXISTS(W_STDBY) + SET_INPUT_PULLDOWN(W_STDBY_PIN); + #endif #if PIN_EXISTS(E0_STDBY) SET_INPUT_PULLDOWN(E0_STDBY_PIN); #endif diff --git a/Marlin/src/core/drivers.h b/Marlin/src/core/drivers.h index ac1f4a155de1..80262d513f38 100644 --- a/Marlin/src/core/drivers.h +++ b/Marlin/src/core/drivers.h @@ -63,6 +63,9 @@ #define AXIS_DRIVER_TYPE_I(T) _AXIS_DRIVER_TYPE(I,T) #define AXIS_DRIVER_TYPE_J(T) _AXIS_DRIVER_TYPE(J,T) #define AXIS_DRIVER_TYPE_K(T) _AXIS_DRIVER_TYPE(K,T) +#define AXIS_DRIVER_TYPE_U(T) _AXIS_DRIVER_TYPE(U,T) +#define AXIS_DRIVER_TYPE_V(T) _AXIS_DRIVER_TYPE(V,T) +#define AXIS_DRIVER_TYPE_W(T) _AXIS_DRIVER_TYPE(W,T) #define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T)) #define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T)) @@ -87,6 +90,7 @@ #define HAS_DRIVER(T) ( AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Z(T) \ || AXIS_DRIVER_TYPE_I(T) || AXIS_DRIVER_TYPE_J(T) || AXIS_DRIVER_TYPE_K(T) \ + || AXIS_DRIVER_TYPE_U(T) || AXIS_DRIVER_TYPE_V(T) || AXIS_DRIVER_TYPE_W(T) \ || AXIS_DRIVER_TYPE_X2(T) || AXIS_DRIVER_TYPE_Y2(T) || AXIS_DRIVER_TYPE_Z2(T) \ || AXIS_DRIVER_TYPE_Z3(T) || AXIS_DRIVER_TYPE_Z4(T) || HAS_E_DRIVER(T) ) @@ -161,6 +165,7 @@ || AXIS_HAS_##T(Y) || AXIS_HAS_##T(Y2) \ || AXIS_HAS_##T(Z) || AXIS_HAS_##T(Z2) || AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) \ || AXIS_HAS_##T(I) || AXIS_HAS_##T(J) || AXIS_HAS_##T(K) \ + || AXIS_HAS_##T(U) || AXIS_HAS_##T(V) || AXIS_HAS_##T(W) \ || E_AXIS_HAS(T) ) #if ANY_AXIS_HAS(STEALTHCHOP) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 8e0784f70d76..89c0babc2568 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -444,6 +444,54 @@ #define STR_K "" #endif +#if HAS_U_AXIS + #if AXIS7_NAME == 'U' + #define STR_U "U" + #define STR_U_MIN "u_min" + #define STR_U_MAX "u_max" + #elif AXIS7_NAME == 'V' + #define STR_U "V" + #define STR_U_MIN "v_min" + #define STR_U_MAX "v_max" + #elif AXIS7_NAME == 'W' + #define STR_U "W" + #define STR_U_MIN "w_min" + #define STR_U_MAX "w_max" + #else + #error "AXIS7_NAME can only be one of 'U', 'V', or 'W'." + #endif +#else + #define STR_U "" +#endif + +#if HAS_V_AXIS + #if AXIS8_NAME == 'V' + #define STR_V "V" + #define STR_V_MIN "v_min" + #define STR_V_MAX "v_max" + #elif AXIS8_NAME == 'W' + #define STR_V "W" + #define STR_V_MIN "w_min" + #define STR_V_MAX "w_max" + #else + #error "AXIS8_NAME can only be one of 'V', or 'W'." + #endif +#else + #define STR_V "" +#endif + +#if HAS_W_AXIS + #if AXIS9_NAME == 'W' + #define STR_W "W" + #define STR_W_MIN "w_min" + #define STR_W_MAX "w_max" + #else + #error "AXIS9_NAME can only be 'W'." + #endif +#else + #define STR_W "" +#endif + #if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL) // Custom characters defined in the first 8 characters of the LCD diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 31808586cf0d..629486d85f43 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -39,24 +39,36 @@ #define _ISTOP_ 0x04 #define _JSTOP_ 0x05 #define _KSTOP_ 0x06 +#define _USTOP_ 0x07 +#define _VSTOP_ 0x08 +#define _WSTOP_ 0x09 #define _XMIN_ 0x11 #define _YMIN_ 0x12 #define _ZMIN_ 0x13 #define _IMIN_ 0x14 #define _JMIN_ 0x15 #define _KMIN_ 0x16 +#define _UMIN_ 0x17 +#define _VMIN_ 0x18 +#define _WMIN_ 0x19 #define _XMAX_ 0x21 #define _YMAX_ 0x22 #define _ZMAX_ 0x23 #define _IMAX_ 0x24 #define _JMAX_ 0x25 #define _KMAX_ 0x26 +#define _UMAX_ 0x27 +#define _VMAX_ 0x28 +#define _WMAX_ 0x29 #define _XDIAG_ 0x31 #define _YDIAG_ 0x32 #define _ZDIAG_ 0x33 #define _IDIAG_ 0x34 #define _JDIAG_ 0x35 #define _KDIAG_ 0x36 +#define _UDIAG_ 0x37 +#define _VDIAG_ 0x38 +#define _WDIAG_ 0x39 #define _E0DIAG_ 0xE0 #define _E1DIAG_ 0xE1 #define _E2DIAG_ 0xE2 @@ -350,7 +362,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/serial.cpp b/Marlin/src/core/serial.cpp index 562cddbaa07a..819b06968cf0 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -32,14 +32,18 @@ uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE; // Commonly-used strings in serial output PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E"); +PGMSTR(U_STR, STR_U); PGMSTR(V_STR, STR_V); PGMSTR(W_STR, STR_W); PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:"); +PGMSTR(U_LBL, STR_U ":"); PGMSTR(V_LBL, STR_V ":"); PGMSTR(W_LBL, STR_W ":"); PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); PGMSTR(I_STR, STR_I); PGMSTR(J_STR, STR_J); PGMSTR(K_STR, STR_K); PGMSTR(I_LBL, STR_I ":"); PGMSTR(J_LBL, STR_J ":"); PGMSTR(K_LBL, STR_K ":"); PGMSTR(SP_I_STR, " " STR_I); PGMSTR(SP_J_STR, " " STR_J); PGMSTR(SP_K_STR, " " STR_K); +PGMSTR(SP_U_STR, " " STR_U); PGMSTR(SP_V_STR, " " STR_V); PGMSTR(SP_W_STR, " " STR_W); PGMSTR(SP_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":"); +PGMSTR(SP_U_LBL, " " STR_U ":"); PGMSTR(SP_V_LBL, " " STR_V ":"); PGMSTR(SP_W_LBL, " " STR_W ":"); // Hook Meatpack if it's enabled on the first leaf #if ENABLED(MEATPACK_ON_SERIAL_PORT_1) @@ -102,10 +106,10 @@ void print_bin(uint16_t val) { } } -void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) { +void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) { if (prefix) serial_print(prefix); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k) + LIST_N(DOUBLE(NUM_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k, SP_U_STR, u, SP_V_STR, v, SP_W_STR, w) ); if (suffix) serial_print(suffix); else SERIAL_EOL(); } diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 98e82b6d7281..2998fe803fdd 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -29,17 +29,12 @@ #endif // Commonly-used strings in serial output -extern const char NUL_STR[], - SP_X_STR[], SP_Y_STR[], SP_Z_STR[], - SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_E_STR[], - SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[], - SP_I_STR[], SP_J_STR[], SP_K_STR[], - SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], - SP_P_STR[], SP_T_STR[], - X_STR[], Y_STR[], Z_STR[], E_STR[], - I_STR[], J_STR[], K_STR[], - X_LBL[], Y_LBL[], Z_LBL[], E_LBL[], - I_LBL[], J_LBL[], K_LBL[]; +extern const char NUL_STR[], SP_P_STR[], SP_T_STR[], + SP_A_STR[], SP_B_STR[], SP_C_STR[], + SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_I_STR[], SP_J_STR[], SP_K_STR[], SP_U_STR[], SP_V_STR[], SP_W_STR[], SP_E_STR[], + SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], SP_U_LBL[], SP_V_LBL[], SP_W_LBL[], SP_E_LBL[], + X_STR[], Y_STR[], Z_STR[], I_STR[], J_STR[], K_STR[], U_STR[], V_STR[], W_STR[], E_STR[], + X_LBL[], Y_LBL[], Z_LBL[], I_LBL[], J_LBL[], K_LBL[], U_LBL[], V_LBL[], W_LBL[], E_LBL[]; // // Debugging flags for use by M111 @@ -348,10 +343,10 @@ void serial_spaces(uint8_t count); void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2) void print_bin(const uint16_t val); -void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); +void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) { - print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix); + print_pos(NUM_AXIS_ELEM(xyz), prefix, suffix); } #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 045ca3589f4c..47a126f165cf 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -36,23 +36,33 @@ struct IF { typedef R type; }; template struct IF { typedef L type; }; -#define LINEAR_AXIS_GANG(V...) GANG_N(LINEAR_AXES, V) -#define LINEAR_AXIS_CODE(V...) CODE_N(LINEAR_AXES, V) -#define LINEAR_AXIS_LIST(V...) LIST_N(LINEAR_AXES, V) -#define LINEAR_AXIS_ARRAY(V...) { LINEAR_AXIS_LIST(V) } -#define LINEAR_AXIS_ARGS(T...) LINEAR_AXIS_LIST(T x, T y, T z, T i, T j, T k) -#define LINEAR_AXIS_ELEM(O) LINEAR_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k) -#define LINEAR_AXIS_DEFS(T,V) LINEAR_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V) - -#define LOGICAL_AXIS_GANG(E,V...) LINEAR_AXIS_GANG(V) GANG_ITEM_E(E) -#define LOGICAL_AXIS_CODE(E,V...) LINEAR_AXIS_CODE(V) CODE_ITEM_E(E) -#define LOGICAL_AXIS_LIST(E,V...) LINEAR_AXIS_LIST(V) LIST_ITEM_E(E) +#define NUM_AXIS_GANG(V...) GANG_N(NUM_AXES, V) +#define NUM_AXIS_CODE(V...) CODE_N(NUM_AXES, V) +#define NUM_AXIS_LIST(V...) LIST_N(NUM_AXES, V) +#define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) } +#define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k, T u, T v, T w) +#define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) +#define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) + +#define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E) +#define LOGICAL_AXIS_CODE(E,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(E) +#define LOGICAL_AXIS_LIST(E,V...) NUM_AXIS_LIST(V) LIST_ITEM_E(E) #define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) } -#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k) -#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k) -#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V) +#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k, T u, T v, T w) +#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) +#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) -#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K) +#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) + +#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_ROTATIONAL_AXES + #define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V) +#endif #if HAS_EXTRUDERS #define LIST_ITEM_E(N) , N @@ -64,7 +74,7 @@ struct IF { typedef L type; }; #define GANG_ITEM_E(N) #endif -#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L) +#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L) // // Enumerated axis indices @@ -76,7 +86,7 @@ struct IF { typedef L type; }; enum AxisEnum : uint8_t { // Linear axes may be controlled directly or indirectly - LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS) + NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS) // Extruder axes may be considered distinctly #define _EN_ITEM(N) , E##N##_AXIS @@ -110,12 +120,13 @@ enum AxisEnum : uint8_t { }; typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t; +typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; // // Loop over axes // #define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS) -#define LOOP_LINEAR_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LINEAR_AXES) +#define LOOP_NUM_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, NUM_AXES) #define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES) #define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES) #define LOOP_DISTINCT_E(VAR) LOOP_L_N(VAR, DISTINCT_E) @@ -260,10 +271,10 @@ struct XYval { FI void set(const T px, const T py) { x = px; y = py; } FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; } #endif - #if LINEAR_AXES > XY - FI void set(const T (&arr)[LINEAR_AXES]) { x = arr[0]; y = arr[1]; } + #if NUM_AXES > XY + FI void set(const T (&arr)[NUM_AXES]) { x = arr[0]; y = arr[1]; } #endif - #if LOGICAL_AXES > LINEAR_AXES + #if LOGICAL_AXES > NUM_AXES FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; } #if DISTINCT_AXES > LOGICAL_AXES FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; } @@ -385,60 +396,69 @@ struct XYval { template struct XYZval { union { - struct { T LINEAR_AXIS_ARGS(); }; - struct { T LINEAR_AXIS_LIST(a, b, c, u, v, w); }; - T pos[LINEAR_AXES]; + struct { T NUM_AXIS_ARGS(); }; + struct { T NUM_AXIS_LIST(a, b, c, _i, _j, _k, _u, _v, _w); }; + T pos[NUM_AXES]; }; // Set all to 0 - FI void reset() { LINEAR_AXIS_GANG(x =, y =, z =, i =, j =, k =) 0; } + FI void reset() { NUM_AXIS_GANG(x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; } // Setters taking struct types and arrays FI void set(const T px) { x = px; } FI void set(const T px, const T py) { x = px; y = py; } FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } - FI void set(const XYval pxy, const T pz) { LINEAR_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); } + FI void set(const XYval pxy, const T pz) { NUM_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP); } FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; } #if HAS_Z_AXIS - FI void set(const T (&arr)[LINEAR_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } - FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); } + FI void set(const T (&arr)[NUM_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } + FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); } #endif - #if LOGICAL_AXES > LINEAR_AXES - FI void set(const T (&arr)[LOGICAL_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } - FI void set(LOGICAL_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); } + #if LOGICAL_AXES > NUM_AXES + FI void set(const T (&arr)[LOGICAL_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } + FI void set(LOGICAL_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); } #if DISTINCT_AXES > LOGICAL_AXES - FI void set(const T (&arr)[DISTINCT_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } + FI void set(const T (&arr)[DISTINCT_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } #endif #endif #if HAS_I_AXIS - FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } + FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } #endif #if HAS_J_AXIS - FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } + FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } #endif #if HAS_K_AXIS FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } #endif + #if HAS_U_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; } + #endif + #if HAS_V_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; } + #endif + #if HAS_W_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; } + #endif // Length reduced to one dimension - FI T magnitude() const { return (T)sqrtf(LINEAR_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); } + FI T magnitude() const { return (T)sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); } // Pointer to the data as a simple array FI operator T* () { return pos; } // If any element is true then it's true - FI operator bool() { return LINEAR_AXIS_GANG(x, || y, || z, || i, || j, || k); } + FI operator bool() { return NUM_AXIS_GANG(x, || y, || z, || i, || j, || k, || u, || v, || w); } // Explicit copy and copies with conversion FI XYZval copy() const { XYZval o = *this; return o; } - FI XYZval ABS() const { return LINEAR_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); } - FI XYZval asInt() { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZval asInt() const { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZval asLong() { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZval asLong() const { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZval ROUNDL() { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZval ROUNDL() const { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZval asFloat() { return LINEAR_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZval asFloat() const { return LINEAR_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZval reciprocal() const { return LINEAR_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); } + FI XYZval ABS() const { return NUM_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); } + FI XYZval asInt() { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZval asInt() const { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZval asLong() { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZval asLong() const { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZval ROUNDL() { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZval ROUNDL() const { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZval asFloat() { return NUM_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZval asFloat() const { return NUM_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZval reciprocal() const { return NUM_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); } // Marlin workspace shifting is done with G92 and M206 FI XYZval asLogical() const { XYZval o = asFloat(); toLogical(o); return o; } @@ -449,78 +469,78 @@ struct XYZval { FI operator const XYval&() const { return *(const XYval*)this; } // Cast to a type with more fields by making a new object - FI operator XYZEval() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); } + FI operator XYZEval() const { return NUM_AXIS_ARRAY(x, y, z, i, j, k, u, v, w); } // Accessor via an AxisEnum (or any integer) [index] FI T& operator[](const int n) { return pos[n]; } FI const T& operator[](const int n) const { return pos[n]; } // Assignment operator overrides do the expected thing - FI XYZval& operator= (const T v) { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; } + FI XYZval& operator= (const T v) { set(ARRAY_N_1(NUM_AXES, v)); return *this; } FI XYZval& operator= (const XYval &rs) { set(rs.x, rs.y ); return *this; } - FI XYZval& operator= (const XYZEval &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; } + FI XYZval& operator= (const XYZEval &rs) { set(NUM_AXIS_ELEM(rs)); return *this; } // Override other operators to get intuitive behaviors - FI XYZval operator+ (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator+ (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator- (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator- (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator* (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator* (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator/ (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator/ (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator+ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator+ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator- (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator- (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator* (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator* (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator/ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator/ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator+ (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator+ (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator- (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator- (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator* (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator* (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator/ (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator/ (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator* (const float &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const float &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator/ (const float &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const float &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator>>(const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZval operator>>(const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZval operator<<(const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI XYZval operator<<(const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI const XYZval operator-() const { XYZval o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; } - FI XYZval operator-() { XYZval o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; } + FI XYZval operator+ (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator+ (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator- (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator- (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator* (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator* (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator/ (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator/ (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator+ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator+ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator- (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator- (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator* (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator* (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator/ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator/ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator+ (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator+ (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator- (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator- (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator* (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator* (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator/ (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator/ (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator* (const float &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const float &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const int &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator/ (const float &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const float &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const int &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator>>(const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZval operator>>(const int &v) { XYZval ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZval operator<<(const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI XYZval operator<<(const int &v) { XYZval ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI const XYZval operator-() const { XYZval o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; } + FI XYZval operator-() { XYZval o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; } // Modifier operators - FI XYZval& operator+=(const XYval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator-=(const XYval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator*=(const XYval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator/=(const XYval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator+=(const XYZval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZval& operator-=(const XYZval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZval& operator*=(const XYZval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZval& operator/=(const XYZval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZval& operator+=(const XYZEval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZval& operator-=(const XYZEval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZval& operator*=(const XYZEval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZval& operator/=(const XYZEval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZval& operator*=(const float &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZval& operator*=(const int &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZval& operator>>=(const int &v) { LINEAR_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; } - FI XYZval& operator<<=(const int &v) { LINEAR_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; } + FI XYZval& operator+=(const XYval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator-=(const XYval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator*=(const XYval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator/=(const XYval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator+=(const XYZval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZval& operator-=(const XYZval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZval& operator*=(const XYZval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZval& operator/=(const XYZval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZval& operator+=(const XYZEval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZval& operator-=(const XYZEval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZval& operator*=(const XYZEval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZval& operator/=(const XYZEval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZval& operator*=(const float &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZval& operator*=(const int &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZval& operator>>=(const int &v) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; } + FI XYZval& operator<<=(const int &v) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; } // Exact comparisons. For floats a "NEAR" operation may be better. - FI bool operator==(const XYZEval &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } - FI bool operator==(const XYZEval &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } + FI bool operator==(const XYZEval &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } + FI bool operator==(const XYZEval &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator!=(const XYZEval &rs) { return !operator==(rs); } FI bool operator!=(const XYZEval &rs) const { return !operator==(rs); } }; @@ -532,56 +552,66 @@ template struct XYZEval { union { struct { T LOGICAL_AXIS_ARGS(); }; - struct { T LOGICAL_AXIS_LIST(_e, a, b, c, u, v, w); }; + struct { T LOGICAL_AXIS_LIST(_e, a, b, c, _i, _j, _k, _u, _v, _w); }; T pos[LOGICAL_AXES]; }; // Reset all to 0 - FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =) 0; } + FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; } // Setters for some number of linear axes, not all - FI void set(const T px) { x = px; } - FI void set(const T px, const T py) { x = px; y = py; } + FI void set(const T px) { x = px; } + FI void set(const T px, const T py) { x = px; y = py; } #if HAS_I_AXIS - FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } + FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } #endif #if HAS_J_AXIS - FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } + FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } #endif #if HAS_K_AXIS - FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } + FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } + #endif + #if HAS_U_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; } #endif + #if HAS_V_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; } + #endif + #if HAS_W_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pm; v = pv; } + #endif + // Setters taking struct types and arrays - FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } - FI void set(const XYZval pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); } + FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } + FI void set(const XYZval pxyz) { set(NUM_AXIS_ELEM(pxyz)); } #if HAS_Z_AXIS - FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k); } + FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); } #endif - FI void set(const XYval pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); } - #if LOGICAL_AXES > LINEAR_AXES + FI void set(const XYval pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); } + #if LOGICAL_AXES > NUM_AXES FI void set(const XYval pxy, const T pz, const T pe) { set(pxy, pz); e = pe; } - FI void set(const XYZval pxyz, const T pe) { set(pxyz); e = pe; } - FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, u = i, v = j, w = k); } + FI void set(const XYZval pxyz, const T pe) { set(pxyz); e = pe; } + FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); } #endif // Length reduced to one dimension - FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); } + FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); } // Pointer to the data as a simple array FI operator T* () { return pos; } // If any element is true then it's true - FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k); } + FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); } // Explicit copy and copies with conversion - FI XYZEval copy() const { XYZEval o = *this; return o; } - FI XYZEval ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); } - FI XYZEval asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZEval asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZEval asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZEval asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZEval ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZEval ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZEval asFloat() { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZEval asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZEval reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); } + FI XYZEval copy() const { XYZEval v = *this; return v; } + FI XYZEval ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); } + FI XYZEval asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZEval asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZEval asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZEval asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZEval ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZEval ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZEval asFloat() { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZEval asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZEval reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); } // Marlin workspace shifting is done with G92 and M206 FI XYZEval asLogical() const { XYZEval o = asFloat(); toLogical(o); return o; } @@ -598,9 +628,9 @@ struct XYZEval { FI const T& operator[](const int n) const { return pos[n]; } // Assignment operator overrides do the expected thing - FI XYZEval& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; } + FI XYZEval& operator= (const T v) { set(LIST_N_1(NUM_AXES, v)); return *this; } FI XYZEval& operator= (const XYval &rs) { set(rs.x, rs.y); return *this; } - FI XYZEval& operator= (const XYZval &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; } + FI XYZEval& operator= (const XYZval &rs) { set(NUM_AXIS_ELEM(rs)); return *this; } // Override other operators to get intuitive behaviors FI XYZEval operator+ (const XYval &rs) const { XYZEval ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } @@ -611,57 +641,57 @@ struct XYZEval { FI XYZEval operator* (const XYval &rs) { XYZEval ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZEval operator/ (const XYval &rs) const { XYZEval ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZEval operator/ (const XYval &rs) { XYZEval ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } - FI XYZEval operator+ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator+ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator- (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator- (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator* (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator* (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator/ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator/ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator+ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator+ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator- (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator- (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator* (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator* (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator/ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator/ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator* (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator/ (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator>>(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZEval operator>>(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZEval operator<<(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI XYZEval operator<<(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI const XYZEval operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); } - FI XYZEval operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); } + FI XYZEval operator+ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator+ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator- (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator- (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator* (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator* (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator/ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator/ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator+ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator+ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator- (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator- (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator* (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator* (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator/ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator/ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator* (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator/ (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator>>(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZEval operator>>(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZEval operator<<(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI XYZEval operator<<(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI const XYZEval operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); } + FI XYZEval operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); } // Modifier operators FI XYZEval& operator+=(const XYval &rs) { x += rs.x; y += rs.y; return *this; } FI XYZEval& operator-=(const XYval &rs) { x -= rs.x; y -= rs.y; return *this; } FI XYZEval& operator*=(const XYval &rs) { x *= rs.x; y *= rs.y; return *this; } FI XYZEval& operator/=(const XYval &rs) { x /= rs.x; y /= rs.y; return *this; } - FI XYZEval& operator+=(const XYZval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZEval& operator-=(const XYZval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZEval& operator*=(const XYZval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZEval& operator/=(const XYZval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZEval& operator+=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZEval& operator-=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZEval& operator*=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZEval& operator/=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZEval& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZEval& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; } - FI XYZEval& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; } + FI XYZEval& operator+=(const XYZval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZEval& operator-=(const XYZval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZEval& operator*=(const XYZval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZEval& operator/=(const XYZval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZEval& operator+=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZEval& operator-=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZEval& operator*=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZEval& operator/=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZEval& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZEval& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; } + FI XYZEval& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; } // Exact comparisons. For floats a "NEAR" operation may be better. - FI bool operator==(const XYZval &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } - FI bool operator==(const XYZval &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } + FI bool operator==(const XYZval &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } + FI bool operator==(const XYZval &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator!=(const XYZval &rs) { return !operator==(rs); } FI bool operator!=(const XYZval &rs) const { return !operator==(rs); } }; diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp index 4e16e2693a4d..d30511ae4019 100644 --- a/Marlin/src/core/utility.cpp +++ b/Marlin/src/core/utility.cpp @@ -125,7 +125,7 @@ void safe_delay(millis_t ms) { #endif #if ABL_PLANAR SERIAL_ECHOPGM("ABL Adjustment"); - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { SERIAL_CHAR(' ', AXIS_CHAR(a)); serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]); } diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h index d248091ce575..b845cd0412a4 100644 --- a/Marlin/src/core/utility.h +++ b/Marlin/src/core/utility.h @@ -77,10 +77,13 @@ class restorer { // 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; } -const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME); - -#if LINEAR_AXES <= XYZ +// 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, AXIS7_NAME, AXIS8_NAME, AXIS9_NAME); +#if NUM_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', 'U', 'V', 'W'); #define AXIS_CHAR(A) axis_codes[A] + #define IAXIS_CHAR(A) iaxis_codes[A] #endif diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index 84382cf85680..876d28a8feb0 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -97,7 +97,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const const float f_corr = float(correction) / all_on; - LOOP_LINEAR_AXES(axis) { + LOOP_NUM_AXES(axis) { if (distance_mm[axis]) { const bool reverse = TEST(dm, axis); @@ -145,7 +145,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 >= LINEAR_AXES) return 0; + if (axis >= NUM_AXES) return 0; const bool reverse = TEST(last_direction_bits, axis); @@ -165,11 +165,11 @@ class Backlash::StepAdjuster { xyz_long_t applied_steps; public: StepAdjuster() { - LOOP_LINEAR_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); } ~StepAdjuster() { // after backlash compensation parameter changes, ensure applied step count does not change - LOOP_LINEAR_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; + LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; } }; diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 0d00296b5b60..9d2aaf82470e 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -317,6 +317,42 @@ void unified_bed_leveling::G29() { // Send 'N' to force homing before G29 (internal only) if (axes_should_home() || parser.seen_test('N')) gcode.home_all_axes(); TERN_(HAS_MULTI_HOTEND, if (active_extruder != 0) tool_change(0, true)); + + // Position bed horizontally and Z probe vertically. + #if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \ + || defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \ + || defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W) + xyze_pos_t safe_position = current_position; + #ifdef SAFE_BED_LEVELING_START_X + safe_position.x = SAFE_BED_LEVELING_START_X; + #endif + #ifdef SAFE_BED_LEVELING_START_Y + safe_position.y = SAFE_BED_LEVELING_START_Y; + #endif + #ifdef SAFE_BED_LEVELING_START_Z + safe_position.z = SAFE_BED_LEVELING_START_Z; + #endif + #ifdef SAFE_BED_LEVELING_START_I + safe_position.i = SAFE_BED_LEVELING_START_I; + #endif + #ifdef SAFE_BED_LEVELING_START_J + safe_position.j = SAFE_BED_LEVELING_START_J; + #endif + #ifdef SAFE_BED_LEVELING_START_K + safe_position.k = SAFE_BED_LEVELING_START_K; + #endif + #ifdef SAFE_BED_LEVELING_START_U + safe_position.u = SAFE_BED_LEVELING_START_U; + #endif + #ifdef SAFE_BED_LEVELING_START_V + safe_position.v = SAFE_BED_LEVELING_START_V; + #endif + #ifdef SAFE_BED_LEVELING_START_W + safe_position.w = SAFE_BED_LEVELING_START_W; + #endif + + do_blocking_move_to(safe_position); + #endif } // Invalidate one or more nearby mesh points, possibly all. diff --git a/Marlin/src/feature/encoder_i2c.cpp b/Marlin/src/feature/encoder_i2c.cpp index fa14c9ac715d..c1dbb906fd92 100644 --- a/Marlin/src/feature/encoder_i2c.cpp +++ b/Marlin/src/feature/encoder_i2c.cpp @@ -337,7 +337,7 @@ bool I2CPositionEncoder::test_axis() { ec = false; xyze_pos_t startCoord, endCoord; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); } @@ -395,7 +395,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) { travelDistance = endDistance - startDistance; xyze_pos_t startCoord, endCoord; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); } diff --git a/Marlin/src/feature/joystick.cpp b/Marlin/src/feature/joystick.cpp index c68a2b8df90a..daa642d32e36 100644 --- a/Marlin/src/feature/joystick.cpp +++ b/Marlin/src/feature/joystick.cpp @@ -163,7 +163,7 @@ Joystick joystick; // norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate] xyz_float_t move_dist{0}; float hypot2 = 0; - LOOP_LINEAR_AXES(i) if (norm_jog[i]) { + LOOP_NUM_AXES(i) if (norm_jog[i]) { move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i]; hypot2 += sq(move_dist[i]); } diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 74008ed55a55..0fc195e7dd5e 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -562,7 +562,7 @@ void PrintJobRecovery::resume() { TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset); TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift); #if HAS_HOME_OFFSET || HAS_POSITION_SHIFT - LOOP_LINEAR_AXES(i) update_workspace_offset((AxisEnum)i); + LOOP_NUM_AXES(i) update_workspace_offset((AxisEnum)i); #endif // Relative axis modes @@ -612,7 +612,7 @@ void PrintJobRecovery::resume() { #if HAS_HOME_OFFSET DEBUG_ECHOPGM("home_offset: "); - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (i) DEBUG_CHAR(','); DEBUG_DECIMAL(info.home_offset[i]); } @@ -621,7 +621,7 @@ void PrintJobRecovery::resume() { #if HAS_POSITION_SHIFT DEBUG_ECHOPGM("position_shift: "); - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (i) DEBUG_CHAR(','); DEBUG_DECIMAL(info.position_shift[i]); } diff --git a/Marlin/src/feature/stepper_driver_safety.cpp b/Marlin/src/feature/stepper_driver_safety.cpp index 11b90954b4f5..b8762da9b0c0 100644 --- a/Marlin/src/feature/stepper_driver_safety.cpp +++ b/Marlin/src/feature/stepper_driver_safety.cpp @@ -65,15 +65,18 @@ void stepper_driver_backward_check() { TEST_BACKWARD(I, 8); TEST_BACKWARD(J, 9); TEST_BACKWARD(K, 10); - - TEST_BACKWARD(E0, 11); - TEST_BACKWARD(E1, 12); - TEST_BACKWARD(E2, 13); - TEST_BACKWARD(E3, 14); - TEST_BACKWARD(E4, 15); - TEST_BACKWARD(E5, 16); - TEST_BACKWARD(E6, 17); - TEST_BACKWARD(E7, 18); + TEST_BACKWARD(U, 11); + TEST_BACKWARD(V, 12); + TEST_BACKWARD(W, 13); + + TEST_BACKWARD(E0, 14); + TEST_BACKWARD(E1, 15); + TEST_BACKWARD(E2, 16); + TEST_BACKWARD(E3, 17); + TEST_BACKWARD(E4, 18); + TEST_BACKWARD(E5, 19); + TEST_BACKWARD(E6, 20); + TEST_BACKWARD(E7, 21); if (!axis_plug_backward) WRITE(SAFE_POWER_PIN, HIGH); @@ -103,15 +106,18 @@ void stepper_driver_backward_report() { REPORT_BACKWARD(I, 8); REPORT_BACKWARD(J, 9); REPORT_BACKWARD(K, 10); - - REPORT_BACKWARD(E0, 11); - REPORT_BACKWARD(E1, 12); - REPORT_BACKWARD(E2, 13); - REPORT_BACKWARD(E3, 14); - REPORT_BACKWARD(E4, 15); - REPORT_BACKWARD(E5, 16); - REPORT_BACKWARD(E6, 17); - REPORT_BACKWARD(E7, 18); + REPORT_BACKWARD(U, 11); + REPORT_BACKWARD(V, 12); + REPORT_BACKWARD(W, 13); + + REPORT_BACKWARD(E0, 14); + REPORT_BACKWARD(E1, 15); + REPORT_BACKWARD(E2, 16); + REPORT_BACKWARD(E3, 17); + REPORT_BACKWARD(E4, 18); + REPORT_BACKWARD(E5, 19); + REPORT_BACKWARD(E6, 20); + REPORT_BACKWARD(E7, 21); } #endif // HAS_DRIVER_SAFE_POWER_PROTECT diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index c69772bebcaf..cb970c7ebc87 100644 --- a/Marlin/src/feature/tmc_util.cpp +++ b/Marlin/src/feature/tmc_util.cpp @@ -429,6 +429,18 @@ if (monitor_tmc_driver(stepperK, need_update_error_counters, need_debug_reporting)) step_current_down(stepperK); #endif + #if AXIS_IS_TMC(U) + if (monitor_tmc_driver(stepperU, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperU); + #endif + #if AXIS_IS_TMC(V) + if (monitor_tmc_driver(stepperV, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperV); + #endif + #if AXIS_IS_TMC(W) + if (monitor_tmc_driver(stepperW, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperW); + #endif #if AXIS_IS_TMC(E0) (void)monitor_tmc_driver(stepperE0, need_update_error_counters, need_debug_reporting); @@ -809,6 +821,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_status(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_status(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_status(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_status(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -883,6 +904,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_parse_drv_status(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_parse_drv_status(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_parse_drv_status(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_parse_drv_status(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1088,6 +1118,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_get_registers(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_get_registers(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_get_registers(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_get_registers(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1244,6 +1283,15 @@ void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) { #if AXIS_IS_TMC(K) if (k) axis_connection += test_connection(stepperK); #endif + #if AXIS_IS_TMC(U) + if (u) axis_connection += test_connection(stepperU); + #endif + #if AXIS_IS_TMC(V) + if (v) axis_connection += test_connection(stepperV); + #endif + #if AXIS_IS_TMC(W) + if (w) axis_connection += test_connection(stepperW); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1313,6 +1361,15 @@ void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) { #if AXIS_HAS_SPI(K) SET_CS_PIN(K); #endif + #if AXIS_HAS_SPI(U) + SET_CS_PIN(U); + #endif + #if AXIS_HAS_SPI(V) + SET_CS_PIN(V); + #endif + #if AXIS_HAS_SPI(W) + SET_CS_PIN(W); + #endif #if AXIS_HAS_SPI(E0) SET_CS_PIN(E0); #endif diff --git a/Marlin/src/feature/tmc_util.h b/Marlin/src/feature/tmc_util.h index fc333b09dd99..c10bab62749d 100644 --- a/Marlin/src/feature/tmc_util.h +++ b/Marlin/src/feature/tmc_util.h @@ -348,7 +348,7 @@ void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true)); #if USE_SENSORLESS // Track enabled status of stealthChop and only re-enable where applicable - struct sensorless_t { bool LINEAR_AXIS_ARGS(), x2, y2, z2, z3, z4; }; + struct sensorless_t { bool NUM_AXIS_ARGS(), x2, y2, z2, z3, z4; }; #if ENABLED(IMPROVE_HOMING_RELIABILITY) extern millis_t sg_guard_period; diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 61848c45bdba..ac8eff0e9515 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -437,6 +437,42 @@ G29_TYPE GcodeSuite::G29() { #endif } + // Position bed horizontally and Z probe vertically. + #if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \ + || defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \ + || defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W) + xyze_pos_t safe_position = current_position; + #ifdef SAFE_BED_LEVELING_START_X + safe_position.x = SAFE_BED_LEVELING_START_X; + #endif + #ifdef SAFE_BED_LEVELING_START_Y + safe_position.y = SAFE_BED_LEVELING_START_Y; + #endif + #ifdef SAFE_BED_LEVELING_START_Z + safe_position.z = SAFE_BED_LEVELING_START_Z; + #endif + #ifdef SAFE_BED_LEVELING_START_I + safe_position.i = SAFE_BED_LEVELING_START_I; + #endif + #ifdef SAFE_BED_LEVELING_START_J + safe_position.j = SAFE_BED_LEVELING_START_J; + #endif + #ifdef SAFE_BED_LEVELING_START_K + safe_position.k = SAFE_BED_LEVELING_START_K; + #endif + #ifdef SAFE_BED_LEVELING_START_U + safe_position.u = SAFE_BED_LEVELING_START_U; + #endif + #ifdef SAFE_BED_LEVELING_START_V + safe_position.v = SAFE_BED_LEVELING_START_V; + #endif + #ifdef SAFE_BED_LEVELING_START_W + safe_position.w = SAFE_BED_LEVELING_START_W; + #endif + + do_blocking_move_to(safe_position); + #endif + // Disable auto bed leveling during G29. // Be formal so G29 can be done successively without G28. if (!no_action) set_bed_leveling_enabled(false); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index 74843235f437..e04073b122c9 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -106,6 +106,43 @@ void GcodeSuite::G29() { queue.inject(parser.seen_test('N') ? F("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : F("G29S2")); TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart()); + + // Position bed horizontally and Z probe vertically. + #if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \ + || defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \ + || defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W) + xyze_pos_t safe_position = current_position; + #ifdef SAFE_BED_LEVELING_START_X + safe_position.x = SAFE_BED_LEVELING_START_X; + #endif + #ifdef SAFE_BED_LEVELING_START_Y + safe_position.y = SAFE_BED_LEVELING_START_Y; + #endif + #ifdef SAFE_BED_LEVELING_START_Z + safe_position.z = SAFE_BED_LEVELING_START_Z; + #endif + #ifdef SAFE_BED_LEVELING_START_I + safe_position.i = SAFE_BED_LEVELING_START_I; + #endif + #ifdef SAFE_BED_LEVELING_START_J + safe_position.j = SAFE_BED_LEVELING_START_J; + #endif + #ifdef SAFE_BED_LEVELING_START_K + safe_position.k = SAFE_BED_LEVELING_START_K; + #endif + #ifdef SAFE_BED_LEVELING_START_U + safe_position.u = SAFE_BED_LEVELING_START_U; + #endif + #ifdef SAFE_BED_LEVELING_START_V + safe_position.v = SAFE_BED_LEVELING_START_V; + #endif + #ifdef SAFE_BED_LEVELING_START_W + safe_position.w = SAFE_BED_LEVELING_START_W; + #endif + + do_blocking_move_to(safe_position); + #endif + return; } state = MeshNext; diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 681df55f209f..07896856a1cc 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -82,7 +82,7 @@ #if ENABLED(SENSORLESS_HOMING) sensorless_t stealth_states { - LINEAR_AXIS_LIST( + NUM_AXIS_LIST( TERN0(X_SENSORLESS, tmc_enable_stallguard(stepperX)), TERN0(Y_SENSORLESS, tmc_enable_stallguard(stepperY)), false, false, false, false @@ -214,7 +214,7 @@ void GcodeSuite::G28() { #if ENABLED(MARLIN_DEV_MODE) if (parser.seen_test('S')) { - LOOP_LINEAR_AXES(a) set_axis_is_at_home((AxisEnum)a); + LOOP_NUM_AXES(a) set_axis_is_at_home((AxisEnum)a); sync_plan_position(); SERIAL_ECHOLNPGM("Simulated Homing"); report_current_position(); @@ -258,7 +258,7 @@ void GcodeSuite::G28() { reset_stepper_timeout(); #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT) - #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z)) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) + #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2) || (ENABLED(DELTA) && HAS_CURRENT_HOME(Z)) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) || HAS_CURRENT_HOME(U) || HAS_CURRENT_HOME(V) || HAS_CURRENT_HOME(W) #define HAS_HOMING_CURRENT 1 #endif @@ -286,21 +286,6 @@ void GcodeSuite::G28() { stepperY2.rms_current(Y2_CURRENT_HOME); if (DEBUGGING(LEVELING)) debug_current(F(STR_Y2), tmc_save_current_Y2, Y2_CURRENT_HOME); #endif - #if HAS_CURRENT_HOME(I) - const int16_t tmc_save_current_I = stepperI.getMilliamps(); - stepperI.rms_current(I_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_I), tmc_save_current_I, I_CURRENT_HOME); - #endif - #if HAS_CURRENT_HOME(J) - const int16_t tmc_save_current_J = stepperJ.getMilliamps(); - stepperJ.rms_current(J_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_J), tmc_save_current_J, J_CURRENT_HOME); - #endif - #if HAS_CURRENT_HOME(K) - const int16_t tmc_save_current_K = stepperK.getMilliamps(); - stepperK.rms_current(K_CURRENT_HOME); - if (DEBUGGING(LEVELING)) debug_current(F(STR_K), tmc_save_current_K, K_CURRENT_HOME); - #endif #if HAS_CURRENT_HOME(Z) && ENABLED(DELTA) const int16_t tmc_save_current_Z = stepperZ.getMilliamps(); stepperZ.rms_current(Z_CURRENT_HOME); @@ -321,6 +306,21 @@ void GcodeSuite::G28() { stepperK.rms_current(K_CURRENT_HOME); if (DEBUGGING(LEVELING)) debug_current(F(STR_K), tmc_save_current_K, K_CURRENT_HOME); #endif + #if HAS_CURRENT_HOME(U) + const int16_t tmc_save_current_U = stepperU.getMilliamps(); + stepperU.rms_current(U_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(STR_U), tmc_save_current_U, U_CURRENT_HOME); + #endif + #if HAS_CURRENT_HOME(V) + const int16_t tmc_save_current_V = stepperV.getMilliamps(); + stepperV.rms_current(V_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(STR_V), tmc_save_current_V, V_CURRENT_HOME); + #endif + #if HAS_CURRENT_HOME(W) + const int16_t tmc_save_current_W = stepperW.getMilliamps(); + stepperW.rms_current(W_CURRENT_HOME); + if (DEBUGGING(LEVELING)) debug_current(F(STR_W), tmc_save_current_W, W_CURRENT_HOME); + #endif #endif #if ENABLED(IMPROVE_HOMING_RELIABILITY) @@ -364,23 +364,28 @@ void GcodeSuite::G28() { #define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS)))) const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')), - LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing + NUM_AXIS_LIST( // Other axes should be homed before Z safe-homing needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED - needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K) + needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K), + needU = _UNSAFE(U), needV = _UNSAFE(V), needW = _UNSAFE(W) ), - LINEAR_AXIS_LIST( // Home each axis if needed or flagged + NUM_AXIS_LIST( // Home each axis if needed or flagged homeX = needX || parser.seen_test('X'), homeY = needY || parser.seen_test('Y'), homeZZ = homeZ, - homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME) + homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), + homeK = needK || parser.seen_test(AXIS6_NAME), homeU = needU || parser.seen_test(AXIS7_NAME), + homeV = needV || parser.seen_test(AXIS8_NAME), homeW = needW || parser.seen_test(AXIS9_NAME), ), - home_all = LINEAR_AXIS_GANG( // Home-all if all or none are flagged + home_all = NUM_AXIS_GANG( // Home-all if all or none are flagged homeX == homeX, && homeY == homeX, && homeZ == homeX, - && homeI == homeX, && homeJ == homeX, && homeK == homeX + && homeI == homeX, && homeJ == homeX, && homeK == homeX, + && homeU == homeX, && homeV == homeX, && homeW == homeX ), - LINEAR_AXIS_LIST( + NUM_AXIS_LIST( doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ, - doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK + doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK, + doU = home_all || homeU, doV = home_all || homeV, doW = home_all || homeW ); #if HAS_Z_AXIS @@ -394,7 +399,7 @@ void GcodeSuite::G28() { const bool seenR = parser.seenval('R'); const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT; - if (z_homing_height && (seenR || LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) { + if (z_homing_height && (seenR || NUM_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK, || doU, || doV, || doW))) { // Raise Z before homing any other axes and z is not already high enough (never lower z) if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height); do_z_clearance(z_homing_height); @@ -434,33 +439,53 @@ void GcodeSuite::G28() { #endif } + #if BOTH(FOAMCUTTER_XYUV, HAS_I_AXIS) + // Home I (after X) + if (doI) homeaxis(I_AXIS); + #endif + // Home Y (after X) if (DISABLED(HOME_Y_BEFORE_X) && doY) homeaxis(Y_AXIS); + #if BOTH(FOAMCUTTER_XYUV, HAS_J_AXIS) + // Home J (after Y) + if (doJ) homeaxis(J_AXIS); + #endif + TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state)); - // Home Z last if homing towards the bed - #if HAS_Z_AXIS && DISABLED(HOME_Z_FIRST) - if (doZ) { - #if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN) - stepper.set_all_z_lock(false); - stepper.set_separate_multi_axis(false); - #endif + #if ENABLED(FOAMCUTTER_XYUV) + // skip homing of unused Z axis for foamcutters + if (doZ) set_axis_is_at_home(Z_AXIS); + #else + // Home Z last if homing towards the bed + #if HAS_Z_AXIS && DISABLED(HOME_Z_FIRST) + if (doZ) { + #if EITHER(Z_MULTI_ENDSTOPS, Z_STEPPER_AUTO_ALIGN) + stepper.set_all_z_lock(false); + stepper.set_separate_multi_axis(false); + #endif + + #if ENABLED(Z_SAFE_HOMING) + if (TERN1(POWER_LOSS_RECOVERY, !parser.seen_test('H'))) home_z_safely(); else homeaxis(Z_AXIS); + #else + homeaxis(Z_AXIS); + #endif + probe.move_z_after_homing(); + } + #endif - #if ENABLED(Z_SAFE_HOMING) - if (TERN1(POWER_LOSS_RECOVERY, !parser.seen_test('H'))) home_z_safely(); else homeaxis(Z_AXIS); - #else - homeaxis(Z_AXIS); - #endif - probe.move_z_after_homing(); - } + SECONDARY_AXIS_CODE( + if (doI) homeaxis(I_AXIS), + if (doJ) homeaxis(J_AXIS), + if (doK) homeaxis(K_AXIS), + if (doU) homeaxis(U_AXIS), + if (doV) homeaxis(V_AXIS), + if (doW) homeaxis(W_AXIS) + ); #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)); - sync_plan_position(); #endif @@ -542,6 +567,15 @@ void GcodeSuite::G28() { #if HAS_CURRENT_HOME(K) stepperK.rms_current(tmc_save_current_K); #endif + #if HAS_CURRENT_HOME(U) + stepperU.rms_current(tmc_save_current_U); + #endif + #if HAS_CURRENT_HOME(V) + stepperV.rms_current(tmc_save_current_V); + #endif + #if HAS_CURRENT_HOME(W) + stepperW.rms_current(tmc_save_current_W); + #endif #endif // HAS_HOMING_CURRENT ui.refresh(); @@ -562,7 +596,7 @@ void GcodeSuite::G28() { // If not, this will need a PROGMEM directive and an accessor. #define _EN_ITEM(N) , E_AXIS static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = { - LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS), + NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS), X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS REPEAT(E_STEPPERS, _EN_ITEM) }; diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 506f367947df..7f487abd6b87 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -343,7 +343,7 @@ static float auto_tune_a(const float dcr) { abc_float_t delta_e = { 0.0f }, delta_t = { 0.0f }; delta_t.reset(); - LOOP_LINEAR_AXES(axis) { + LOOP_NUM_AXES(axis) { delta_t[axis] = diff; calc_kinematics_diff_probe_points(z_pt, dcr, delta_e, delta_r, delta_t); delta_t[axis] = 0; @@ -536,7 +536,7 @@ void GcodeSuite::G33() { case 1: test_precision = 0.0f; // forced end - LOOP_LINEAR_AXES(axis) e_delta[axis] = +Z4(CEN); + LOOP_NUM_AXES(axis) e_delta[axis] = +Z4(CEN); break; case 2: @@ -584,14 +584,14 @@ void GcodeSuite::G33() { // Normalize angles to least-squares if (_angle_results) { float a_sum = 0.0f; - LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis]; - LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f; + LOOP_NUM_AXES(axis) a_sum += delta_tower_angle_trim[axis]; + LOOP_NUM_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f; } // adjust delta_height and endstops by the max amount const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c); delta_height -= z_temp; - LOOP_LINEAR_AXES(axis) delta_endstop_adj[axis] -= z_temp; + LOOP_NUM_AXES(axis) delta_endstop_adj[axis] -= z_temp; } recalc_delta_settings(); NOMORE(zero_std_dev_min, zero_std_dev); diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index a2dec64bc3a8..450a71511748 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -85,10 +85,19 @@ #if ALL(HAS_K_AXIS, CALIBRATION_MEASURE_KMIN, CALIBRATION_MEASURE_KMAX) #define HAS_K_CENTER 1 #endif +#if ALL(HAS_U_AXIS, CALIBRATION_MEASURE_UMIN, CALIBRATION_MEASURE_UMAX) + #define HAS_U_CENTER 1 +#endif +#if ALL(HAS_V_AXIS, CALIBRATION_MEASURE_VMIN, CALIBRATION_MEASURE_VMAX) + #define HAS_V_CENTER 1 +#endif +#if ALL(HAS_W_AXIS, CALIBRATION_MEASURE_WMIN, CALIBRATION_MEASURE_WMAX) + #define HAS_W_CENTER 1 +#endif 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, UMINIMUM, UMAXIMUM, VMINIMUM, VMAXIMUM, WMINIMUM, WMAXIMUM) }; static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER; @@ -282,6 +291,15 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t #if HAS_K_AXIS && AXIS_CAN_CALIBRATE(K) _PCASE(K); #endif + #if HAS_U_AXIS && AXIS_CAN_CALIBRATE(U) + _PCASE(U); + #endif + #if HAS_V_AXIS && AXIS_CAN_CALIBRATE(V) + _PCASE(V); + #endif + #if HAS_W_AXIS && AXIS_CAN_CALIBRATE(W) + _PCASE(W); + #endif default: return; } @@ -335,6 +353,12 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { TERN_(CALIBRATION_MEASURE_JMAX, probe_side(m, uncertainty, JMAXIMUM, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_KMIN, probe_side(m, uncertainty, KMINIMUM, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_KMAX, probe_side(m, uncertainty, KMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_UMIN, probe_side(m, uncertainty, UMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_UMAX, probe_side(m, uncertainty, UMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_VMIN, probe_side(m, uncertainty, VMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_VMAX, probe_side(m, uncertainty, VMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_WMIN, probe_side(m, uncertainty, WMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_WMAX, probe_side(m, uncertainty, WMAXIMUM, probe_top_at_edge)); // Compute the measured center of the calibration object. TERN_(HAS_X_CENTER, m.obj_center.x = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2); @@ -342,6 +366,9 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { TERN_(HAS_I_CENTER, m.obj_center.i = (m.obj_side[IMINIMUM] + m.obj_side[IMAXIMUM]) / 2); TERN_(HAS_J_CENTER, m.obj_center.j = (m.obj_side[JMINIMUM] + m.obj_side[JMAXIMUM]) / 2); TERN_(HAS_K_CENTER, m.obj_center.k = (m.obj_side[KMINIMUM] + m.obj_side[KMAXIMUM]) / 2); + TERN_(HAS_U_CENTER, m.obj_center.u = (m.obj_side[UMINIMUM] + m.obj_side[UMAXIMUM]) / 2); + TERN_(HAS_V_CENTER, m.obj_center.v = (m.obj_side[VMINIMUM] + m.obj_side[VMAXIMUM]) / 2); + TERN_(HAS_W_CENTER, m.obj_center.w = (m.obj_side[WMINIMUM] + m.obj_side[WMAXIMUM]) / 2); // Compute the outside diameter of the nozzle at the height // at which it makes contact with the calibration object @@ -352,13 +379,16 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { // The difference between the known and the measured location // of the calibration object is the positional error - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x), m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y), m.pos_error.z = true_center.z - m.obj_center.z, m.pos_error.i = TERN0(HAS_I_CENTER, true_center.i - m.obj_center.i), m.pos_error.j = TERN0(HAS_J_CENTER, true_center.j - m.obj_center.j), - m.pos_error.k = TERN0(HAS_K_CENTER, true_center.k - m.obj_center.k) + m.pos_error.k = TERN0(HAS_K_CENTER, true_center.k - m.obj_center.k), + m.pos_error.u = TERN0(HAS_U_CENTER, true_center.u - m.obj_center.u), + m.pos_error.v = TERN0(HAS_V_CENTER, true_center.v - m.obj_center.v), + m.pos_error.w = TERN0(HAS_W_CENTER, true_center.w - m.obj_center.w) ); } @@ -406,6 +436,30 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM(" " STR_K_MAX ": ", m.obj_side[KMAXIMUM]); #endif #endif + #if HAS_U_AXIS + #if ENABLED(CALIBRATION_MEASURE_UMIN) + SERIAL_ECHOLNPAIR(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_UMAX) + SERIAL_ECHOLNPAIR(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]); + #endif + #endif + #if HAS_V_AXIS + #if ENABLED(CALIBRATION_MEASURE_VMIN) + SERIAL_ECHOLNPAIR(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_VMAX) + SERIAL_ECHOLNPAIR(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]); + #endif + #endif + #if HAS_W_AXIS + #if ENABLED(CALIBRATION_MEASURE_WMIN) + SERIAL_ECHOLNPAIR(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_WMAX) + SERIAL_ECHOLNPAIR(" " STR_W_MAX ": ", m.obj_side[WMAXIMUM]); + #endif + #endif SERIAL_EOL(); } @@ -427,6 +481,15 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { #if HAS_K_CENTER SERIAL_ECHOLNPGM_P(SP_K_STR, m.obj_center.k); #endif + #if HAS_U_CENTER + SERIAL_ECHOLNPGM_P(SP_U_STR, m.obj_center.u); + #endif + #if HAS_V_CENTER + SERIAL_ECHOLNPGM_P(SP_V_STR, m.obj_center.v); + #endif + #if HAS_W_CENTER + SERIAL_ECHOLNPGM_P(SP_W_STR, m.obj_center.w); + #endif SERIAL_EOL(); } @@ -475,6 +538,30 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM(" " STR_K_MAX ": ", m.backlash[KMAXIMUM]); #endif #endif + #if HAS_U_AXIS && AXIS_CAN_CALIBRATE(U) + #if ENABLED(CALIBRATION_MEASURE_UMIN) + SERIAL_ECHOLNPGM(" " STR_U_MIN ": ", m.backlash[UMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_UMAX) + SERIAL_ECHOLNPGM(" " STR_U_MAX ": ", m.backlash[UMAXIMUM]); + #endif + #endif + #if HAS_V_AXIS && AXIS_CAN_CALIBRATE(V) + #if ENABLED(CALIBRATION_MEASURE_VMIN) + SERIAL_ECHOLNPGM(" " STR_V_MIN ": ", m.backlash[VMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_VMAX) + SERIAL_ECHOLNPGM(" " STR_V_MAX ": ", m.backlash[VMAXIMUM]); + #endif + #endif + #if HAS_W_AXIS && AXIS_CAN_CALIBRATE(W) + #if ENABLED(CALIBRATION_MEASURE_WMIN) + SERIAL_ECHOLNPGM(" " STR_W_MIN ": ", m.backlash[WMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_WMAX) + SERIAL_ECHOLNPGM(" " STR_W_MAX ": ", m.backlash[WMAXIMUM]); + #endif + #endif SERIAL_EOL(); } @@ -498,7 +585,16 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM_P(SP_J_STR, m.pos_error.j); #endif #if HAS_K_CENTER && AXIS_CAN_CALIBRATE(K) - SERIAL_ECHOLNPGM_P(SP_Z_STR, m.pos_error.z); + SERIAL_ECHOLNPGM_P(SP_K_STR, m.pos_error.k); + #endif + #if HAS_U_CENTER && AXIS_CAN_CALIBRATE(U) + SERIAL_ECHOLNPGM_P(SP_U_STR, m.pos_error.u); + #endif + #if HAS_V_CENTER && AXIS_CAN_CALIBRATE(V) + SERIAL_ECHOLNPGM_P(SP_V_STR, m.pos_error.v); + #endif + #if HAS_W_CENTER && AXIS_CAN_CALIBRATE(W) + SERIAL_ECHOLNPGM_P(SP_W_STR, m.pos_error.w); #endif SERIAL_EOL(); } @@ -587,6 +683,30 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) { backlash.set_distance_mm(K_AXIS, m.backlash[KMAXIMUM]); #endif + #if HAS_U_CENTER + backlash.distance_mm.u = (m.backlash[UMINIMUM] + m.backlash[UMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_UMIN) + backlash.distance_mm.u = m.backlash[UMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_UMAX) + backlash.distance_mm.u = m.backlash[UMAXIMUM]; + #endif + + #if HAS_V_CENTER + backlash.distance_mm.v = (m.backlash[VMINIMUM] + m.backlash[VMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_VMIN) + backlash.distance_mm.v = m.backlash[VMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_UMAX) + backlash.distance_mm.v = m.backlash[VMAXIMUM]; + #endif + + #if HAS_W_CENTER + backlash.distance_mm.w = (m.backlash[WMINIMUM] + m.backlash[WMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_WMIN) + backlash.distance_mm.w = m.backlash[WMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_WMAX) + backlash.distance_mm.w = m.backlash[WMAXIMUM]; + #endif + #endif // BACKLASH_GCODE } @@ -597,9 +717,10 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) { // New scope for TEMPORARY_BACKLASH_CORRECTION TEMPORARY_BACKLASH_CORRECTION(backlash.all_on); TEMPORARY_BACKLASH_SMOOTHING(0.0f); - const xyz_float_t move = LINEAR_AXIS_ARRAY( + const xyz_float_t move = NUM_AXIS_ARRAY( AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3, - AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3 + AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3, + AXIS_CAN_CALIBRATE(U) * 3, AXIS_CAN_CALIBRATE(V) * 3, AXIS_CAN_CALIBRATE(W) * 3 ); current_position += move; calibration_move(); current_position -= move; calibration_move(); @@ -650,6 +771,9 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const TERN_(HAS_I_CENTER, update_measurements(m, I_AXIS)); TERN_(HAS_J_CENTER, update_measurements(m, J_AXIS)); TERN_(HAS_K_CENTER, update_measurements(m, K_AXIS)); + TERN_(HAS_U_CENTER, update_measurements(m, U_AXIS)); + TERN_(HAS_V_CENTER, update_measurements(m, V_AXIS)); + TERN_(HAS_W_CENTER, update_measurements(m, W_AXIS)); sync_plan_position(); } diff --git a/Marlin/src/gcode/calibrate/M425.cpp b/Marlin/src/gcode/calibrate/M425.cpp index 6b1f56fcf658..bfceefdbe289 100644 --- a/Marlin/src/gcode/calibrate/M425.cpp +++ b/Marlin/src/gcode/calibrate/M425.cpp @@ -49,21 +49,24 @@ void GcodeSuite::M425() { auto axis_can_calibrate = [](const uint8_t a) { switch (a) { default: return false; - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( case X_AXIS: return AXIS_CAN_CALIBRATE(X), case Y_AXIS: return AXIS_CAN_CALIBRATE(Y), case Z_AXIS: return AXIS_CAN_CALIBRATE(Z), case I_AXIS: return AXIS_CAN_CALIBRATE(I), case J_AXIS: return AXIS_CAN_CALIBRATE(J), - case K_AXIS: return AXIS_CAN_CALIBRATE(K) + case K_AXIS: return AXIS_CAN_CALIBRATE(K), + case U_AXIS: return AXIS_CAN_CALIBRATE(U), + case V_AXIS: return AXIS_CAN_CALIBRATE(V), + case W_AXIS: return AXIS_CAN_CALIBRATE(W) ); } }; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_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; } } @@ -88,7 +91,7 @@ void GcodeSuite::M425() { SERIAL_ECHOLNPGM("active:"); SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)"); SERIAL_ECHOPGM(" Backlash Distance (mm): "); - LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a)) { + LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) { SERIAL_CHAR(' ', AXIS_CHAR(a)); SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a))); SERIAL_EOL(); @@ -101,7 +104,7 @@ void GcodeSuite::M425() { #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING) SERIAL_ECHOPGM(" Average measured backlash (mm):"); if (backlash.has_any_measurement()) { - LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { + LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { SERIAL_CHAR(' ', AXIS_CHAR(a)); SERIAL_ECHO(backlash.get_measurement(AxisEnum(a))); } @@ -120,13 +123,16 @@ void GcodeSuite::M425_report(const bool forReplay/*=true*/) { #ifdef BACKLASH_SMOOTHING_MM , PSTR(" S"), LINEAR_UNIT(backlash.get_smoothing_mm()) #endif - , LIST_N(DOUBLE(LINEAR_AXES), + , LIST_N(DOUBLE(NUM_AXES), SP_X_STR, LINEAR_UNIT(backlash.get_distance_mm(X_AXIS)), SP_Y_STR, LINEAR_UNIT(backlash.get_distance_mm(Y_AXIS)), SP_Z_STR, LINEAR_UNIT(backlash.get_distance_mm(Z_AXIS)), - SP_I_STR, LINEAR_UNIT(backlash.get_distance_mm(I_AXIS)), - SP_J_STR, LINEAR_UNIT(backlash.get_distance_mm(J_AXIS)), - SP_K_STR, LINEAR_UNIT(backlash.get_distance_mm(K_AXIS)) + SP_I_STR, I_AXIS_UNIT(backlash.get_distance_mm(I_AXIS)), + SP_J_STR, J_AXIS_UNIT(backlash.get_distance_mm(J_AXIS)), + SP_K_STR, K_AXIS_UNIT(backlash.get_distance_mm(K_AXIS)), + SP_U_STR, U_AXIS_UNIT(backlash.get_distance_mm(U_AXIS)), + SP_V_STR, V_AXIS_UNIT(backlash.get_distance_mm(V_AXIS)), + SP_W_STR, W_AXIS_UNIT(backlash.get_distance_mm(W_AXIS)) ) ); } diff --git a/Marlin/src/gcode/calibrate/M666.cpp b/Marlin/src/gcode/calibrate/M666.cpp index 15f8baf109eb..fe244b21f7b8 100644 --- a/Marlin/src/gcode/calibrate/M666.cpp +++ b/Marlin/src/gcode/calibrate/M666.cpp @@ -44,7 +44,7 @@ void GcodeSuite::M666() { DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING)); bool is_err = false, is_set = false; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (parser.seen(AXIS_CHAR(i))) { is_set = true; const float v = parser.value_linear_units(); diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp index fb4c9b8af347..5e15ff65e8fb 100644 --- a/Marlin/src/gcode/config/M200-M205.cpp +++ b/Marlin/src/gcode/config/M200-M205.cpp @@ -135,13 +135,16 @@ void GcodeSuite::M201() { void GcodeSuite::M201_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_MAX_ACCELERATION)); SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]), - SP_I_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]), - SP_J_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]) + SP_I_STR, I_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]), + SP_J_STR, J_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]), + SP_K_STR, K_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]), + SP_U_STR, U_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[U_AXIS]), + SP_V_STR, V_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[V_AXIS]), + SP_W_STR, W_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[W_AXIS]), ) #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS]) @@ -180,13 +183,16 @@ void GcodeSuite::M203() { void GcodeSuite::M203_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_MAX_FEEDRATES)); SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]), SP_I_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[I_AXIS]), SP_J_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS]) + SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS]), + SP_U_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[U_AXIS]), + SP_V_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[V_AXIS]), + SP_W_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[W_AXIS]) ) #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS]) @@ -273,9 +279,12 @@ void GcodeSuite::M205() { if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()), if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()), if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.value_linear_units()) + if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS7_NAME)) planner.set_max_jerk(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS8_NAME)) planner.set_max_jerk(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS9_NAME)) planner.set_max_jerk(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)()) ); #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING) if (seenZ && planner.max_jerk.z <= 0.1f) @@ -289,9 +298,10 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) { "Advanced (B S T" TERN_(HAS_JUNCTION_DEVIATION, " J") #if HAS_CLASSIC_JERK - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( " X", " Y", " Z", - " " STR_I "", " " STR_J "", " " STR_K "" + " " STR_I "", " " STR_J "", " " STR_K "", + " " STR_U "", " " STR_V "", " " STR_W "" ) #endif TERN_(HAS_CLASSIC_E_JERK, " E") @@ -305,13 +315,16 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) { , PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm) #endif #if HAS_CLASSIC_JERK - , LIST_N(DOUBLE(LINEAR_AXES), + , LIST_N(DOUBLE(NUM_AXES), SP_X_STR, LINEAR_UNIT(planner.max_jerk.x), SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y), SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z), - SP_I_STR, LINEAR_UNIT(planner.max_jerk.i), - SP_J_STR, LINEAR_UNIT(planner.max_jerk.j), - SP_K_STR, LINEAR_UNIT(planner.max_jerk.k) + SP_I_STR, I_AXIS_UNIT(planner.max_jerk.i), + SP_J_STR, J_AXIS_UNIT(planner.max_jerk.j), + SP_K_STR, K_AXIS_UNIT(planner.max_jerk.k), + SP_U_STR, U_AXIS_UNIT(planner.max_jerk.u), + SP_V_STR, V_AXIS_UNIT(planner.max_jerk.v), + SP_W_STR, W_AXIS_UNIT(planner.max_jerk.w) ) #if HAS_CLASSIC_E_JERK , SP_E_STR, LINEAR_UNIT(planner.max_jerk.e) diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index 344adc34e320..ad96b2b659ce 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -50,9 +50,12 @@ * W[linear] 0/1 Enable park & Z Raise * X[linear] Park X (Requires TOOLCHANGE_PARK) * Y[linear] Park Y (Requires TOOLCHANGE_PARK) - * I[linear] Park I (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 4) - * J[linear] Park J (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 5) - * K[linear] Park K (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 6) + * I[linear] Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4) + * J[linear] Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5) + * K[linear] Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6) + * C[linear] Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7) + * H[linear] Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8) + * O[linear] Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9) * Z[linear] Z Raise * F[linear] Fan Speed 0-255 * G[linear/s] Fan time @@ -95,13 +98,22 @@ void GcodeSuite::M217() { if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); } #endif #if HAS_I_AXIS - if (parser.seenval('I')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); } + if (parser.seenval('I')) { const int16_t v = parser.TERN(AXIS4_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); } #endif #if HAS_J_AXIS - if (parser.seenval('J')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); } + if (parser.seenval('J')) { const int16_t v = parser.TERN(AXIS5_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); } #endif #if HAS_K_AXIS - if (parser.seenval('K')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); } + if (parser.seenval('K')) { const int16_t v = parser.TERN(AXIS6_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); } + #endif + #if HAS_U_AXIS + if (parser.seenval('C')) { const int16_t v = parser.TERN(AXIS7_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.u = constrain(v, U_MIN_POS, U_MAX_POS); } + #endif + #if HAS_V_AXIS + if (parser.seenval('H')) { const int16_t v = parser.TERN(AXIS8_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.v = constrain(v, V_MIN_POS, V_MAX_POS); } + #endif + #if HAS_W_AXIS + if (parser.seenval('O')) { const int16_t v = parser.TERN(AXIS9_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.w = constrain(v, W_MIN_POS, W_MAX_POS); } #endif #endif @@ -167,24 +179,23 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) { #endif #if ENABLED(TOOLCHANGE_PARK) - { SERIAL_ECHOPGM(" W", LINEAR_UNIT(toolchange_settings.enable_park)); SERIAL_ECHOPGM_P( SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x) #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), + PSTR(" I"), I_AXIS_UNIT(toolchange_settings.change_point.i), + PSTR(" J"), J_AXIS_UNIT(toolchange_settings.change_point.j), + PSTR(" K"), K_AXIS_UNIT(toolchange_settings.change_point.k), + SP_C_STR, U_AXIS_UNIT(toolchange_settings.change_point.u), + PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v), + PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w), + ) #endif ); - } #endif #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED) diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp index 8f527919fd83..cca4f7f12aa1 100644 --- a/Marlin/src/gcode/config/M92.cpp +++ b/Marlin/src/gcode/config/M92.cpp @@ -24,7 +24,7 @@ #include "../../module/planner.h" /** - * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, [I, [J, [K]]] and E. + * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, [I, [J, [K, [U, [V, [W,]]]]]] and E. * (Follows the same syntax as G92) * * With multiple extruders use T to specify which one. @@ -92,14 +92,17 @@ void GcodeSuite::M92() { void GcodeSuite::M92_report(const bool forReplay/*=true*/, const int8_t e/*=-1*/) { report_heading_etc(forReplay, F(STR_STEPS_PER_UNIT)); - SERIAL_ECHOPGM_P(LIST_N(DOUBLE(LINEAR_AXES), + SERIAL_ECHOPGM_P(LIST_N(DOUBLE(NUM_AXES), PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]), - SP_I_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[I_AXIS]), - SP_J_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[K_AXIS])) - ); + SP_I_STR, I_AXIS_UNIT(planner.settings.axis_steps_per_mm[I_AXIS]), + SP_J_STR, J_AXIS_UNIT(planner.settings.axis_steps_per_mm[J_AXIS]), + SP_K_STR, K_AXIS_UNIT(planner.settings.axis_steps_per_mm[K_AXIS]), + SP_U_STR, U_AXIS_UNIT(planner.settings.axis_steps_per_mm[U_AXIS]), + SP_V_STR, V_AXIS_UNIT(planner.settings.axis_steps_per_mm[V_AXIS]), + SP_W_STR, W_AXIS_UNIT(planner.settings.axis_steps_per_mm[W_AXIS]) + )); #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) SERIAL_ECHOPGM_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS])); #endif diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index 3bc5582ce700..c6473af48fd4 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -46,13 +46,16 @@ inline axis_flags_t selected_axis_bits() { selected.bits = selected.e_bits(); } #endif - selected.bits |= LINEAR_AXIS_GANG( + selected.bits |= NUM_AXIS_GANG( (parser.seen_test('X') << X_AXIS), | (parser.seen_test('Y') << Y_AXIS), | (parser.seen_test('Z') << Z_AXIS), | (parser.seen_test(AXIS4_NAME) << I_AXIS), | (parser.seen_test(AXIS5_NAME) << J_AXIS), - | (parser.seen_test(AXIS6_NAME) << K_AXIS) + | (parser.seen_test(AXIS6_NAME) << K_AXIS), + | (parser.seen_test(AXIS7_NAME) << U_AXIS), + | (parser.seen_test(AXIS8_NAME) << V_AXIS), + | (parser.seen_test(AXIS9_NAME) << W_AXIS) ); return selected; } @@ -69,7 +72,7 @@ void do_enable(const axis_flags_t to_enable) { ena_mask_t also_enabled = 0; // Track steppers enabled due to overlap // Enable all flagged axes - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { if (TEST(shall_enable, a)) { stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits)); @@ -89,7 +92,7 @@ void do_enable(const axis_flags_t to_enable) { if ((also_enabled &= ~(shall_enable | was_enabled))) { SERIAL_CHAR('('); - LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' '); + LOOP_NUM_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' '); #if HAS_EXTRUDERS #define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' '); REPEAT(EXTRUDERS, _EN_ALSO) @@ -125,13 +128,16 @@ void GcodeSuite::M17() { stepper.enable_e_steppers(); } #endif - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seen_test('X')) stepper.enable_axis(X_AXIS), if (parser.seen_test('Y')) stepper.enable_axis(Y_AXIS), if (parser.seen_test('Z')) stepper.enable_axis(Z_AXIS), if (parser.seen_test(AXIS4_NAME)) stepper.enable_axis(I_AXIS), if (parser.seen_test(AXIS5_NAME)) stepper.enable_axis(J_AXIS), - if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS) + if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS), + if (parser.seen_test(AXIS7_NAME)) stepper.enable_axis(U_AXIS), + if (parser.seen_test(AXIS8_NAME)) stepper.enable_axis(V_AXIS), + if (parser.seen_test(AXIS9_NAME)) stepper.enable_axis(W_AXIS) ); } } @@ -149,7 +155,7 @@ void try_to_disable(const axis_flags_t to_disable) { if (!still_enabled) return; // Attempt to disable all flagged axes - LOOP_LINEAR_AXES(a) + LOOP_NUM_AXES(a) if (TEST(to_disable.bits, a)) { DEBUG_ECHOPGM("Try to disable ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... "); if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable @@ -178,7 +184,7 @@ void try_to_disable(const axis_flags_t to_disable) { auto overlap_warning = [](const ena_mask_t axis_bits) { SERIAL_ECHOPGM(" not disabled. Shared with"); - LOOP_LINEAR_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]); + LOOP_NUM_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]); #if HAS_EXTRUDERS #define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N); REPEAT(EXTRUDERS, _EN_STILLON) @@ -187,7 +193,7 @@ void try_to_disable(const axis_flags_t to_disable) { }; // If any of the requested axes are still enabled, give a warning - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { if (TEST(still_enabled, a)) { SERIAL_CHAR(axis_codes[a]); overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]); @@ -229,13 +235,16 @@ void GcodeSuite::M18_M84() { stepper.disable_e_steppers(); } #endif - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seen_test('X')) stepper.disable_axis(X_AXIS), if (parser.seen_test('Y')) stepper.disable_axis(Y_AXIS), if (parser.seen_test('Z')) stepper.disable_axis(Z_AXIS), if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS), if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS), - if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS) + if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS), + if (parser.seen_test(AXIS7_NAME)) stepper.disable_axis(U_AXIS), + if (parser.seen_test(AXIS8_NAME)) stepper.disable_axis(V_AXIS), + if (parser.seen_test(AXIS9_NAME)) stepper.disable_axis(W_AXIS) ); } } diff --git a/Marlin/src/gcode/control/M605.cpp b/Marlin/src/gcode/control/M605.cpp index 788659e7e27a..a0296bba5700 100644 --- a/Marlin/src/gcode/control/M605.cpp +++ b/Marlin/src/gcode/control/M605.cpp @@ -146,7 +146,7 @@ HOTEND_LOOP() { DEBUG_ECHOPGM_P(SP_T_STR, e); - LOOP_LINEAR_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]); + LOOP_NUM_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]); DEBUG_EOL(); } DEBUG_EOL(); diff --git a/Marlin/src/gcode/feature/digipot/M907-M910.cpp b/Marlin/src/gcode/feature/digipot/M907-M910.cpp index 95adde3ea532..3b66f78593d7 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] [U] [V] [W] [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, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) + "XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W") #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) "Z" @@ -67,8 +67,12 @@ 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, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) + if (NUM_AXIS_GANG( + parser.seenval('X'), || parser.seenval('Y'), || false, + || parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K'), + || parser.seenval('U'), || parser.seenval('V'), || parser.seenval('W') + )) 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 +85,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 +99,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 +108,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, U, V, W) , 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]); + LOOP_LOGICAL_AXES(q) { // X Y Z (I J K U V W) E (map to X Y Z (I J K U V W) E0 by default) + 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 d4770577a65f..9e0962fd34f6 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -48,10 +48,14 @@ void GcodeSuite::G60() { #if ENABLED(SAVED_POSITIONS_DEBUG) { - DEBUG_ECHOPGM(STR_SAVED_POS " S", slot); const xyze_pos_t &pos = stored_position[slot]; + DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :"); DEBUG_ECHOLNPAIR_F_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(NUM_AXES), + SP_Y_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, + SP_U_STR, pos.u, SP_V_STR, pos.v, SP_W_STR, pos.w + ) #if HAS_EXTRUDERS , SP_E_STR, pos.e #endif diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index e0e1983a2574..baf96f0d0af0 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -68,9 +68,9 @@ void GcodeSuite::G61() { SYNC_E(stored_position[slot].e); } else { - if (parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K))) { + if (parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W))) { DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { destination[i] = parser.seen(AXIS_CHAR(i)) ? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i) : current_position[i]; diff --git a/Marlin/src/gcode/feature/pause/M125.cpp b/Marlin/src/gcode/feature/pause/M125.cpp index 940e1b369bc6..ae450cc5e945 100644 --- a/Marlin/src/gcode/feature/pause/M125.cpp +++ b/Marlin/src/gcode/feature/pause/M125.cpp @@ -52,6 +52,9 @@ * A = Override park position A (requires AXIS*_NAME 'A') * B = Override park position B (requires AXIS*_NAME 'B') * C = Override park position C (requires AXIS*_NAME 'C') + * U = Override park position U (requires AXIS*_NAME 'U') + * V = Override park position V (requires AXIS*_NAME 'V') + * W = Override park position W (requires AXIS*_NAME 'W') * Z = Override Z raise * * With an LCD menu: @@ -64,17 +67,22 @@ void GcodeSuite::M125() { xyz_pos_t park_point = NOZZLE_PARK_POINT; // Move to filament change position or given position - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seenval('X')) park_point.x = RAW_X_POSITION(parser.linearval('X')), if (parser.seenval('Y')) park_point.y = RAW_Y_POSITION(parser.linearval('Y')), NOOP, - if (parser.seenval(AXIS4_NAME)) park_point.i = RAW_I_POSITION(parser.linearval(AXIS4_NAME)), - if (parser.seenval(AXIS5_NAME)) park_point.j = RAW_J_POSITION(parser.linearval(AXIS5_NAME)), - if (parser.seenval(AXIS6_NAME)) park_point.k = RAW_K_POSITION(parser.linearval(AXIS6_NAME)) + if (parser.seenval(AXIS4_NAME)) park_point.i = RAW_X_POSITION(parser.linearval(AXIS4_NAME)), + if (parser.seenval(AXIS5_NAME)) park_point.j = RAW_X_POSITION(parser.linearval(AXIS5_NAME)), + if (parser.seenval(AXIS6_NAME)) park_point.k = RAW_X_POSITION(parser.linearval(AXIS6_NAME)), + if (parser.seenval(AXIS7_NAME)) park_point.u = RAW_X_POSITION(parser.linearval(AXIS7_NAME)), + if (parser.seenval(AXIS8_NAME)) park_point.v = RAW_X_POSITION(parser.linearval(AXIS8_NAME)), + if (parser.seenval(AXIS9_NAME)) park_point.w = RAW_X_POSITION(parser.linearval(AXIS9_NAME)) ); // 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 1679c90687bd..4fd08489d39a 100644 --- a/Marlin/src/gcode/feature/pause/M600.cpp +++ b/Marlin/src/gcode/feature/pause/M600.cpp @@ -54,8 +54,14 @@ * * 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) + * C[position] - Move to this U position (instead of NOZZLE_PARK_POINT.u) + * H[position] - Move to this V position (instead of NOZZLE_PARK_POINT.v) + * O[position] - Move to this W position (instead of NOZZLE_PARK_POINT.w) * 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) @@ -117,26 +123,25 @@ void GcodeSuite::M600() { xyz_pos_t park_point NOZZLE_PARK_POINT; // Move XY axes to filament change position or given position - LINEAR_AXIS_CODE( + NUM_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('I')) park_point.i = parser.linearval('I'), + if (parser.seenval('J')) park_point.j = parser.linearval('J'), + if (parser.seenval('K')) park_point.k = parser.linearval('K'), + if (parser.seenval('C')) park_point.u = parser.linearval('C'), // U axis + if (parser.seenval('H')) park_point.v = parser.linearval('H'), // V axis + if (parser.seenval('O')) park_point.w = parser.linearval('O') // W axis ); #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/M569.cpp b/Marlin/src/gcode/feature/trinamic/M569.cpp index 7bfedf8c7210..3a325ad26496 100644 --- a/Marlin/src/gcode/feature/trinamic/M569.cpp +++ b/Marlin/src/gcode/feature/trinamic/M569.cpp @@ -85,6 +85,15 @@ static void set_stealth_status(const bool enable, const int8_t eindex) { #if K_HAS_STEALTHCHOP case K_AXIS: TMC_SET_STEALTH(K); break; #endif + #if U_HAS_STEALTHCHOP + case U_AXIS: TMC_SET_STEALTH(U); break; + #endif + #if V_HAS_STEALTHCHOP + case V_AXIS: TMC_SET_STEALTH(V); break; + #endif + #if W_HAS_STEALTHCHOP + case W_AXIS: TMC_SET_STEALTH(W); break; + #endif #if E_STEPPERS case E_AXIS: { @@ -115,6 +124,9 @@ static void say_stealth_status() { OPTCODE( I_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(I)) OPTCODE( J_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(J)) OPTCODE( K_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(K)) + OPTCODE( U_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(U)) + OPTCODE( V_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(V)) + OPTCODE( W_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(W)) OPTCODE(E0_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E0)) OPTCODE(E1_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E1)) OPTCODE(E2_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E2)) @@ -157,17 +169,23 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) { chop_z = TERN0(Z_HAS_STEALTHCHOP, stepperZ.get_stored_stealthChop()), chop_i = TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop()), chop_j = TERN0(J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop()), - chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop()); + chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop()), + chop_u = TERN0(U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop()), + chop_v = TERN0(V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop()), + chop_w = TERN0(W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop()); - if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k) { + if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k || chop_u || chop_v || chop_w) { say_M569(forReplay); - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (chop_x) SERIAL_ECHOPGM_P(SP_X_STR), if (chop_y) SERIAL_ECHOPGM_P(SP_Y_STR), if (chop_z) SERIAL_ECHOPGM_P(SP_Z_STR), if (chop_i) SERIAL_ECHOPGM_P(SP_I_STR), if (chop_j) SERIAL_ECHOPGM_P(SP_J_STR), - if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR) + if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR), + if (chop_u) SERIAL_ECHOPGM_P(SP_U_STR), + if (chop_v) SERIAL_ECHOPGM_P(SP_V_STR), + if (chop_w) SERIAL_ECHOPGM_P(SP_W_STR) ); SERIAL_EOL(); } @@ -190,6 +208,9 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) { if (TERN0( I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_I_STR), true); } if (TERN0( J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_J_STR), true); } if (TERN0( K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_K_STR), true); } + if (TERN0( U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_U_STR), true); } + if (TERN0( V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_V_STR), true); } + if (TERN0( W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_W_STR), true); } if (TERN0(E0_HAS_STEALTHCHOP, stepperE0.get_stored_stealthChop())) { say_M569(forReplay, F("T0 E"), true); } if (TERN0(E1_HAS_STEALTHCHOP, stepperE1.get_stored_stealthChop())) { say_M569(forReplay, F("T1 E"), true); } diff --git a/Marlin/src/gcode/feature/trinamic/M906.cpp b/Marlin/src/gcode/feature/trinamic/M906.cpp index c85d0be8a19a..4822b8e268ad 100644 --- a/Marlin/src/gcode/feature/trinamic/M906.cpp +++ b/Marlin/src/gcode/feature/trinamic/M906.cpp @@ -44,6 +44,9 @@ static void tmc_print_current(TMC &st) { * A[current] - Set mA current for A driver(s) (Requires AXIS*_NAME 'A') * B[current] - Set mA current for B driver(s) (Requires AXIS*_NAME 'B') * C[current] - Set mA current for C driver(s) (Requires AXIS*_NAME 'C') + * U[current] - Set mA current for U driver(s) (Requires AXIS*_NAME 'U') + * V[current] - Set mA current for V driver(s) (Requires AXIS*_NAME 'V') + * W[current] - Set mA current for W driver(s) (Requires AXIS*_NAME 'W') * E[current] - Set mA current for E driver(s) * * I[index] - Axis sub-index (Omit or 0 for X, Y, Z; 1 for X2, Y2, Z2; 2 for Z3; 3 for Z4.) @@ -114,6 +117,15 @@ void GcodeSuite::M906() { #if AXIS_IS_TMC(K) case K_AXIS: TMC_SET_CURRENT(K); break; #endif + #if AXIS_IS_TMC(U) + case U_AXIS: TMC_SET_CURRENT(U); break; + #endif + #if AXIS_IS_TMC(V) + case V_AXIS: TMC_SET_CURRENT(V); break; + #endif + #if AXIS_IS_TMC(W) + case W_AXIS: TMC_SET_CURRENT(W); break; + #endif #if AXIS_IS_TMC(E0) || AXIS_IS_TMC(E1) || AXIS_IS_TMC(E2) || AXIS_IS_TMC(E3) || AXIS_IS_TMC(E4) || AXIS_IS_TMC(E5) || AXIS_IS_TMC(E6) || AXIS_IS_TMC(E7) case E_AXIS: { @@ -181,6 +193,16 @@ void GcodeSuite::M906() { #if AXIS_IS_TMC(K) TMC_SAY_CURRENT(K); #endif + #if AXIS_IS_TMC(U) + TMC_SAY_CURRENT(U); + #endif + #if AXIS_IS_TMC(V) + TMC_SAY_CURRENT(V); + #endif + #if AXIS_IS_TMC(W) + TMC_SAY_CURRENT(W); + #endif + #if AXIS_IS_TMC(E0) TMC_SAY_CURRENT(E0); #endif @@ -217,7 +239,8 @@ void GcodeSuite::M906_report(const bool forReplay/*=true*/) { }; #if AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z) \ - || AXIS_IS_TMC(I) || AXIS_IS_TMC(J) || AXIS_IS_TMC(K) + || AXIS_IS_TMC(I) || AXIS_IS_TMC(J) || AXIS_IS_TMC(K) \ + || AXIS_IS_TMC(U) || AXIS_IS_TMC(V) || AXIS_IS_TMC(W) say_M906(forReplay); #if AXIS_IS_TMC(X) SERIAL_ECHOPGM_P(SP_X_STR, stepperX.getMilliamps()); @@ -237,6 +260,15 @@ void GcodeSuite::M906_report(const bool forReplay/*=true*/) { #if AXIS_IS_TMC(K) SERIAL_ECHOPGM_P(SP_K_STR, stepperK.getMilliamps()); #endif + #if AXIS_IS_TMC(U) + SERIAL_ECHOPGM_P(SP_U_STR, stepperU.getMilliamps()); + #endif + #if AXIS_IS_TMC(V) + SERIAL_ECHOPGM_P(SP_V_STR, stepperV.getMilliamps()); + #endif + #if AXIS_IS_TMC(W) + SERIAL_ECHOPGM_P(SP_W_STR, stepperW.getMilliamps()); + #endif SERIAL_EOL(); #endif diff --git a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp index 57a77c0e5d4e..206e2e456ce7 100644 --- a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp +++ b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp @@ -53,12 +53,21 @@ #if HAS_K_AXIS && M91x_USE(K) #define M91x_USE_K 1 #endif + #if HAS_U_AXIS && M91x_USE(U) + #define M91x_USE_U 1 + #endif + #if HAS_V_AXIS && M91x_USE(V) + #define M91x_USE_V 1 + #endif + #if HAS_W_AXIS && M91x_USE(W) + #define M91x_USE_W 1 + #endif #if M91x_USE_E(0) || M91x_USE_E(1) || M91x_USE_E(2) || M91x_USE_E(3) || M91x_USE_E(4) || M91x_USE_E(5) || M91x_USE_E(6) || M91x_USE_E(7) #define M91x_SOME_E 1 #endif - #if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_SOME_E + #if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_USE_U && !M91x_USE_V && !M91x_USE_W && !M91x_SOME_E #error "MONITOR_DRIVER_STATUS requires at least one TMC2130, 2160, 2208, 2209, 2660, 5130, or 5160." #endif @@ -109,6 +118,9 @@ TERN_(M91x_USE_I, tmc_report_otpw(stepperI)); TERN_(M91x_USE_J, tmc_report_otpw(stepperJ)); TERN_(M91x_USE_K, tmc_report_otpw(stepperK)); + TERN_(M91x_USE_U, tmc_report_otpw(stepperU)); + TERN_(M91x_USE_V, tmc_report_otpw(stepperV)); + TERN_(M91x_USE_W, tmc_report_otpw(stepperW)); #if M91x_USE_E(0) tmc_report_otpw(stepperE0); #endif @@ -137,7 +149,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, U, V, W, and E[index]. * If no axes are given, clear all. * * Examples: @@ -154,9 +166,12 @@ hasI = TERN0(M91x_USE_I, parser.seen(axis_codes.i)), hasJ = TERN0(M91x_USE_J, parser.seen(axis_codes.j)), hasK = TERN0(M91x_USE_K, parser.seen(axis_codes.k)), + hasU = TERN0(M91x_USE_U, parser.seen(axis_codes.u)), + hasV = TERN0(M91x_USE_V, parser.seen(axis_codes.v)), + hasW = TERN0(M91x_USE_W, parser.seen(axis_codes.w)), hasE = TERN0(M91x_SOME_E, parser.seen(axis_codes.e)); - const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK; + const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK && !hasU && !hasV && !hasW; #if M91x_SOME_X const int8_t xval = int8_t(parser.byteval(axis_codes.x, 0xFF)); @@ -206,6 +221,18 @@ const int8_t kval = int8_t(parser.byteval(axis_codes.k, 0xFF)); if (hasNone || kval == 1 || (hasK && kval < 0)) tmc_clear_otpw(stepperK); #endif + #if M91x_USE_U + const int8_t uval = int8_t(parser.byteval(axis_codes.u, 0xFF)); + if (hasNone || uval == 1 || (hasU && uval < 0)) tmc_clear_otpw(stepperU); + #endif + #if M91x_USE_V + const int8_t vval = int8_t(parser.byteval(axis_codes.v, 0xFF)); + if (hasNone || vval == 1 || (hasV && vval < 0)) tmc_clear_otpw(stepperV); + #endif + #if M91x_USE_W + const int8_t wval = int8_t(parser.byteval(axis_codes.w, 0xFF)); + if (hasNone || wval == 1 || (hasW && wval < 0)) tmc_clear_otpw(stepperW); + #endif #if M91x_SOME_E const int8_t eval = int8_t(parser.byteval(axis_codes.e, 0xFF)); @@ -296,6 +323,15 @@ #if K_HAS_STEALTHCHOP case K_AXIS: TMC_SET_PWMTHRS(K,K); break; #endif + #if U_HAS_STEALTHCHOP + case U_AXIS: TMC_SET_PWMTHRS(U,U); break; + #endif + #if V_HAS_STEALTHCHOP + case V_AXIS: TMC_SET_PWMTHRS(V,V); break; + #endif + #if W_HAS_STEALTHCHOP + case W_AXIS: TMC_SET_PWMTHRS(W,W); break; + #endif #if E0_HAS_STEALTHCHOP || E1_HAS_STEALTHCHOP || E2_HAS_STEALTHCHOP || E3_HAS_STEALTHCHOP || E4_HAS_STEALTHCHOP || E5_HAS_STEALTHCHOP || E6_HAS_STEALTHCHOP || E7_HAS_STEALTHCHOP case E_AXIS: { @@ -326,6 +362,9 @@ TERN_( I_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(I,I)); TERN_( J_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(J,J)); TERN_( K_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(K,K)); + TERN_( U_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(U,U)); + TERN_( V_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(V,V)); + TERN_( W_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(W,W)); TERN_(E0_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(0)); TERN_(E1_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(1)); @@ -397,6 +436,18 @@ say_M913(forReplay); SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.get_pwm_thrs()); #endif + #if U_HAS_STEALTHCHOP + say_M913(forReplay); + SERIAL_ECHOLNPGM_P(SP_U_STR, stepperU.get_pwm_thrs()); + #endif + #if V_HAS_STEALTHCHOP + say_M913(forReplay); + SERIAL_ECHOLNPGM_P(SP_V_STR, stepperV.get_pwm_thrs()); + #endif + #if W_HAS_STEALTHCHOP + say_M913(forReplay); + SERIAL_ECHOLNPGM_P(SP_W_STR, stepperW.get_pwm_thrs()); + #endif #if E0_HAS_STEALTHCHOP say_M913(forReplay); @@ -451,7 +502,7 @@ bool report = true; const uint8_t index = parser.byteval('I'); - LOOP_LINEAR_AXES(i) if (parser.seen(AXIS_CHAR(i))) { + LOOP_NUM_AXES(i) if (parser.seen(AXIS_CHAR(i))) { const int16_t value = parser.value_int(); report = false; switch (i) { @@ -484,6 +535,15 @@ #if K_SENSORLESS case K_AXIS: stepperK.homing_threshold(value); break; #endif + #if U_SENSORLESS && AXIS_HAS_STALLGUARD(U) + case U_AXIS: stepperU.homing_threshold(value); break; + #endif + #if V_SENSORLESS && AXIS_HAS_STALLGUARD(V) + case V_AXIS: stepperV.homing_threshold(value); break; + #endif + #if W_SENSORLESS && AXIS_HAS_STALLGUARD(W) + case W_AXIS: stepperW.homing_threshold(value); break; + #endif } } @@ -499,6 +559,9 @@ TERN_(I_SENSORLESS, tmc_print_sgt(stepperI)); TERN_(J_SENSORLESS, tmc_print_sgt(stepperJ)); TERN_(K_SENSORLESS, tmc_print_sgt(stepperK)); + TERN_(U_SENSORLESS, tmc_print_sgt(stepperU)); + TERN_(V_SENSORLESS, tmc_print_sgt(stepperV)); + TERN_(W_SENSORLESS, tmc_print_sgt(stepperW)); } } @@ -561,6 +624,18 @@ say_M914(forReplay); SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.homing_threshold()); #endif + #if U_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_U_STR, stepperU.homing_threshold()); + #endif + #if V_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_V_STR, stepperV.homing_threshold()); + #endif + #if W_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_W_STR, stepperW.homing_threshold()); + #endif } #endif // USE_SENSORLESS diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index c365f8a67b42..9d225cef5194 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -85,7 +85,10 @@ axis_bits_t GcodeSuite::axis_relative = 0 LOGICAL_AXIS_GANG( | (ar_init.z << REL_Z), | (ar_init.i << REL_I), | (ar_init.j << REL_J), - | (ar_init.k << REL_K) + | (ar_init.k << REL_K), + | (ar_init.u << REL_U), + | (ar_init.v << REL_V), + | (ar_init.w << REL_W) ); #if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE) @@ -176,7 +179,7 @@ void GcodeSuite::get_destination_from_command() { #endif // Get new XYZ position, whether absolute or relative - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if ( (seen[i] = parser.seenval(AXIS_CHAR(i))) ) { const float v = parser.value_axis_units((AxisEnum)i); if (skip_move) diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 61fe6cb9d96f..3ec27710b402 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -337,7 +337,7 @@ #endif enum AxisRelative : uint8_t { - LOGICAL_AXIS_LIST(REL_E, REL_X, REL_Y, REL_Z, REL_I, REL_J, REL_K) + LOGICAL_AXIS_LIST(REL_E, REL_X, REL_Y, REL_Z, REL_I, REL_J, REL_K, REL_U, REL_V, REL_W) #if HAS_EXTRUDERS , E_MODE_ABS, E_MODE_REL #endif @@ -363,7 +363,8 @@ class GcodeSuite { axis_relative = rel ? (0 LOGICAL_AXIS_GANG( | _BV(REL_E), | _BV(REL_X), | _BV(REL_Y), | _BV(REL_Z), - | _BV(REL_I), | _BV(REL_J), | _BV(REL_K) + | _BV(REL_I), | _BV(REL_J), | _BV(REL_K), + | _BV(REL_U), | _BV(REL_V), | _BV(REL_W) )) : 0; } #if HAS_EXTRUDERS diff --git a/Marlin/src/gcode/geometry/G53-G59.cpp b/Marlin/src/gcode/geometry/G53-G59.cpp index db2404a28dc2..092c141228fb 100644 --- a/Marlin/src/gcode/geometry/G53-G59.cpp +++ b/Marlin/src/gcode/geometry/G53-G59.cpp @@ -39,7 +39,7 @@ bool GcodeSuite::select_coordinate_system(const int8_t _new) { xyz_float_t new_offset{0}; if (WITHIN(_new, 0, MAX_COORDINATE_SYSTEMS - 1)) new_offset = coordinate_system[_new]; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (position_shift[i] != new_offset[i]) { position_shift[i] = new_offset[i]; update_workspace_offset((AxisEnum)i); diff --git a/Marlin/src/gcode/geometry/G92.cpp b/Marlin/src/gcode/geometry/G92.cpp index 3c49fe2a2640..240759923983 100644 --- a/Marlin/src/gcode/geometry/G92.cpp +++ b/Marlin/src/gcode/geometry/G92.cpp @@ -29,7 +29,7 @@ #endif /** - * G92: Set the Current Position to the given X [Y [Z [A [B [C [E]]]]]] values. + * G92: Set the Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E] values. * * Behind the scenes the G92 command may modify the Current Position * or the Position Shift depending on settings and sub-commands. @@ -37,14 +37,14 @@ * Since E has no Workspace Offset, it is always set directly. * * Without Workspace Offsets (e.g., with NO_WORKSPACE_OFFSETS): - * G92 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]]. + * G92 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * * Using Workspace Offsets (default Marlin behavior): - * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [E]]]]]]. + * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position). * * With POWER_LOSS_RECOVERY: - * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]]. + * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. */ void GcodeSuite::G92() { @@ -64,7 +64,7 @@ void GcodeSuite::G92() { #if ENABLED(CNC_COORDINATE_SYSTEMS) && !IS_SCARA case 1: // G92.1 - Zero the Workspace Offset - LOOP_LINEAR_AXES(i) if (position_shift[i]) { + LOOP_NUM_AXES(i) if (position_shift[i]) { position_shift[i] = 0; update_workspace_offset((AxisEnum)i); } diff --git a/Marlin/src/gcode/geometry/M206_M428.cpp b/Marlin/src/gcode/geometry/M206_M428.cpp index b32d72996940..f23c83140e4c 100644 --- a/Marlin/src/gcode/geometry/M206_M428.cpp +++ b/Marlin/src/gcode/geometry/M206_M428.cpp @@ -39,11 +39,17 @@ */ void GcodeSuite::M206() { if (!parser.seen_any()) return M206_report(); - - LOOP_LINEAR_AXES(i) - if (parser.seen(AXIS_CHAR(i))) - set_home_offset((AxisEnum)i, parser.value_linear_units()); - + NUM_AXIS_CODE( + if (parser.seen('X')) set_home_offset(X_AXIS, parser.value_linear_units()), + if (parser.seen('Y')) set_home_offset(Y_AXIS, parser.value_linear_units()), + if (parser.seen('Z')) set_home_offset(Y_AXIS, parser.value_linear_units()), + if (parser.seen(AXIS4_NAME)) set_home_offset(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS5_NAME)) set_home_offset(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS6_NAME)) set_home_offset(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS7_NAME)) set_home_offset(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS8_NAME)) set_home_offset(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS9_NAME)) set_home_offset(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)()) + ); #if ENABLED(MORGAN_SCARA) if (parser.seen('T')) set_home_offset(A_AXIS, parser.value_float()); // Theta if (parser.seen('P')) set_home_offset(B_AXIS, parser.value_float()); // Psi @@ -56,13 +62,16 @@ void GcodeSuite::M206_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_HOME_OFFSET)); SERIAL_ECHOLNPGM_P( #if IS_CARTESIAN - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M206 X"), LINEAR_UNIT(home_offset.x), SP_Y_STR, LINEAR_UNIT(home_offset.y), SP_Z_STR, LINEAR_UNIT(home_offset.z), - SP_I_STR, LINEAR_UNIT(home_offset.i), - SP_J_STR, LINEAR_UNIT(home_offset.j), - SP_K_STR, LINEAR_UNIT(home_offset.k) + SP_I_STR, I_AXIS_UNIT(home_offset.i), + SP_J_STR, J_AXIS_UNIT(home_offset.j), + SP_K_STR, K_AXIS_UNIT(home_offset.k), + SP_U_STR, U_AXIS_UNIT(home_offset.u), + SP_V_STR, V_AXIS_UNIT(home_offset.v), + SP_W_STR, W_AXIS_UNIT(home_offset.w) ) #else PSTR(" M206 Z"), LINEAR_UNIT(home_offset.z) @@ -85,7 +94,7 @@ void GcodeSuite::M428() { if (homing_needed_error()) return; xyz_float_t diff; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { diff[i] = base_home_pos((AxisEnum)i) - current_position[i]; if (!WITHIN(diff[i], -20, 20) && home_dir((AxisEnum)i) > 0) diff[i] = -current_position[i]; @@ -97,7 +106,7 @@ void GcodeSuite::M428() { } } - LOOP_LINEAR_AXES(i) set_home_offset((AxisEnum)i, diff[i]); + LOOP_NUM_AXES(i) set_home_offset((AxisEnum)i, diff[i]); report_current_position(); LCD_MESSAGE(MSG_HOME_OFFSETS_APPLIED); OKAY_BUZZ(); diff --git a/Marlin/src/gcode/host/M114.cpp b/Marlin/src/gcode/host/M114.cpp index cdb9efb71b26..41433b510d22 100644 --- a/Marlin/src/gcode/host/M114.cpp +++ b/Marlin/src/gcode/host/M114.cpp @@ -47,7 +47,7 @@ void report_linear_axis_pos(const xyz_pos_t &pos, const uint8_t precision=3) { char str[12]; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { SERIAL_CHAR(' ', AXIS_CHAR(a), ':'); SERIAL_ECHO(dtostrf(pos[a], 1, precision, str)); } @@ -134,6 +134,15 @@ #if AXIS_IS_L64XX(K) REPORT_ABSOLUTE_POS(K); #endif + #if AXIS_IS_L64XX(U) + REPORT_ABSOLUTE_POS(U); + #endif + #if AXIS_IS_L64XX(V) + REPORT_ABSOLUTE_POS(V); + #endif + #if AXIS_IS_L64XX(W) + REPORT_ABSOLUTE_POS(W); + #endif #if AXIS_IS_L64XX(E0) REPORT_ABSOLUTE_POS(E0); #endif @@ -184,7 +193,10 @@ cartes.x, cartes.y, cartes.z, planner.get_axis_position_mm(I_AXIS), planner.get_axis_position_mm(J_AXIS), - planner.get_axis_position_mm(K_AXIS) + planner.get_axis_position_mm(K_AXIS), + planner.get_axis_position_mm(U_AXIS), + planner.get_axis_position_mm(V_AXIS), + planner.get_axis_position_mm(W_AXIS) ); report_all_axis_pos(from_steppers); diff --git a/Marlin/src/gcode/host/M115.cpp b/Marlin/src/gcode/host/M115.cpp index 36731c23da16..d38bd6612d9c 100644 --- a/Marlin/src/gcode/host/M115.cpp +++ b/Marlin/src/gcode/host/M115.cpp @@ -65,8 +65,8 @@ void GcodeSuite::M115() { "PROTOCOL_VERSION:" PROTOCOL_VERSION " " "MACHINE_TYPE:" MACHINE_NAME " " "EXTRUDER_COUNT:" STRINGIFY(EXTRUDERS) " " - #if LINEAR_AXES != XYZ - "AXIS_COUNT:" STRINGIFY(LINEAR_AXES) " " + #if NUM_AXES != XYZ + "AXIS_COUNT:" STRINGIFY(NUM_AXES) " " #endif #ifdef MACHINE_UUID "UUID:" MACHINE_UUID diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp index 493fd00da187..d647894d2774 100644 --- a/Marlin/src/gcode/motion/G0_G1.cpp +++ b/Marlin/src/gcode/motion/G0_G1.cpp @@ -49,13 +49,16 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) { if (IsRunning() #if ENABLED(NO_MOTION_BEFORE_HOMING) && !homing_needed_error( - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( (parser.seen_test('X') ? _BV(X_AXIS) : 0), | (parser.seen_test('Y') ? _BV(Y_AXIS) : 0), | (parser.seen_test('Z') ? _BV(Z_AXIS) : 0), | (parser.seen_test(AXIS4_NAME) ? _BV(I_AXIS) : 0), | (parser.seen_test(AXIS5_NAME) ? _BV(J_AXIS) : 0), - | (parser.seen_test(AXIS6_NAME) ? _BV(K_AXIS) : 0)) + | (parser.seen_test(AXIS6_NAME) ? _BV(K_AXIS) : 0), + | (parser.seen_test(AXIS7_NAME) ? _BV(U_AXIS) : 0), + | (parser.seen_test(AXIS8_NAME) ? _BV(V_AXIS) : 0), + | (parser.seen_test(AXIS9_NAME) ? _BV(W_AXIS) : 0)) ) #endif ) { @@ -89,7 +92,7 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) { if (MIN_AUTORETRACT <= MAX_AUTORETRACT) { // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves if (fwretract.autoretract_enabled && parser.seen_test('E') - && !parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K)) + && !parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)) ) { const float echange = destination.e - current_position.e; // Is this a retract or recover move? diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp index 0c7bdc7a3a40..dd1c1d14708f 100644 --- a/Marlin/src/gcode/motion/G2_G3.cpp +++ b/Marlin/src/gcode/motion/G2_G3.cpp @@ -48,8 +48,8 @@ #define MIN_ARC_SEGMENT_MM MAX_ARC_SEGMENT_MM #endif -#define ARC_LIJK_CODE(L,I,J,K) CODE_N(SUB2(LINEAR_AXES),L,I,J,K) -#define ARC_LIJKE_CODE(L,I,J,K,E) ARC_LIJK_CODE(L,I,J,K); CODE_ITEM_E(E) +#define ARC_LIJKUVW_CODE(L,I,J,K,U,V,W) CODE_N(SUB2(NUM_AXES),L,I,J,K,U,V,W) +#define ARC_LIJKUVWE_CODE(L,I,J,K,U,V,W,E) ARC_LIJKUVW_CODE(L,I,J,K,U,V,W); CODE_ITEM_E(E) /** * Plan an arc in 2 dimensions, with linear motion in the other axes. @@ -82,11 +82,14 @@ void plan_arc( rt_X = cart[axis_p] - center_P, rt_Y = cart[axis_q] - center_Q; - ARC_LIJK_CODE( + ARC_LIJKUVW_CODE( const float start_L = current_position[axis_l], const float start_I = current_position.i, const float start_J = current_position.j, - const float start_K = current_position.k + const float start_K = current_position.k, + const float start_U = current_position.u, + const float start_V = current_position.v, + const float start_W = current_position.w ); // Angle of rotation between position and target from the circle center. @@ -122,11 +125,14 @@ void plan_arc( min_segments = CEIL((MIN_CIRCLE_SEGMENTS) * portion_of_circle); // Minimum segments for the arc } - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( float travel_L = cart[axis_l] - start_L, float travel_I = cart.i - start_I, float travel_J = cart.j - start_J, float travel_K = cart.k - start_K, + float travel_U = cart.u - start_U, + float travel_V = cart.v - start_V, + float travel_W = cart.w - start_W, float travel_E = cart.e - current_position.e ); @@ -135,30 +141,39 @@ void plan_arc( const float total_angular = abs_angular_travel + circles * RADIANS(360), // Total rotation with all circles and remainder part_per_circle = RADIANS(360) / total_angular; // Each circle's part of the total - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( const float per_circle_L = travel_L * part_per_circle, // L movement per circle const float per_circle_I = travel_I * part_per_circle, const float per_circle_J = travel_J * part_per_circle, const float per_circle_K = travel_K * part_per_circle, + const float per_circle_U = travel_U * part_per_circle, + const float per_circle_V = travel_V * part_per_circle, + const float per_circle_W = travel_W * part_per_circle, const float per_circle_E = travel_E * part_per_circle // E movement per circle ); xyze_pos_t temp_position = current_position; for (uint16_t n = circles; n--;) { - ARC_LIJKE_CODE( // Destination Linear Axes + ARC_LIJKUVWE_CODE( // Destination Linear Axes temp_position[axis_l] += per_circle_L, temp_position.i += per_circle_I, temp_position.j += per_circle_J, temp_position.k += per_circle_K, + temp_position.u += per_circle_U, + temp_position.v += per_circle_V, + temp_position.w += per_circle_W, temp_position.e += per_circle_E // Destination E axis ); plan_arc(temp_position, offset, clockwise, 0); // Plan a single whole circle } - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( travel_L = cart[axis_l] - current_position[axis_l], travel_I = cart.i - current_position.i, travel_J = cart.j - current_position.j, travel_K = cart.k - current_position.k, + travel_U = cart.u - current_position.u, + travel_V = cart.v - current_position.v, + travel_W = cart.w - current_position.w, travel_E = cart.e - current_position.e ); } @@ -168,11 +183,14 @@ void plan_arc( // Return if the move is near zero if (flat_mm < 0.0001f - GANG_N(SUB2(LINEAR_AXES), + GANG_N(SUB2(NUM_AXES), && travel_L < 0.0001f, && travel_I < 0.0001f, && travel_J < 0.0001f, - && travel_K < 0.0001f + && travel_K < 0.0001f, + && travel_U < 0.0001f, + && travel_V < 0.0001f, + && travel_W < 0.0001f ) ) return; @@ -236,11 +254,14 @@ void plan_arc( cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation #if DISABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE( + ARC_LIJKUVW_CODE( const float per_segment_L = proportion * travel_L / segments, const float per_segment_I = proportion * travel_I / segments, const float per_segment_J = proportion * travel_J / segments, - const float per_segment_K = proportion * travel_K / segments + const float per_segment_K = proportion * travel_K / segments, + const float per_segment_U = proportion * travel_U / segments, + const float per_segment_V = proportion * travel_V / segments, + const float per_segment_W = proportion * travel_W / segments ); #endif @@ -250,11 +271,14 @@ void plan_arc( if (tooshort) segments++; // Initialize all linear axes and E - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( raw[axis_l] = current_position[axis_l], raw.i = current_position.i, raw.j = current_position.j, raw.k = current_position.k, + raw.u = current_position.u, + raw.v = current_position.v, + raw.w = current_position.w, raw.e = current_position.e ); @@ -303,11 +327,15 @@ void plan_arc( // Update raw location raw[axis_p] = center_P + rvec.a; raw[axis_q] = center_Q + rvec.b; - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( #if ENABLED(AUTO_BED_LEVELING_UBL) - raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_V #else - raw[axis_l] += per_segment_L, raw.i += per_segment_I, raw.j += per_segment_J, raw.k += per_segment_K + raw[axis_l] += per_segment_L, + raw.i += per_segment_I, raw.j += per_segment_J, raw.k += per_segment_K, + raw.u += per_segment_U, raw.v += per_segment_V, raw.w += per_segment_W #endif , raw.e += extruder_per_segment ); @@ -325,7 +353,11 @@ void plan_arc( // Ensure last segment arrives at target location. raw = cart; #if ENABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE(raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K); + ARC_LIJKUVW_CODE( + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_W + ); #endif apply_motion_limits(raw); @@ -337,7 +369,11 @@ void plan_arc( planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, 0 OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)); #if ENABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE(raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K); + ARC_LIJKUVW_CODE( + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_W + ); #endif current_position = raw; @@ -380,7 +416,7 @@ void GcodeSuite::G2_G3(const bool clockwise) { relative_mode = true; #endif - get_destination_from_command(); // Get X Y [Z[I[J[K]]]] [E] F (and set cutter power) + get_destination_from_command(); // Get X Y [Z[I[J[K...]]]] [E] F (and set cutter power) TERN_(SF_ARC_FIX, relative_mode = relative_mode_backup); diff --git a/Marlin/src/gcode/motion/M290.cpp b/Marlin/src/gcode/motion/M290.cpp index f3d7b7c8dca2..8185bf8f78b4 100644 --- a/Marlin/src/gcode/motion/M290.cpp +++ b/Marlin/src/gcode/motion/M290.cpp @@ -69,7 +69,7 @@ */ void GcodeSuite::M290() { #if ENABLED(BABYSTEP_XY) - LOOP_LINEAR_AXES(a) + LOOP_NUM_AXES(a) if (parser.seenval(AXIS_CHAR(a)) || (a == Z_AXIS && parser.seenval('S'))) { const float offs = constrain(parser.value_axis_units((AxisEnum)a), -2, 2); babystep.add_mm((AxisEnum)a, offs); @@ -87,7 +87,7 @@ void GcodeSuite::M290() { } #endif - if (!parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K)) || parser.seen('R')) { + if (!parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)) || parser.seen('R')) { SERIAL_ECHO_START(); #if ENABLED(BABYSTEP_ZPROBE_OFFSET) diff --git a/Marlin/src/gcode/parser.cpp b/Marlin/src/gcode/parser.cpp index 4d4fdae0d621..3fc1fc1625ad 100644 --- a/Marlin/src/gcode/parser.cpp +++ b/Marlin/src/gcode/parser.cpp @@ -248,7 +248,7 @@ void GCodeParser::parse(char *p) { case 'R': if (!WITHIN(motion_mode_codenum, 2, 3)) return; #endif - LOGICAL_AXIS_GANG(case 'E':, case 'X':, case 'Y':, case 'Z':, case AXIS4_NAME:, case AXIS5_NAME:, case AXIS6_NAME:) + LOGICAL_AXIS_GANG(case 'E':, case 'X':, case 'Y':, case 'Z':, case AXIS4_NAME:, case AXIS5_NAME:, case AXIS6_NAME:, case AXIS7_NAME:, case AXIS8_NAME:, case AXIS9_NAME:) case 'F': if (motion_mode_codenum < 0) return; command_letter = 'G'; diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h index 1487c083ec60..c91a0de5f219 100644 --- a/Marlin/src/gcode/parser.h +++ b/Marlin/src/gcode/parser.h @@ -309,13 +309,18 @@ class GCodeParser { } static float axis_unit_factor(const AxisEnum axis) { - return ( - #if HAS_EXTRUDERS - axis >= E_AXIS && volumetric_enabled ? volumetric_unit_factor : linear_unit_factor - #else - linear_unit_factor - #endif - ); + if (false + || TERN0(AXIS4_ROTATES, axis == I_AXIS) + || TERN0(AXIS5_ROTATES, axis == J_AXIS) + || TERN0(AXIS6_ROTATES, axis == K_AXIS) + || TERN0(AXIS7_ROTATES, axis == U_AXIS) + || TERN0(AXIS8_ROTATES, axis == V_AXIS) + || TERN0(AXIS9_ROTATES, axis == W_AXIS) + ) return 1.0f; + #if HAS_EXTRUDERS + if (axis >= E_AXIS && volumetric_enabled) return volumetric_unit_factor; + #endif + return linear_unit_factor; } static float linear_value_to_mm(const_float_t v) { return v * linear_unit_factor; } @@ -340,6 +345,13 @@ class GCodeParser { #define LINEAR_UNIT(V) parser.mm_to_linear_unit(V) #define VOLUMETRIC_UNIT(V) parser.mm_to_volumetric_unit(V) + #define I_AXIS_UNIT(V) TERN(AXIS4_ROTATES, (V), LINEAR_UNIT(V)) + #define J_AXIS_UNIT(V) TERN(AXIS5_ROTATES, (V), LINEAR_UNIT(V)) + #define K_AXIS_UNIT(V) TERN(AXIS6_ROTATES, (V), LINEAR_UNIT(V)) + #define U_AXIS_UNIT(V) TERN(AXIS7_ROTATES, (V), LINEAR_UNIT(V)) + #define V_AXIS_UNIT(V) TERN(AXIS8_ROTATES, (V), LINEAR_UNIT(V)) + #define W_AXIS_UNIT(V) TERN(AXIS9_ROTATES, (V), LINEAR_UNIT(V)) + static float value_linear_units() { return linear_value_to_mm(value_float()); } static float value_axis_units(const AxisEnum axis) { return axis_value_to_mm(axis, value_float()); } static float value_per_axis_units(const AxisEnum axis) { return per_axis_value(axis, value_float()); } diff --git a/Marlin/src/gcode/probe/G38.cpp b/Marlin/src/gcode/probe/G38.cpp index 6906805fca14..ed24ce3258d9 100644 --- a/Marlin/src/gcode/probe/G38.cpp +++ b/Marlin/src/gcode/probe/G38.cpp @@ -49,7 +49,7 @@ inline bool G38_run_probe() { #if MULTIPLE_PROBING > 1 // Get direction of move and retract xyz_float_t retract_mm; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { const float dist = destination[i] - current_position[i]; retract_mm[i] = ABS(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm((AxisEnum)i) * (dist > 0 ? -1 : 1); } @@ -119,7 +119,7 @@ void GcodeSuite::G38(const int8_t subcode) { ; // If any axis has enough movement, do the move - LOOP_LINEAR_AXES(i) + LOOP_NUM_AXES(i) if (ABS(destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) { if (!parser.seenval('F')) feedrate_mm_s = homing_feedrate((AxisEnum)i); // If G38.2 fails throw an error diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index e7473420cf9d..5adc04fe2da0 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -677,22 +677,31 @@ #endif /** - * Number of Linear Axes (e.g., XYZ) + * Number of Linear Axes (e.g., XYZIJKUVW) * All the logical axes except for the tool (E) axis */ -#ifndef LINEAR_AXES - #define LINEAR_AXES XYZ +#ifndef NUM_AXES + #define NUM_AXES XYZ #endif -#if LINEAR_AXES >= XY +#if NUM_AXES >= XY #define HAS_Y_AXIS 1 - #if LINEAR_AXES >= XYZ + #if NUM_AXES >= XYZ #define HAS_Z_AXIS 1 - #if LINEAR_AXES >= 4 + #if NUM_AXES >= 4 #define HAS_I_AXIS 1 - #if LINEAR_AXES >= 5 + #if NUM_AXES >= 5 #define HAS_J_AXIS 1 - #if LINEAR_AXES >= 6 + #if NUM_AXES >= 6 #define HAS_K_AXIS 1 + #if NUM_AXES >= 7 + #define HAS_U_AXIS 1 + #if NUM_AXES >= 8 + #define HAS_V_AXIS 1 + #if NUM_AXES >= 9 + #define HAS_W_AXIS 1 + #endif + #endif + #endif #endif #endif #endif @@ -700,14 +709,58 @@ #endif /** - * Number of Logical Axes (e.g., XYZE) - * All the logical axes that can be commanded directly by G-code. + * 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 NUM_AXES +#endif + +/** + * Number of Secondary Axes (e.g., IJKUVW) + * All linear/rotational axes between XYZ and E. + */ +#define SECONDARY_AXES SUB3(NUM_AXES) + +/** + * Number of Rotational Axes (e.g., IJK) + * All axes for which AXIS*_ROTATES is defined. + * For these axes, positions are specified in angular degrees. + */ +#if ENABLED(AXIS9_ROTATES) + #define ROTATIONAL_AXES 6 +#elif ENABLED(AXIS8_ROTATES) + #define ROTATIONAL_AXES 5 +#elif ENABLED(AXIS7_ROTATES) + #define ROTATIONAL_AXES 4 +#elif ENABLED(AXIS6_ROTATES) + #define ROTATIONAL_AXES 3 +#elif ENABLED(AXIS5_ROTATES) + #define ROTATIONAL_AXES 2 +#elif ENABLED(AXIS4_ROTATES) + #define ROTATIONAL_AXES 1 +#else + #define ROTATIONAL_AXES 0 +#endif + +/** + * Number of Secondary Linear Axes (e.g., UVW) + * All secondary axes for which AXIS*_ROTATES is not defined. + * Excluding primary axes and excluding duplicate axes (X2, Y2, Z2, Z3, Z4) + */ +#define SECONDARY_LINEAR_AXES (NUM_AXES - PRIMARY_LINEAR_AXES - ROTATIONAL_AXES) + +/** + * Number of Logical Axes (e.g., XYZIJKUVWE) + * All logical axes that can be commanded directly by G-code. * Delta maps stepper-specific values to ABC steppers. */ #if HAS_EXTRUDERS - #define LOGICAL_AXES INCREMENT(LINEAR_AXES) + #define LOGICAL_AXES INCREMENT(NUM_AXES) #else - #define LOGICAL_AXES LINEAR_AXES + #define LOGICAL_AXES NUM_AXES #endif /** @@ -725,7 +778,7 @@ * distinguished. */ #if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1 - #define DISTINCT_AXES (LINEAR_AXES + E_STEPPERS) + #define DISTINCT_AXES (NUM_AXES + E_STEPPERS) #define DISTINCT_E E_STEPPERS #define E_INDEX_N(E) (E) #else @@ -955,6 +1008,21 @@ #elif K_HOME_DIR < 0 #define K_HOME_TO_MIN 1 #endif +#if U_HOME_DIR > 0 + #define U_HOME_TO_MAX 1 +#elif U_HOME_DIR < 0 + #define U_HOME_TO_MIN 1 +#endif +#if V_HOME_DIR > 0 + #define V_HOME_TO_MAX 1 +#elif V_HOME_DIR < 0 + #define V_HOME_TO_MIN 1 +#endif +#if W_HOME_DIR > 0 + #define W_HOME_TO_MAX 1 +#elif W_HOME_DIR < 0 + #define W_HOME_TO_MIN 1 +#endif /** * Conditionals based on the type of Bed Probe @@ -1228,6 +1296,15 @@ #if HAS_K_AXIS && !defined(INVERT_K_DIR) #define INVERT_K_DIR false #endif +#if HAS_U_AXIS && !defined(INVERT_U_DIR) + #define INVERT_U_DIR false +#endif +#if HAS_V_AXIS && !defined(INVERT_V_DIR) + #define INVERT_V_DIR false +#endif +#if HAS_W_AXIS && !defined(INVERT_W_DIR) + #define INVERT_W_DIR false +#endif #if HAS_EXTRUDERS && !defined(INVERT_E_DIR) #define INVERT_E_DIR false #endif diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index 8a85536aea48..ace946d766dd 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -914,30 +914,45 @@ #endif // Remove unused STEALTHCHOP flags -#if LINEAR_AXES < 6 - #undef STEALTHCHOP_K - #undef CALIBRATION_MEASURE_KMIN - #undef CALIBRATION_MEASURE_KMAX - #if LINEAR_AXES < 5 - #undef STEALTHCHOP_J - #undef CALIBRATION_MEASURE_JMIN - #undef CALIBRATION_MEASURE_JMAX - #if LINEAR_AXES < 4 - #undef STEALTHCHOP_I - #undef CALIBRATION_MEASURE_IMIN - #undef CALIBRATION_MEASURE_IMAX - #if LINEAR_AXES < 3 - #undef Z_IDLE_HEIGHT - #undef STEALTHCHOP_Z - #undef Z_PROBE_SLED - #undef Z_SAFE_HOMING - #undef HOME_Z_FIRST - #undef HOMING_Z_WITH_PROBE - #undef ENABLE_LEVELING_FADE_HEIGHT - #undef NUM_Z_STEPPER_DRIVERS - #undef CNC_WORKSPACE_PLANES - #if LINEAR_AXES < 2 - #undef STEALTHCHOP_Y +#if NUM_AXES < 9 + #undef STEALTHCHOP_W + #undef CALIBRATION_MEASURE_WMIN + #undef CALIBRATION_MEASURE_WMAX + #if NUM_AXES < 8 + #undef STEALTHCHOP_V + #undef CALIBRATION_MEASURE_VMIN + #undef CALIBRATION_MEASURE_VMAX + #if NUM_AXES < 7 + #undef STEALTHCHOP_U + #undef CALIBRATION_MEASURE_UMIN + #undef CALIBRATION_MEASURE_UMAX + #if NUM_AXES < 6 + #undef STEALTHCHOP_K + #undef CALIBRATION_MEASURE_KMIN + #undef CALIBRATION_MEASURE_KMAX + #if NUM_AXES < 5 + #undef STEALTHCHOP_J + #undef CALIBRATION_MEASURE_JMIN + #undef CALIBRATION_MEASURE_JMAX + #if NUM_AXES < 4 + #undef STEALTHCHOP_I + #undef CALIBRATION_MEASURE_IMIN + #undef CALIBRATION_MEASURE_IMAX + #if NUM_AXES < 3 + #undef Z_IDLE_HEIGHT + #undef STEALTHCHOP_Z + #undef Z_PROBE_SLED + #undef Z_SAFE_HOMING + #undef HOME_Z_FIRST + #undef HOMING_Z_WITH_PROBE + #undef ENABLE_LEVELING_FADE_HEIGHT + #undef NUM_Z_STEPPER_DRIVERS + #undef CNC_WORKSPACE_PLANES + #if NUM_AXES < 2 + #undef STEALTHCHOP_Y + #endif + #endif + #endif #endif #endif #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 85ccb8088ec2..ada2a512b527 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -87,6 +87,19 @@ #if HAS_K_AXIS && !defined(AXIS6_NAME) #define AXIS6_NAME 'C' #endif +#if HAS_U_AXIS && !defined(AXIS7_NAME) + #define AXIS7_NAME 'U' +#endif +#if HAS_V_AXIS && !defined(AXIS8_NAME) + #define AXIS8_NAME 'V' +#endif +#if HAS_W_AXIS && !defined(AXIS9_NAME) + #define AXIS9_NAME 'W' +#endif + +#if ANY(AXIS4_ROTATES, AXIS5_ROTATES, AXIS6_ROTATES, AXIS7_ROTATES, AXIS8_ROTATES, AXIS9_ROTATES) + #define HAS_ROTATIONAL_AXES 1 +#endif #define X_MAX_LENGTH (X_MAX_POS - (X_MIN_POS)) #if HAS_Y_AXIS @@ -106,6 +119,15 @@ #if HAS_K_AXIS #define K_MAX_LENGTH (K_MAX_POS - (K_MIN_POS)) #endif +#if HAS_U_AXIS + #define U_MAX_LENGTH (U_MAX_POS - (U_MIN_POS)) +#endif +#if HAS_V_AXIS + #define V_MAX_LENGTH (V_MAX_POS - (V_MIN_POS)) +#endif +#if HAS_W_AXIS + #define W_MAX_LENGTH (W_MAX_POS - (W_MIN_POS)) +#endif // Defined only if the sanity-check is bypassed #ifndef X_BED_SIZE @@ -123,6 +145,15 @@ #if HAS_K_AXIS && !defined(K_BED_SIZE) #define K_BED_SIZE K_MAX_LENGTH #endif +#if HAS_U_AXIS && !defined(U_BED_SIZE) + #define U_BED_SIZE U_MAX_LENGTH +#endif +#if HAS_V_AXIS && !defined(V_BED_SIZE) + #define V_BED_SIZE V_MAX_LENGTH +#endif +#if HAS_W_AXIS && !defined(W_BED_SIZE) + #define W_BED_SIZE W_MAX_LENGTH +#endif // Require 0,0 bed center for Delta and SCARA #if IS_KINEMATIC @@ -143,6 +174,15 @@ #if HAS_K_AXIS #define _K_HALF_KMAX ((K_BED_SIZE) / 2) #endif +#if HAS_U_AXIS + #define _U_HALF_UMAX ((U_BED_SIZE) / 2) +#endif +#if HAS_V_AXIS + #define _V_HALF_VMAX ((V_BED_SIZE) / 2) +#endif +#if HAS_W_AXIS + #define _W_HALF_WMAX ((W_BED_SIZE) / 2) +#endif #define X_CENTER TERN(BED_CENTER_AT_0_0, 0, _X_HALF_BED) #if HAS_Y_AXIS @@ -158,6 +198,15 @@ #if HAS_K_AXIS #define K_CENTER TERN(BED_CENTER_AT_0_0, 0, _K_HALF_BED) #endif +#if HAS_U_AXIS + #define U_CENTER TERN(BED_CENTER_AT_0_0, 0, _U_HALF_BED) +#endif +#if HAS_V_AXIS + #define V_CENTER TERN(BED_CENTER_AT_0_0, 0, _V_HALF_BED) +#endif +#if HAS_W_AXIS + #define W_CENTER TERN(BED_CENTER_AT_0_0, 0, _W_HALF_BED) +#endif // Get the linear boundaries of the bed #define X_MIN_BED (X_CENTER - _X_HALF_BED) @@ -178,6 +227,18 @@ #define K_MINIM (K_CENTER - _K_HALF_BED_SIZE) #define K_MAXIM (K_MINIM + K_BED_SIZE) #endif +#if HAS_U_AXIS + #define U_MINIM (U_CENTER - _U_HALF_BED_SIZE) + #define U_MAXIM (U_MINIM + U_BED_SIZE) +#endif +#if HAS_V_AXIS + #define V_MINIM (V_CENTER - _V_HALF_BED_SIZE) + #define V_MAXIM (V_MINIM + V_BED_SIZE) +#endif +#if HAS_W_AXIS + #define W_MINIM (W_CENTER - _W_HALF_BED_SIZE) + #define W_MAXIM (W_MINIM + W_BED_SIZE) +#endif /** * Dual X Carriage @@ -274,6 +335,27 @@ #define K_HOME_POS TERN(K_HOME_TO_MIN, K_MIN_POS, K_MAX_POS) #endif #endif +#if HAS_U_AXIS + #ifdef MANUAL_U_HOME_POS + #define U_HOME_POS MANUAL_U_HOME_POS + #else + #define U_HOME_POS (U_HOME_DIR < 0 ? U_MIN_POS : U_MAX_POS) + #endif +#endif +#if HAS_V_AXIS + #ifdef MANUAL_V_HOME_POS + #define V_HOME_POS MANUAL_V_HOME_POS + #else + #define V_HOME_POS (V_HOME_DIR < 0 ? V_MIN_POS : V_MAX_POS) + #endif +#endif +#if HAS_W_AXIS + #ifdef MANUAL_W_HOME_POS + #define W_HOME_POS MANUAL_W_HOME_POS + #else + #define W_HOME_POS (W_HOME_DIR < 0 ? W_MIN_POS : W_MAX_POS) + #endif +#endif /** * If DELTA_HEIGHT isn't defined use the old setting @@ -1440,6 +1522,15 @@ #if ENABLED(USE_KMAX_PLUG) #define ENDSTOPPULLUP_KMAX #endif + #if ENABLED(USE_UMAX_PLUG) + #define ENDSTOPPULLUP_UMAX + #endif + #if ENABLED(USE_VMAX_PLUG) + #define ENDSTOPPULLUP_VMAX + #endif + #if ENABLED(USE_WMAX_PLUG) + #define ENDSTOPPULLUP_WMAX + #endif #if ENABLED(USE_XMIN_PLUG) #define ENDSTOPPULLUP_XMIN #endif @@ -1458,6 +1549,15 @@ #if ENABLED(USE_KMIN_PLUG) #define ENDSTOPPULLUP_KMIN #endif + #if ENABLED(USE_UMIN_PLUG) + #define ENDSTOPPULLUP_UMIN + #endif + #if ENABLED(USE_VMIN_PLUG) + #define ENDSTOPPULLUP_VMIN + #endif + #if ENABLED(USE_WMIN_PLUG) + #define ENDSTOPPULLUP_WMIN + #endif #endif /** @@ -1680,6 +1780,66 @@ #undef DISABLE_INACTIVE_K #endif +#if HAS_U_AXIS + #if PIN_EXISTS(U_ENABLE) || AXIS_IS_L64XX(U) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(U)) + #define HAS_U_ENABLE 1 + #endif + #if PIN_EXISTS(U_DIR) + #define HAS_U_DIR 1 + #endif + #if PIN_EXISTS(U_STEP) + #define HAS_U_STEP 1 + #endif + #if PIN_EXISTS(U_MS1) + #define HAS_U_MS_PINS 1 + #endif + #if !defined(DISABLE_INACTIVE_U) && ENABLED(DISABLE_U) + #define DISABLE_INACTIVE_U 1 + #endif +#else + #undef DISABLE_INACTIVE_U +#endif + +#if HAS_V_AXIS + #if PIN_EXISTS(V_ENABLE) || AXIS_IS_L64XX(V) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(V)) + #define HAS_V_ENABLE 1 + #endif + #if PIN_EXISTS(V_DIR) + #define HAS_V_DIR 1 + #endif + #if PIN_EXISTS(V_STEP) + #define HAS_V_STEP 1 + #endif + #if PIN_EXISTS(V_MS1) + #define HAS_V_MS_PINS 1 + #endif + #if !defined(DISABLE_INACTIVE_V) && ENABLED(DISABLE_V) + #define DISABLE_INACTIVE_V 1 + #endif +#else + #undef DISABLE_INACTIVE_V +#endif + +#if HAS_W_AXIS + #if PIN_EXISTS(W_ENABLE) || AXIS_IS_L64XX(W) || (ENABLED(SOFTWARE_DRIVER_ENABLE) && AXIS_IS_TMC(W)) + #define HAS_W_ENABLE 1 + #endif + #if PIN_EXISTS(W_DIR) + #define HAS_W_DIR 1 + #endif + #if PIN_EXISTS(W_STEP) + #define HAS_W_STEP 1 + #endif + #if PIN_EXISTS(W_MS1) + #define HAS_W_MS_PINS 1 + #endif + #if !defined(DISABLE_INACTIVE_W) && ENABLED(DISABLE_W) + #define DISABLE_INACTIVE_W 1 + #endif +#else + #undef DISABLE_INACTIVE_W +#endif + // Extruder steppers and solenoids #if HAS_EXTRUDERS @@ -1848,7 +2008,7 @@ // #if HAS_TRINAMIC_CONFIG - #if ANY(STEALTHCHOP_E, STEALTHCHOP_XY, STEALTHCHOP_Z, STEALTHCHOP_I, STEALTHCHOP_J, STEALTHCHOP_K) + #if ANY(STEALTHCHOP_E, STEALTHCHOP_XY, STEALTHCHOP_Z, STEALTHCHOP_I, STEALTHCHOP_J, STEALTHCHOP_K, STEALTHCHOP_U, STEALTHCHOP_V, STEALTHCHOP_W) #define STEALTHCHOP_ENABLED 1 #endif #if EITHER(SENSORLESS_HOMING, SENSORLESS_PROBING) @@ -1937,6 +2097,15 @@ #define Y2_SLAVE_ADDRESS 0 #endif #endif + #if HAS_U_AXIS + #define U_SPI_SENSORLESS U_SENSORLESS + #endif + #if HAS_V_AXIS + #define V_SPI_SENSORLESS V_SENSORLESS + #endif + #if HAS_W_AXIS + #define W_SPI_SENSORLESS W_SENSORLESS + #endif #endif #if AXIS_IS_TMC(Z) @@ -2074,6 +2243,69 @@ #endif #endif + #if AXIS_IS_TMC(U) + #if defined(U_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(U) + #define U_SENSORLESS 1 + #endif + #if AXIS_HAS_STEALTHCHOP(U) + #define U_HAS_STEALTHCHOP 1 + #endif + #if ENABLED(SPI_ENDSTOPS) + #define U_SPI_SENSORLESS U_SENSORLESS + #endif + #ifndef U_INTERPOLATE + #define U_INTERPOLATE INTERPOLATE + #endif + #ifndef U_HOLD_MULTIPLIER + #define U_HOLD_MULTIPLIER HOLD_MULTIPLIER + #endif + #ifndef U_SLAVE_ADDRESS + #define U_SLAVE_ADDRESS 0 + #endif + #endif + + #if AXIS_IS_TMC(V) + #if defined(V_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(V) + #define V_SENSORLESS 1 + #endif + #if AXIS_HAS_STEALTHCHOP(V) + #define V_HAS_STEALTHCHOP 1 + #endif + #if ENABLED(SPI_ENDSTOPS) + #define V_SPI_SENSORLESS V_SENSORLESS + #endif + #ifndef V_INTERPOLATE + #define V_INTERPOLATE INTERPOLATE + #endif + #ifndef V_HOLD_MULTIPLIER + #define V_HOLD_MULTIPLIER HOLD_MULTIPLIER + #endif + #ifndef V_SLAVE_ADDRESS + #define V_SLAVE_ADDRESS 0 + #endif + #endif + + #if AXIS_IS_TMC(W) + #if defined(W_STALL_SENSITIVITY) && AXIS_HAS_STALLGUARD(W) + #define W_SENSORLESS 1 + #endif + #if AXIS_HAS_STEALTHCHOP(W) + #define W_HAS_STEALTHCHOP 1 + #endif + #if ENABLED(SPI_ENDSTOPS) + #define W_SPI_SENSORLESS W_SENSORLESS + #endif + #ifndef W_INTERPOLATE + #define W_INTERPOLATE INTERPOLATE + #endif + #ifndef W_HOLD_MULTIPLIER + #define W_HOLD_MULTIPLIER HOLD_MULTIPLIER + #endif + #ifndef W_SLAVE_ADDRESS + #define W_SLAVE_ADDRESS 0 + #endif + #endif + #if AXIS_IS_TMC(E0) #if AXIS_HAS_STEALTHCHOP(E0) #define E0_HAS_STEALTHCHOP 1 @@ -2215,6 +2447,7 @@ #define ANY_SERIAL_IS(N) ( CONF_SERIAL_IS(N) \ || TMC_UART_IS(X, N) || TMC_UART_IS(Y , N) || TMC_UART_IS(Z , N) \ || TMC_UART_IS(I, N) || TMC_UART_IS(J , N) || TMC_UART_IS(K , N) \ + || TMC_UART_IS(U, N) || TMC_UART_IS(V , N) || TMC_UART_IS(W , N) \ || TMC_UART_IS(X2, N) || TMC_UART_IS(Y2, N) || TMC_UART_IS(Z2, N) || TMC_UART_IS(Z3, N) || TMC_UART_IS(Z4, N) \ || TMC_UART_IS(E0, N) || TMC_UART_IS(E1, N) || TMC_UART_IS(E2, N) || TMC_UART_IS(E3, N) || TMC_UART_IS(E4, N) ) @@ -2349,6 +2582,24 @@ #if _HAS_STOP(K,MAX) #define HAS_K_MAX 1 #endif +#if _HAS_STOP(U,MIN) + #define HAS_U_MIN 1 +#endif +#if _HAS_STOP(U,MAX) + #define HAS_U_MAX 1 +#endif +#if _HAS_STOP(V,MIN) + #define HAS_V_MIN 1 +#endif +#if _HAS_STOP(V,MAX) + #define HAS_V_MAX 1 +#endif +#if _HAS_STOP(W,MIN) + #define HAS_W_MIN 1 +#endif +#if _HAS_STOP(W,MAX) + #define HAS_W_MAX 1 +#endif #if PIN_EXISTS(X2_MIN) #define HAS_X2_MIN 1 #endif @@ -2849,7 +3100,7 @@ #if HAS_EXTRUDERS && PIN_EXISTS(MOTOR_CURRENT_PWM_E) #define HAS_MOTOR_CURRENT_PWM_E 1 #endif -#if HAS_MOTOR_CURRENT_PWM_E || ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K) +#if HAS_MOTOR_CURRENT_PWM_E || ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_Z, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) #define HAS_MOTOR_CURRENT_PWM 1 #endif @@ -2859,7 +3110,7 @@ #if ANY(HAS_E0_MS_PINS, HAS_E1_MS_PINS, HAS_E2_MS_PINS, HAS_E3_MS_PINS, HAS_E4_MS_PINS, HAS_E5_MS_PINS, HAS_E6_MS_PINS, HAS_E7_MS_PINS) #define HAS_SOME_E_MS_PINS 1 #endif -#if ANY(HAS_X_MS_PINS, HAS_X2_MS_PINS, HAS_Y_MS_PINS, HAS_Y2_MS_PINS, HAS_SOME_Z_MS_PINS, HAS_I_MS_PINS, HAS_J_MS_PINS, HAS_K_MS_PINS, HAS_SOME_E_MS_PINS) +#if ANY(HAS_X_MS_PINS, HAS_X2_MS_PINS, HAS_Y_MS_PINS, HAS_Y2_MS_PINS, HAS_SOME_Z_MS_PINS, HAS_I_MS_PINS, HAS_J_MS_PINS, HAS_K_MS_PINS, HAS_U_MS_PINS, HAS_V_MS_PINS, HAS_W_MS_PINS, HAS_SOME_E_MS_PINS) #define HAS_MICROSTEPS 1 #endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 665381207f3a..ec8b278b0213 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -35,8 +35,8 @@ #endif // Strings for sanity check messages -#define _LINEAR_AXES_STR LINEAR_AXIS_GANG("X ", "Y ", "Z ", "I ", "J ", "K ") -#define _LOGICAL_AXES_STR LOGICAL_AXIS_GANG("E ", "X ", "Y ", "Z ", "I ", "J ", "K ") +#define _NUM_AXES_STR NUM_AXIS_GANG("X ", "Y ", "Z ", "I ", "J ", "K ", "U ", "V ", "W ") +#define _LOGICAL_AXES_STR LOGICAL_AXIS_GANG("E ", "X ", "Y ", "Z ", "I ", "J ", "K ", "U ", "V ", "W ") // Make sure macros aren't borked #define TEST1 @@ -617,6 +617,8 @@ #error "Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS is now just Z_STEPPER_ALIGN_STEPPER_XY." #elif defined(DWIN_CREALITY_LCD_ENHANCED) #error "DWIN_CREALITY_LCD_ENHANCED is now DWIN_LCD_PROUI." +#elif defined(LINEAR_AXES) + #error "LINEAR_AXES is now NUM_AXES (to account for rotational axes)." #endif constexpr float arm[] = AXIS_RELATIVE_MODES; @@ -798,6 +800,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "Enable only one of ENDSTOPPULLUP_J_MAX or ENDSTOPPULLDOWN_J_MAX." #elif BOTH(ENDSTOPPULLUP_KMAX, ENDSTOPPULLDOWN_KMAX) #error "Enable only one of ENDSTOPPULLUP_K_MAX or ENDSTOPPULLDOWN_K_MAX." +#elif BOTH(ENDSTOPPULLUP_UMAX, ENDSTOPPULLDOWN_UMAX) + #error "Enable only one of ENDSTOPPULLUP_U_MAX or ENDSTOPPULLDOWN_U_MAX." +#elif BOTH(ENDSTOPPULLUP_VMAX, ENDSTOPPULLDOWN_VMAX) + #error "Enable only one of ENDSTOPPULLUP_V_MAX or ENDSTOPPULLDOWN_V_MAX." +#elif BOTH(ENDSTOPPULLUP_WMAX, ENDSTOPPULLDOWN_WMAX) + #error "Enable only one of ENDSTOPPULLUP_W_MAX or ENDSTOPPULLDOWN_W_MAX." #elif BOTH(ENDSTOPPULLUP_XMIN, ENDSTOPPULLDOWN_XMIN) #error "Enable only one of ENDSTOPPULLUP_X_MIN or ENDSTOPPULLDOWN_X_MIN." #elif BOTH(ENDSTOPPULLUP_YMIN, ENDSTOPPULLDOWN_YMIN) @@ -810,6 +818,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "Enable only one of ENDSTOPPULLUP_J_MIN or ENDSTOPPULLDOWN_J_MIN." #elif BOTH(ENDSTOPPULLUP_KMIN, ENDSTOPPULLDOWN_KMIN) #error "Enable only one of ENDSTOPPULLUP_K_MIN or ENDSTOPPULLDOWN_K_MIN." +#elif BOTH(ENDSTOPPULLUP_UMIN, ENDSTOPPULLDOWN_UMIN) + #error "Enable only one of ENDSTOPPULLUP_U_MIN or ENDSTOPPULLDOWN_U_MIN." +#elif BOTH(ENDSTOPPULLUP_VMIN, ENDSTOPPULLDOWN_VMIN) + #error "Enable only one of ENDSTOPPULLUP_V_MIN or ENDSTOPPULLDOWN_V_MIN." +#elif BOTH(ENDSTOPPULLUP_WMIN, ENDSTOPPULLDOWN_WMIN) + #error "Enable only one of ENDSTOPPULLUP_W_MIN or ENDSTOPPULLDOWN_W_MIN." #endif /** @@ -1417,16 +1431,18 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif /** - * Features that require a min/max/specific LINEAR_AXES + * Features that require a min/max/specific NUM_AXES */ #if HAS_LEVELING && !HAS_Z_AXIS #error "Leveling in Marlin requires three or more axes, with Z as the vertical axis." #elif ENABLED(CNC_WORKSPACE_PLANES) && !HAS_Z_AXIS - #error "CNC_WORKSPACE_PLANES currently requires LINEAR_AXES >= 3" -#elif ENABLED(DIRECT_STEPPING) && LINEAR_AXES > XYZ - #error "DIRECT_STEPPING currently requires LINEAR_AXES 3" -#elif ENABLED(FOAMCUTTER_XYUV) && LINEAR_AXES < 5 - #error "FOAMCUTTER_XYUV requires LINEAR_AXES >= 5." + #error "CNC_WORKSPACE_PLANES currently requires NUM_AXES >= 3" +#elif ENABLED(DIRECT_STEPPING) && NUM_AXES > XYZ + #error "DIRECT_STEPPING currently requires NUM_AXES 3" +#elif ENABLED(FOAMCUTTER_XYUV) && NUM_AXES < 5 + #error "FOAMCUTTER_XYUV requires NUM_AXES >= 5." +#elif ENABLED(LINEAR_ADVANCE) && HAS_I_AXIS + #error "LINEAR_ADVANCE currently requires NUM_AXES <= 3." #endif /** @@ -1434,33 +1450,76 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS */ #if HAS_I_AXIS #if !defined(I_MIN_POS) || !defined(I_MAX_POS) - #error "I_MIN_POS and I_MAX_POS are required with LINEAR_AXES >= 4." + #error "I_MIN_POS and I_MAX_POS are required with NUM_AXES >= 4." #elif !defined(I_HOME_DIR) - #error "I_HOME_DIR is required with LINEAR_AXES >= 4." + #error "I_HOME_DIR is required with NUM_AXES >= 4." #elif HAS_I_ENABLE && !defined(I_ENABLE_ON) - #error "I_ENABLE_ON is required for your I driver with LINEAR_AXES >= 4." + #error "I_ENABLE_ON is required for your I driver with NUM_AXES >= 4." #endif #endif #if HAS_J_AXIS #if AXIS5_NAME == AXIS4_NAME #error "AXIS5_NAME must be unique." + #elif ENABLED(AXIS5_ROTATES) && DISABLED(AXIS4_ROTATES) + #error "AXIS5_ROTATES requires AXIS4_ROTATES." #elif !defined(J_MIN_POS) || !defined(J_MAX_POS) - #error "J_MIN_POS and J_MAX_POS are required with LINEAR_AXES >= 5." + #error "J_MIN_POS and J_MAX_POS are required with NUM_AXES >= 5." #elif !defined(J_HOME_DIR) - #error "J_HOME_DIR is required with LINEAR_AXES >= 5." + #error "J_HOME_DIR is required with NUM_AXES >= 5." #elif HAS_J_ENABLE && !defined(J_ENABLE_ON) - #error "J_ENABLE_ON is required for your J driver with LINEAR_AXES >= 5." + #error "J_ENABLE_ON is required for your J driver with NUM_AXES >= 5." #endif #endif #if HAS_K_AXIS #if AXIS6_NAME == AXIS5_NAME || AXIS6_NAME == AXIS4_NAME #error "AXIS6_NAME must be unique." + #elif ENABLED(AXIS6_ROTATES) && DISABLED(AXIS5_ROTATES) + #error "AXIS6_ROTATES requires AXIS5_ROTATES." #elif !defined(K_MIN_POS) || !defined(K_MAX_POS) - #error "K_MIN_POS and K_MAX_POS are required with LINEAR_AXES >= 6." + #error "K_MIN_POS and K_MAX_POS are required with NUM_AXES >= 6." #elif !defined(K_HOME_DIR) - #error "K_HOME_DIR is required with LINEAR_AXES >= 6." + #error "K_HOME_DIR is required with NUM_AXES >= 6." #elif HAS_K_ENABLE && !defined(K_ENABLE_ON) - #error "K_ENABLE_ON is required for your K driver with LINEAR_AXES >= 6." + #error "K_ENABLE_ON is required for your K driver with NUM_AXES >= 6." + #endif +#endif +#if HAS_U_AXIS + #if AXIS7_NAME == AXIS6_NAME || AXIS7_NAME == AXIS5_NAME || AXIS7_NAME == AXIS4_NAME + #error "AXIS7_NAME must be unique." + #elif ENABLED(AXIS7_ROTATES) && DISABLED(AXIS6_ROTATES) + #error "AXIS7_ROTATES requires AXIS6_ROTATES." + #elif !defined(U_MIN_POS) || !defined(U_MAX_POS) + #error "U_MIN_POS and U_MAX_POS are required with NUM_AXES >= 7." + #elif !defined(U_HOME_DIR) + #error "U_HOME_DIR is required with NUM_AXES >= 7." + #elif HAS_U_ENABLE && !defined(U_ENABLE_ON) + #error "U_ENABLE_ON is required for your U driver with NUM_AXES >= 7." + #endif +#endif +#if HAS_V_AXIS + #if AXIS8_NAME == AXIS7_NAME || AXIS8_NAME == AXIS6_NAME || AXIS8_NAME == AXIS5_NAME || AXIS8_NAME == AXIS4_NAME + #error "AXIS8_NAME must be unique." + #elif ENABLED(AXIS8_ROTATES) && DISABLED(AXIS7_ROTATES) + #error "AXIS8_ROTATES requires AXIS7_ROTATES." + #elif !defined(V_MIN_POS) || !defined(V_MAX_POS) + #error "V_MIN_POS and V_MAX_POS are required with NUM_AXES >= 8." + #elif !defined(V_HOME_DIR) + #error "V_HOME_DIR is required with NUM_AXES >= 8." + #elif HAS_V_ENABLE && !defined(V_ENABLE_ON) + #error "V_ENABLE_ON is required for your V driver with NUM_AXES >= 8." + #endif +#endif +#if HAS_W_AXIS + #if AXIS9_NAME == AXIS8_NAME || AXIS9_NAME == AXIS7_NAME || AXIS9_NAME == AXIS6_NAME || AXIS9_NAME == AXIS5_NAME || AXIS9_NAME == AXIS4_NAME + #error "AXIS9_NAME must be unique." + #elif ENABLED(AXIS9_ROTATES) && DISABLED(AXIS8_ROTATES) + #error "AXIS9_ROTATES requires AXIS8_ROTATES." + #elif !defined(W_MIN_POS) || !defined(W_MAX_POS) + #error "W_MIN_POS and W_MAX_POS are required with NUM_AXES >= 9." + #elif !defined(W_HOME_DIR) + #error "W_HOME_DIR is required with NUM_AXES >= 9." + #elif HAS_W_ENABLE && !defined(W_ENABLE_ON) + #error "W_ENABLE_ON is required for your W driver with NUM_AXES >= 9." #endif #endif @@ -1850,49 +1909,61 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "Required setting HOMING_BUMP_DIVISOR is missing!" #else constexpr float hbm[] = HOMING_BUMP_MM, hbd[] = HOMING_BUMP_DIVISOR; - static_assert(COUNT(hbm) == LINEAR_AXES, "HOMING_BUMP_MM must have " _LINEAR_AXES_STR "elements (and no others)."); - LINEAR_AXIS_CODE( + static_assert(COUNT(hbm) == NUM_AXES, "HOMING_BUMP_MM must have " _NUM_AXES_STR "elements (and no others)."); + NUM_AXIS_CODE( static_assert(hbm[X_AXIS] >= 0, "HOMING_BUMP_MM.X must be greater than or equal to 0."), static_assert(hbm[Y_AXIS] >= 0, "HOMING_BUMP_MM.Y must be greater than or equal to 0."), static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal to 0."), static_assert(hbm[I_AXIS] >= 0, "HOMING_BUMP_MM.I must be greater than or equal to 0."), static_assert(hbm[J_AXIS] >= 0, "HOMING_BUMP_MM.J must be greater than or equal to 0."), - static_assert(hbm[K_AXIS] >= 0, "HOMING_BUMP_MM.K must be greater than or equal to 0.") + static_assert(hbm[K_AXIS] >= 0, "HOMING_BUMP_MM.K must be greater than or equal to 0."), + static_assert(hbm[U_AXIS] >= 0, "HOMING_BUMP_MM.U must be greater than or equal to 0."), + static_assert(hbm[V_AXIS] >= 0, "HOMING_BUMP_MM.V must be greater than or equal to 0."), + static_assert(hbm[W_AXIS] >= 0, "HOMING_BUMP_MM.W must be greater than or equal to 0.") ); - static_assert(COUNT(hbd) == LINEAR_AXES, "HOMING_BUMP_DIVISOR must have " _LINEAR_AXES_STR "elements (and no others)."); - LINEAR_AXIS_CODE( + static_assert(COUNT(hbd) == NUM_AXES, "HOMING_BUMP_DIVISOR must have " _NUM_AXES_STR "elements (and no others)."); + NUM_AXIS_CODE( static_assert(hbd[X_AXIS] >= 1, "HOMING_BUMP_DIVISOR.X must be greater than or equal to 1."), static_assert(hbd[Y_AXIS] >= 1, "HOMING_BUMP_DIVISOR.Y must be greater than or equal to 1."), static_assert(hbd[Z_AXIS] >= 1, "HOMING_BUMP_DIVISOR.Z must be greater than or equal to 1."), static_assert(hbd[I_AXIS] >= 1, "HOMING_BUMP_DIVISOR.I must be greater than or equal to 1."), static_assert(hbd[J_AXIS] >= 1, "HOMING_BUMP_DIVISOR.J must be greater than or equal to 1."), - static_assert(hbd[K_AXIS] >= 1, "HOMING_BUMP_DIVISOR.K must be greater than or equal to 1.") + static_assert(hbd[K_AXIS] >= 1, "HOMING_BUMP_DIVISOR.K must be greater than or equal to 1."), + static_assert(hbd[U_AXIS] >= 1, "HOMING_BUMP_DIVISOR.U must be greater than or equal to 1."), + static_assert(hbd[V_AXIS] >= 1, "HOMING_BUMP_DIVISOR.V must be greater than or equal to 1."), + static_assert(hbd[W_AXIS] >= 1, "HOMING_BUMP_DIVISOR.W must be greater than or equal to 1.") ); #endif #ifdef HOMING_BACKOFF_POST_MM constexpr float hbp[] = HOMING_BACKOFF_POST_MM; - static_assert(COUNT(hbp) == LINEAR_AXES, "HOMING_BACKOFF_POST_MM must have " _LINEAR_AXES_STR "elements (and no others)."); - LINEAR_AXIS_CODE( + static_assert(COUNT(hbp) == NUM_AXES, "HOMING_BACKOFF_POST_MM must have " _NUM_AXES_STR "elements (and no others)."); + NUM_AXIS_CODE( static_assert(hbp[X_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.X must be greater than or equal to 0."), static_assert(hbp[Y_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.Y must be greater than or equal to 0."), static_assert(hbp[Z_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.Z must be greater than or equal to 0."), static_assert(hbp[I_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.I must be greater than or equal to 0."), static_assert(hbp[J_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.J must be greater than or equal to 0."), - static_assert(hbp[K_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.K must be greater than or equal to 0.") + static_assert(hbp[K_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.K must be greater than or equal to 0."), + static_assert(hbp[U_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.U must be greater than or equal to 0."), + static_assert(hbp[V_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.V must be greater than or equal to 0."), + static_assert(hbp[W_AXIS] >= 0, "HOMING_BACKOFF_POST_MM.W must be greater than or equal to 0.") ); #endif #ifdef SENSORLESS_BACKOFF_MM constexpr float sbm[] = SENSORLESS_BACKOFF_MM; - static_assert(COUNT(sbm) == LINEAR_AXES, "SENSORLESS_BACKOFF_MM must have " _LINEAR_AXES_STR "elements (and no others)."); - LINEAR_AXIS_CODE( + static_assert(COUNT(sbm) == NUM_AXES, "SENSORLESS_BACKOFF_MM must have " _NUM_AXES_STR "elements (and no others)."); + NUM_AXIS_CODE( static_assert(sbm[X_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.X must be greater than or equal to 0."), static_assert(sbm[Y_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.Y must be greater than or equal to 0."), static_assert(sbm[Z_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.Z must be greater than or equal to 0."), static_assert(sbm[I_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.I must be greater than or equal to 0."), static_assert(sbm[J_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.J must be greater than or equal to 0."), - static_assert(sbm[K_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.K must be greater than or equal to 0.") + static_assert(sbm[K_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.K must be greater than or equal to 0."), + static_assert(sbm[U_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.U must be greater than or equal to 0."), + static_assert(sbm[V_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.V must be greater than or equal to 0."), + static_assert(sbm[W_AXIS] >= 0, "SENSORLESS_BACKOFF_MM.W must be greater than or equal to 0.") ); #endif @@ -1915,9 +1986,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS /** * Make sure DISABLE_[XYZ] compatible with selected homing options */ -#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K) +#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W) #if EITHER(HOME_AFTER_DEACTIVATE, Z_SAFE_HOMING) - #error "DISABLE_[XYZIJK] is not compatible with HOME_AFTER_DEACTIVATE or Z_SAFE_HOMING." + #error "DISABLE_[XYZIJKUVW] is not compatible with HOME_AFTER_DEACTIVATE or Z_SAFE_HOMING." #endif #endif @@ -2431,7 +2502,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #define _PLUG_UNUSED_TEST(A,P) (DISABLED(USE_##P##MIN_PLUG, USE_##P##MAX_PLUG) \ && !(ENABLED(A##_DUAL_ENDSTOPS) && WITHIN(A##2_USE_ENDSTOP, _##P##MAX_, _##P##MIN_)) \ && !(ENABLED(A##_MULTI_ENDSTOPS) && WITHIN(A##2_USE_ENDSTOP, _##P##MAX_, _##P##MIN_)) ) -#define _AXIS_PLUG_UNUSED_TEST(A) (1 LINEAR_AXIS_GANG(&& _PLUG_UNUSED_TEST(A,X), && _PLUG_UNUSED_TEST(A,Y), && _PLUG_UNUSED_TEST(A,Z), && _PLUG_UNUSED_TEST(A,I), && _PLUG_UNUSED_TEST(A,J), && _PLUG_UNUSED_TEST(A,K) ) ) +#define _AXIS_PLUG_UNUSED_TEST(A) (1 NUM_AXIS_GANG(&& _PLUG_UNUSED_TEST(A,X), && _PLUG_UNUSED_TEST(A,Y), && _PLUG_UNUSED_TEST(A,Z), \ + && _PLUG_UNUSED_TEST(A,I), && _PLUG_UNUSED_TEST(A,J), && _PLUG_UNUSED_TEST(A,K), \ + && _PLUG_UNUSED_TEST(A,U), && _PLUG_UNUSED_TEST(A,V), && _PLUG_UNUSED_TEST(A,W) ) ) // A machine with endstops must have a minimum of 3 #if HAS_ENDSTOPS @@ -2453,6 +2526,15 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if HAS_K_AXIS && _AXIS_PLUG_UNUSED_TEST(K) #error "You must enable USE_KMIN_PLUG or USE_KMAX_PLUG." #endif + #if HAS_U_AXIS && _AXIS_PLUG_UNUSED_TEST(U) + #error "You must enable USE_UMIN_PLUG or USE_UMAX_PLUG." + #endif + #if HAS_V_AXIS && _AXIS_PLUG_UNUSED_TEST(V) + #error "You must enable USE_VMIN_PLUG or USE_VMAX_PLUG." + #endif + #if HAS_W_AXIS && _AXIS_PLUG_UNUSED_TEST(W) + #error "You must enable USE_WMIN_PLUG or USE_WMAX_PLUG." + #endif // Delta and Cartesian use 3 homing endstops #if NONE(IS_SCARA, SPI_ENDSTOPS) @@ -2476,6 +2558,18 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "Enable USE_KMIN_PLUG when homing K to MIN." #elif HAS_K_AXIS && K_HOME_TO_MAX && DISABLED(USE_KMAX_PLUG) #error "Enable USE_KMAX_PLUG when homing K to MAX." + #elif HAS_U_AXIS && U_HOME_TO_MIN && DISABLED(USE_UMIN_PLUG) + #error "Enable USE_UMIN_PLUG when homing U to MIN." + #elif HAS_U_AXIS && U_HOME_TO_MAX && DISABLED(USE_UMAX_PLUG) + #error "Enable USE_UMAX_PLUG when homing U to MAX." + #elif HAS_V_AXIS && V_HOME_TO_MIN && DISABLED(USE_VMIN_PLUG) + #error "Enable USE_VMIN_PLUG when homing V to MIN." + #elif HAS_V_AXIS && V_HOME_TO_MAX && DISABLED(USE_VMAX_PLUG) + #error "Enable USE_VMAX_PLUG when homing V to MAX." + #elif HAS_W_AXIS && W_HOME_TO_MIN && DISABLED(USE_WMIN_PLUG) + #error "Enable USE_WMIN_PLUG when homing W to MIN." + #elif HAS_W_AXIS && W_HOME_TO_MAX && DISABLED(USE_WMAX_PLUG) + #error "Enable USE_WMAX_PLUG when homing W to MAX." #endif #endif @@ -2959,6 +3053,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "An SPI driven TMC on J requires J_CS_PIN." #elif INVALID_TMC_SPI(K) #error "An SPI driven TMC on K requires K_CS_PIN." +#elif INVALID_TMC_SPI(U) + #error "An SPI driven TMC on U requires U_CS_PIN." +#elif INVALID_TMC_SPI(V) + #error "An SPI driven TMC on V requires V_CS_PIN." +#elif INVALID_TMC_SPI(W) + #error "An SPI driven TMC on W requires W_CS_PIN." #endif #undef INVALID_TMC_SPI @@ -3004,6 +3104,13 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "TMC2208 or TMC2209 on J requires J_HARDWARE_SERIAL or J_SERIAL_(RX|TX)_PIN." #elif HAS_K_AXIS && INVALID_TMC_UART(K) #error "TMC2208 or TMC2209 on K requires K_HARDWARE_SERIAL or K_SERIAL_(RX|TX)_PIN." +#elif HAS_U_AXIS && INVALID_TMC_UART(U) + #error "TMC2208 or TMC2209 on U requires U_HARDWARE_SERIAL or U_SERIAL_(RX|TX)_PIN." +#elif HAS_V_AXIS && INVALID_TMC_UART(V) + #error "TMC2208 or TMC2209 on V requires V_HARDWARE_SERIAL or V_SERIAL_(RX|TX)_PIN." +#elif HAS_W_AXIS && INVALID_TMC_UART(W) + #error "TMC2208 or TMC2209 on W requires W_HARDWARE_SERIAL or W_SERIAL_(RX|TX)_PIN." + #endif #undef INVALID_TMC_UART @@ -3033,6 +3140,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS INVALID_TMC_ADDRESS(J); #elif AXIS_DRIVER_TYPE_K(TMC2209) INVALID_TMC_ADDRESS(K); +#elif AXIS_DRIVER_TYPE_U(TMC2209) + INVALID_TMC_ADDRESS(U); +#elif AXIS_DRIVER_TYPE_V(TMC2209) + INVALID_TMC_ADDRESS(V); +#elif AXIS_DRIVER_TYPE_W(TMC2209) + INVALID_TMC_ADDRESS(W); #elif AXIS_DRIVER_TYPE_E0(TMC2209) INVALID_TMC_ADDRESS(E0); #elif AXIS_DRIVER_TYPE_E1(TMC2209) @@ -3094,6 +3207,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS INVALID_TMC_MS(J) #elif HAS_K_AXIS && !TMC_MICROSTEP_IS_VALID(K) INVALID_TMC_MS(K) +#elif HAS_U_AXIS && !TMC_MICROSTEP_IS_VALID(U) + INVALID_TMC_MS(U) +#elif HAS_V_AXIS && !TMC_MICROSTEP_IS_VALID(V) + INVALID_TMC_MS(V) +#elif HAS_W_AXIS && !TMC_MICROSTEP_IS_VALID(W) + INVALID_TMC_MS(W) #endif #undef INVALID_TMC_MS #undef TMC_MICROSTEP_IS_VALID @@ -3123,6 +3242,15 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if HAS_K_AXIS #define K_ENDSTOP_INVERTING !AXIS_DRIVER_TYPE(K,TMC2209) #endif + #if HAS_U_AXIS + #define U_ENDSTOP_INVERTING !AXIS_DRIVER_TYPE(U,TMC2209) + #endif + #if HAS_V_AXIS + #define V_ENDSTOP_INVERTING !AXIS_DRIVER_TYPE(V,TMC2209) + #endif + #if HAS_W_AXIS + #define W_ENDSTOP_INVERTING !AXIS_DRIVER_TYPE(W,TMC2209) + #endif #if NONE(SPI_ENDSTOPS, ONBOARD_ENDSTOPPULLUPS, ENDSTOPPULLUPS) #if X_SENSORLESS && X_HOME_TO_MIN && DISABLED(ENDSTOPPULLUP_XMIN) @@ -3149,6 +3277,19 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_KMIN (or ENDSTOPPULLUPS) when homing to K_MIN." #elif ALL(HAS_K_AXIS, K_SENSORLESS, K_HOME_TO_MAX) && DISABLED(ENDSTOPPULLUP_KMAX) #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_KMAX (or ENDSTOPPULLUPS) when homing to K_MAX." + #elif HAS_U_AXIS && U_SENSORLESS && U_HOME_TO_MIN && DISABLED(ENDSTOPPULLUP_UMIN) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_UMIN (or ENDSTOPPULLUPS) when homing to U_MIN." + #elif HAS_U_AXIS && U_SENSORLESS && U_HOME_TO_MAX && DISABLED(ENDSTOPPULLUP_UMAX) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_UMAX (or ENDSTOPPULLUPS) when homing to U_MAX." + #elif HAS_V_AXIS && V_SENSORLESS && V_HOME_TO_MIN && DISABLED(ENDSTOPPULLUP_VMIN) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_VMIN (or ENDSTOPPULLUPS) when homing to V_MIN." + #elif HAS_V_AXIS && V_SENSORLESS && V_HOME_TO_MAX && DISABLED(ENDSTOPPULLUP_VMAX) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_VMAX (or ENDSTOPPULLUPS) when homing to V_MAX." + #elif HAS_W_AXIS && W_SENSORLESS && W_HOME_TO_MIN && DISABLED(ENDSTOPPULLUP_WMIN) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_WMIN (or ENDSTOPPULLUPS) when homing to W_MIN." + #elif HAS_W_AXIS && W_SENSORLESS && W_HOME_TO_MAX && DISABLED(ENDSTOPPULLUP_WMAX) + #error "SENSORLESS_HOMING requires ENDSTOPPULLUP_WMAX (or ENDSTOPPULLUPS) when homing to W_MAX." + #endif #endif @@ -3229,6 +3370,42 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #else #error "SENSORLESS_HOMING requires K_MAX_ENDSTOP_INVERTING = false when homing TMC2209 to K_MAX." #endif + #elif ALL(HAS_U_AXIS, U_SENSORLESS, U_HOME_TO_MIN) && U_MIN_ENDSTOP_INVERTING != U_ENDSTOP_INVERTING + #if U_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires U_MIN_ENDSTOP_INVERTING = true when homing to U_MIN." + #else + #error "SENSORLESS_HOMING requires U_MIN_ENDSTOP_INVERTING = false when homing TMC2209 to U_MIN." + #endif + #elif ALL(HAS_U_AXIS, U_SENSORLESS, U_HOME_TO_MAX) && U_MAX_ENDSTOP_INVERTING != U_ENDSTOP_INVERTING + #if U_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires U_MAX_ENDSTOP_INVERTING = true when homing to U_MAX." + #else + #error "SENSORLESS_HOMING requires U_MAX_ENDSTOP_INVERTING = false when homing TMC2209 to U_MAX." + #endif + #elif ALL(HAS_V_AXIS, V_SENSORLESS, V_HOME_TO_MIN) && V_MIN_ENDSTOP_INVERTING != V_ENDSTOP_INVERTING + #if V_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires V_MIN_ENDSTOP_INVERTING = true when homing to V_MIN." + #else + #error "SENSORLESS_HOMING requires V_MIN_ENDSTOP_INVERTING = false when homing TMC2209 to V_MIN." + #endif + #elif ALL(HAS_V_AXIS, V_SENSORLESS, V_HOME_TO_MAX) && V_MAX_ENDSTOP_INVERTING != V_ENDSTOP_INVERTING + #if V_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires V_MAX_ENDSTOP_INVERTING = true when homing to V_MAX." + #else + #error "SENSORLESS_HOMING requires V_MAX_ENDSTOP_INVERTING = false when homing TMC2209 to V_MAX." + #endif + #elif ALL(HAS_W_AXIS, W_SENSORLESS, W_HOME_TO_MIN) && W_MIN_ENDSTOP_INVERTING != W_ENDSTOP_INVERTING + #if W_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires W_MIN_ENDSTOP_INVERTING = true when homing to W_MIN." + #else + #error "SENSORLESS_HOMING requires W_MIN_ENDSTOP_INVERTING = false when homing TMC2209 to W_MIN." + #endif + #elif ALL(HAS_W_AXIS, W_SENSORLESS, W_HOME_TO_MAX0) && W_MAX_ENDSTOP_INVERTING != W_ENDSTOP_INVERTING + #if W_ENDSTOP_INVERTING + #error "SENSORLESS_HOMING requires W_MAX_ENDSTOP_INVERTING = true when homing to W_MAX." + #else + #error "SENSORLESS_HOMING requires W_MAX_ENDSTOP_INVERTING = false when homing TMC2209 to W_MAX." + #endif #endif #endif @@ -3246,6 +3423,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #undef I_ENDSTOP_INVERTING #undef J_ENDSTOP_INVERTING #undef K_ENDSTOP_INVERTING + #undef U_ENDSTOP_INVERTING + #undef V_ENDSTOP_INVERTING + #undef W_ENDSTOP_INVERTING #endif // Sensorless probing requirements @@ -3314,6 +3494,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #define CS_COMPARE J_CS_PIN #elif IN_CHAIN(K) #define CS_COMPARE K_CS_PIN + #elif IN_CHAIN(U) + #define CS_COMPARE U_CS_PIN + #elif IN_CHAIN(V) + #define CS_COMPARE V_CS_PIN + #elif IN_CHAIN(W) + #define CS_COMPARE W_CS_PIN #elif IN_CHAIN(E0) #define CS_COMPARE E0_CS_PIN #elif IN_CHAIN(E1) @@ -3334,6 +3520,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #define BAD_CS_PIN(A) (IN_CHAIN(A) && A##_CS_PIN != CS_COMPARE) #if BAD_CS_PIN(X ) || BAD_CS_PIN(Y ) || BAD_CS_PIN(Z ) || BAD_CS_PIN(X2) || BAD_CS_PIN(Y2) || BAD_CS_PIN(Z2) || BAD_CS_PIN(Z3) || BAD_CS_PIN(Z4) \ || BAD_CS_PIN(I) || BAD_CS_PIN(J) || BAD_CS_PIN(K) \ + || BAD_CS_PIN(U) || BAD_CS_PIN(V) || BAD_CS_PIN(W) \ || BAD_CS_PIN(E0) || BAD_CS_PIN(E1) || BAD_CS_PIN(E2) || BAD_CS_PIN(E3) || BAD_CS_PIN(E4) || BAD_CS_PIN(E5) || BAD_CS_PIN(E6) || BAD_CS_PIN(E7) #error "All chained TMC drivers must use the same CS pin." #endif @@ -3347,8 +3534,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS /** * L64XX requirement */ -#if HAS_L64XX && HAS_I_AXIS - #error "L64XX requires LINEAR_AXES <= 3. Homing with L64XX is not yet implemented for LINEAR_AXES > 3." +#if HAS_L64XX && NUM_AXES > 3 + #error "L64XX requires NUM_AXES <= 3. Homing with L64XX is not yet implemented for NUM_AXES > 3." #endif /** @@ -3372,7 +3559,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if HAS_MULTI_EXTRUDER #define _EXTRA_NOTE " (Did you forget to enable DISTINCT_E_FACTORS?)" #else - #define _EXTRA_NOTE " (Should be " STRINGIFY(LINEAR_AXES) "+" STRINGIFY(E_STEPPERS) ")" + #define _EXTRA_NOTE " (Should be " STRINGIFY(NUM_AXES) "+" STRINGIFY(E_STEPPERS) ")" #endif constexpr float sanity_arr_1[] = DEFAULT_AXIS_STEPS_PER_UNIT; @@ -3391,7 +3578,7 @@ static_assert(COUNT(sanity_arr_3) <= DISTINCT_AXES, "DEFAULT_MAX_ACCELERATION ha static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."); constexpr float sanity_arr_4[] = HOMING_FEEDRATE_MM_M; -static_assert(COUNT(sanity_arr_4) == LINEAR_AXES, "HOMING_FEEDRATE_MM_M requires " _LINEAR_AXES_STR "elements (and no others)."); +static_assert(COUNT(sanity_arr_4) == NUM_AXES, "HOMING_FEEDRATE_MM_M requires " _NUM_AXES_STR "elements (and no others)."); static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); #ifdef MAX_ACCEL_EDIT_VALUES @@ -3831,6 +4018,15 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); #if _BAD_DRIVER(K) #error "K_DRIVER_TYPE is not recognized." #endif +#if _BAD_DRIVER(U) + #error "U_DRIVER_TYPE is not recognized." +#endif +#if _BAD_DRIVER(V) + #error "V_DRIVER_TYPE is not recognized." +#endif +#if _BAD_DRIVER(W) + #error "W_DRIVER_TYPE is not recognized." +#endif #if _BAD_DRIVER(X2) #error "X2_DRIVER_TYPE is not recognized." #endif @@ -3903,7 +4099,7 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); // Misc. Cleanup #undef _TEST_PWM -#undef _LINEAR_AXES_STR +#undef _NUM_AXES_STR #undef _LOGICAL_AXES_STR // JTAG support in the HAL diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index 140d9ba5c215..aadb91dadfa3 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -52,7 +52,7 @@ * to alert users to major changes. */ -#define MARLIN_HEX_VERSION 02000903 +#define MARLIN_HEX_VERSION 02010000 #ifndef REQUIRED_CONFIGURATION_H_VERSION #define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION #endif diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 97e8e76b38d8..96f8dc7d54b2 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -532,6 +532,163 @@ #endif #endif + #if AUTO_ASSIGNED_U_STEPPER + #warning "Note: Auto-assigned U STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_CS + #warning "Note: Auto-assigned U_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS1 + #warning "Note: Auto-assigned U_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS2 + #warning "Note: Auto-assigned U_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS3 + #warning "Note: Auto-assigned U_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_DIAG + #if U_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif K_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if AUTO_ASSIGNED_V_STEPPER + #warning "Note: Auto-assigned V STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_CS + #warning "Note: Auto-assigned V_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS1 + #warning "Note: Auto-assigned V_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS2 + #warning "Note: Auto-assigned V_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS3 + #warning "Note: Auto-assigned V_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_DIAG + #if V_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if AUTO_ASSIGNED_W_STEPPER + #warning "Note: Auto-assigned W STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_CS + #warning "Note: Auto-assigned W_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS1 + #warning "Note: Auto-assigned W_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS2 + #warning "Note: Auto-assigned W_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS3 + #warning "Note: Auto-assigned W_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_DIAG + #if W_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if ENABLED(CHAMBER_FAN) && !defined(CHAMBER_FAN_INDEX) #warning "Note: Auto-assigned CHAMBER_FAN_INDEX to the first free FAN pin. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" #endif diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp index 8d5703876564..961b29ca2236 100644 --- a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp +++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp @@ -286,7 +286,7 @@ void DGUSTxHandler::TempMax(DGUS_VP &vp) { } void DGUSTxHandler::StepperStatus(DGUS_VP &vp) { - const bool motor_on = stepper.axis_enabled.bits & (_BV(LINEAR_AXES) - 1); + const bool motor_on = stepper.axis_enabled.bits & (_BV(NUM_AXES) - 1); dgus_display.Write((uint16_t)vp.addr, Swap16(uint16_t(motor_on ? DGUS_Data::Status::ENABLED : DGUS_Data::Status::DISABLED))); } diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 0dad675cb75c..1da46d7e47a5 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -420,6 +420,15 @@ namespace ExtUI { #if AXIS_IS_TMC(K) case K: return stepperK.getMilliamps(); #endif + #if AXIS_IS_TMC(U) + case U: return stepperU.getMilliamps(); + #endif + #if AXIS_IS_TMC(V) + case V: return stepperV.getMilliamps(); + #endif + #if AXIS_IS_TMC(W) + case W: return stepperW.getMilliamps(); + #endif #if AXIS_IS_TMC(X2) case X2: return stepperX2.getMilliamps(); #endif @@ -489,6 +498,15 @@ namespace ExtUI { #if AXIS_IS_TMC(K) case K: stepperK.rms_current(constrain(mA, 400, 1500)); break; #endif + #if AXIS_IS_TMC(U) + case U: stepperU.rms_current(constrain(mA, 400, 1500)); break; + #endif + #if AXIS_IS_TMC(V) + case V: stepperV.rms_current(constrain(mA, 400, 1500)); break; + #endif + #if AXIS_IS_TMC(W) + case W: stepperW.rms_current(constrain(mA, 400, 1500)); break; + #endif #if AXIS_IS_TMC(X2) case X2: stepperX2.rms_current(constrain(mA, 400, 1500)); break; #endif @@ -546,6 +564,9 @@ namespace ExtUI { OPTCODE(I_SENSORLESS, case I: return stepperI.homing_threshold()) OPTCODE(J_SENSORLESS, case J: return stepperJ.homing_threshold()) OPTCODE(K_SENSORLESS, case K: return stepperK.homing_threshold()) + OPTCODE(U_SENSORLESS, case U: return stepperU.homing_threshold()) + OPTCODE(V_SENSORLESS, case V: return stepperV.homing_threshold()) + OPTCODE(W_SENSORLESS, case W: return stepperW.homing_threshold()) OPTCODE(X2_SENSORLESS, case X2: return stepperX2.homing_threshold()) OPTCODE(Y2_SENSORLESS, case Y2: return stepperY2.homing_threshold()) OPTCODE(Z2_SENSORLESS, case Z2: return stepperZ2.homing_threshold()) @@ -575,6 +596,15 @@ namespace ExtUI { #if K_SENSORLESS case K: stepperK.homing_threshold(value); break; #endif + #if U_SENSORLESS + case U: stepperU.homing_threshold(value); break; + #endif + #if V_SENSORLESS + case V: stepperV.homing_threshold(value); break; + #endif + #if W_SENSORLESS + case W: stepperW.homing_threshold(value); break; + #endif #if X2_SENSORLESS case X2: stepperX2.homing_threshold(value); break; #endif diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h index 84b2ed8c6d70..84555187677a 100644 --- a/Marlin/src/lcd/extui/ui_api.h +++ b/Marlin/src/lcd/extui/ui_api.h @@ -57,7 +57,7 @@ namespace ExtUI { static constexpr size_t eeprom_data_size = 48; - enum axis_t : uint8_t { X, Y, Z, I, J, K, X2, Y2, Z2, Z3, Z4 }; + enum axis_t : uint8_t { X, Y, Z, I, J, K, U, V, W, X2, Y2, Z2, Z3, Z4 }; enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5, E6, E7 }; enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED, CHAMBER, COOLER }; enum fan_t : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5, FAN6, FAN7 }; diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 43bbd90210fd..313098a9f60d 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -103,6 +103,9 @@ namespace Language_en { LSTR MSG_HOME_OFFSET_I = _UxGT("Home Offset ") STR_I; LSTR MSG_HOME_OFFSET_J = _UxGT("Home Offset ") STR_J; LSTR MSG_HOME_OFFSET_K = _UxGT("Home Offset ") STR_K; + LSTR MSG_HOME_OFFSET_U = _UxGT("Home Offset ") STR_U; + LSTR MSG_HOME_OFFSET_V = _UxGT("Home Offset ") STR_V; + LSTR MSG_HOME_OFFSET_W = _UxGT("Home Offset ") STR_W; LSTR MSG_HOME_OFFSETS_APPLIED = _UxGT("Offsets Applied"); LSTR MSG_SET_ORIGIN = _UxGT("Set Origin"); LSTR MSG_TRAMMING_WIZARD = _UxGT("Tramming Wizard"); @@ -288,6 +291,9 @@ namespace Language_en { LSTR MSG_MOVE_I = _UxGT("Move ") STR_I; LSTR MSG_MOVE_J = _UxGT("Move ") STR_J; LSTR MSG_MOVE_K = _UxGT("Move ") STR_K; + LSTR MSG_MOVE_U = _UxGT("Move ") STR_U; + LSTR MSG_MOVE_V = _UxGT("Move ") STR_V; + LSTR MSG_MOVE_W = _UxGT("Move ") STR_W; LSTR MSG_MOVE_E = _UxGT("Move Extruder"); LSTR MSG_MOVE_EN = _UxGT("Move E*"); LSTR MSG_HOTEND_TOO_COLD = _UxGT("Hotend too cold"); @@ -354,6 +360,9 @@ namespace Language_en { LSTR MSG_VI_JERK = _UxGT("Max ") STR_I _UxGT(" Jerk"); LSTR MSG_VJ_JERK = _UxGT("Max ") STR_J _UxGT(" Jerk"); LSTR MSG_VK_JERK = _UxGT("Max ") STR_K _UxGT(" Jerk"); + LSTR MSG_VU_JERK = _UxGT("Max ") STR_U _UxGT(" Jerk"); + LSTR MSG_VV_JERK = _UxGT("Max ") STR_V _UxGT(" Jerk"); + LSTR MSG_VW_JERK = _UxGT("Max ") STR_W _UxGT(" Jerk"); LSTR MSG_VE_JERK = _UxGT("Max E Jerk"); LSTR MSG_JUNCTION_DEVIATION = _UxGT("Junction Dev"); LSTR MSG_VELOCITY = _UxGT("Velocity"); @@ -363,6 +372,9 @@ namespace Language_en { LSTR MSG_VMAX_I = _UxGT("Max ") STR_I _UxGT(" Vel"); LSTR MSG_VMAX_J = _UxGT("Max ") STR_J _UxGT(" Vel"); LSTR MSG_VMAX_K = _UxGT("Max ") STR_K _UxGT(" Vel"); + LSTR MSG_VMAX_U = _UxGT("Max ") STR_U _UxGT(" Vel"); + LSTR MSG_VMAX_V = _UxGT("Max ") STR_V _UxGT(" Vel"); + LSTR MSG_VMAX_W = _UxGT("Max ") STR_W _UxGT(" Vel"); LSTR MSG_VMAX_E = _UxGT("Max ") STR_E _UxGT(" Vel"); LSTR MSG_VMAX_EN = _UxGT("Max * Vel"); LSTR MSG_VMIN = _UxGT("Min Velocity"); @@ -374,6 +386,9 @@ namespace Language_en { LSTR MSG_AMAX_I = _UxGT("Max ") STR_I _UxGT(" Accel"); LSTR MSG_AMAX_J = _UxGT("Max ") STR_J _UxGT(" Accel"); LSTR MSG_AMAX_K = _UxGT("Max ") STR_K _UxGT(" Accel"); + LSTR MSG_AMAX_U = _UxGT("Max ") STR_U _UxGT(" Accel"); + LSTR MSG_AMAX_V = _UxGT("Max ") STR_V _UxGT(" Accel"); + LSTR MSG_AMAX_W = _UxGT("Max ") STR_W _UxGT(" Accel"); LSTR MSG_AMAX_E = _UxGT("Max ") STR_E _UxGT(" Accel"); LSTR MSG_AMAX_EN = _UxGT("Max * Accel"); LSTR MSG_A_RETRACT = _UxGT("Retract Accel"); @@ -387,6 +402,9 @@ namespace Language_en { LSTR MSG_I_STEPS = STR_I _UxGT(" Steps/mm"); LSTR MSG_J_STEPS = STR_J _UxGT(" Steps/mm"); LSTR MSG_K_STEPS = STR_K _UxGT(" Steps/mm"); + LSTR MSG_U_STEPS = STR_U _UxGT(" Steps/mm"); + LSTR MSG_V_STEPS = STR_V _UxGT(" Steps/mm"); + LSTR MSG_W_STEPS = STR_W _UxGT(" Steps/mm"); LSTR MSG_E_STEPS = _UxGT("E steps/mm"); LSTR MSG_EN_STEPS = _UxGT("* Steps/mm"); LSTR MSG_TEMPERATURE = _UxGT("Temperature"); @@ -540,6 +558,9 @@ namespace Language_en { LSTR MSG_BABYSTEP_I = _UxGT("Babystep ") STR_I; LSTR MSG_BABYSTEP_J = _UxGT("Babystep ") STR_J; LSTR MSG_BABYSTEP_K = _UxGT("Babystep ") STR_K; + LSTR MSG_BABYSTEP_U = _UxGT("Babystep ") STR_U; + LSTR MSG_BABYSTEP_V = _UxGT("Babystep ") STR_V; + LSTR MSG_BABYSTEP_W = _UxGT("Babystep ") STR_W; LSTR MSG_BABYSTEP_TOTAL = _UxGT("Total"); LSTR MSG_ENDSTOP_ABORT = _UxGT("Endstop Abort"); LSTR MSG_HEATING_FAILED_LCD = _UxGT("Heating Failed"); @@ -639,6 +660,9 @@ namespace Language_en { LSTR MSG_DAC_PERCENT_I = STR_I _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_J = STR_J _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_K = STR_K _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_U = STR_U _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_V = STR_V _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_W = STR_W _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_E = _UxGT("E Driver %"); LSTR MSG_ERROR_TMC = _UxGT("TMC CONNECTION ERROR"); LSTR MSG_DAC_EEPROM_WRITE = _UxGT("DAC EEPROM Write"); @@ -814,6 +838,9 @@ namespace Language_en { LSTR MSG_BACKLASH_I = STR_I; LSTR MSG_BACKLASH_J = STR_J; LSTR MSG_BACKLASH_K = STR_K; + LSTR MSG_BACKLASH_U = STR_U; + LSTR MSG_BACKLASH_V = STR_V; + LSTR MSG_BACKLASH_W = STR_W; } #if FAN_COUNT == 1 diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index eb979a43195f..80b8f5b1d2eb 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -68,7 +68,7 @@ void menu_backlash(); START_MENU(); BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); }) - LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(A), EDIT_DAC_PERCENT(B), EDIT_DAC_PERCENT(C), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K)); + LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(A), EDIT_DAC_PERCENT(B), EDIT_DAC_PERCENT(C), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K), EDIT_DAC_PERCENT(U), EDIT_DAC_PERCENT(V), EDIT_DAC_PERCENT(W)); ACTION_ITEM(MSG_DAC_EEPROM_WRITE, stepper_dac.commit_eeprom); END_MENU(); } @@ -356,7 +356,7 @@ void menu_backlash(); #elif ENABLED(LIMITED_MAX_FR_EDITING) DEFAULT_MAX_FEEDRATE #else - LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999, 9999, 9999, 9999) + LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999) #endif ; #if ENABLED(LIMITED_MAX_FR_EDITING) && !defined(MAX_FEEDRATE_EDIT_VALUES) @@ -369,7 +369,7 @@ void menu_backlash(); BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)]) - LINEAR_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K)); + NUM_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K), EDIT_VMAX(U), EDIT_VMAX(V), EDIT_VMAX(W)); #if E_STEPPERS EDIT_ITEM_FAST(float5, MSG_VMAX_E, &planner.settings.max_feedrate_mm_s[E_AXIS_N(active_extruder)], 1, max_fr_edit_scaled.e); @@ -399,7 +399,7 @@ void menu_backlash(); #elif ENABLED(LIMITED_MAX_ACCEL_EDITING) DEFAULT_MAX_ACCELERATION #else - LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000, 99000, 99000, 99000) + LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000) #endif ; #if ENABLED(LIMITED_MAX_ACCEL_EDITING) && !defined(MAX_ACCEL_EDIT_VALUES) @@ -423,9 +423,10 @@ void menu_backlash(); EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel); #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); }) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10), - EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10) + EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10), + EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10) ); #if ENABLED(DISTINCT_E_FACTORS) @@ -468,9 +469,10 @@ void menu_backlash(); #elif ENABLED(LIMITED_JERK_EDITING) { LOGICAL_AXIS_LIST((DEFAULT_EJERK) * 2, (DEFAULT_XJERK) * 2, (DEFAULT_YJERK) * 2, (DEFAULT_ZJERK) * 2, - (DEFAULT_IJERK) * 2, (DEFAULT_JJERK) * 2, (DEFAULT_KJERK) * 2) } + (DEFAULT_IJERK) * 2, (DEFAULT_JJERK) * 2, (DEFAULT_KJERK) * 2, + (DEFAULT_UJERK) * 2, (DEFAULT_VJERK) * 2, (DEFAULT_WJERK) * 2) } #else - { LOGICAL_AXIS_LIST(990, 990, 990, 990, 990, 990, 990) } + { LOGICAL_AXIS_LIST(990, 990, 990, 990, 990, 990, 990, 990, 990, 990) } #endif ; #define EDIT_JERK(N) EDIT_ITEM_FAST(float3, MSG_V##N##_JERK, &planner.max_jerk[_AXIS(N)], 1, max_jerk_edit[_AXIS(N)]) @@ -479,9 +481,10 @@ void menu_backlash(); #else #define EDIT_JERK_C() EDIT_ITEM_FAST(float52sign, MSG_VC_JERK, &planner.max_jerk.c, 0.1f, max_jerk_edit.c) #endif - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_JERK(A), EDIT_JERK(B), EDIT_JERK_C(), - EDIT_JERK(I), EDIT_JERK(J), EDIT_JERK(K) + EDIT_JERK(I), EDIT_JERK(J), EDIT_JERK(K), + EDIT_JERK(U), EDIT_JERK(V), EDIT_JERK(W) ); #if HAS_EXTRUDERS @@ -524,9 +527,10 @@ void menu_advanced_steps_per_mm() { BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float61, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); }) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_QSTEPS(A), EDIT_QSTEPS(B), EDIT_QSTEPS(C), - EDIT_QSTEPS(I), EDIT_QSTEPS(J), EDIT_QSTEPS(K) + EDIT_QSTEPS(I), EDIT_QSTEPS(J), EDIT_QSTEPS(K), + EDIT_QSTEPS(U), EDIT_QSTEPS(V), EDIT_QSTEPS(W) ); #if ENABLED(DISTINCT_E_FACTORS) diff --git a/Marlin/src/lcd/menu/menu_backlash.cpp b/Marlin/src/lcd/menu/menu_backlash.cpp index faed8cf77763..07f3c9d7046b 100644 --- a/Marlin/src/lcd/menu/menu_backlash.cpp +++ b/Marlin/src/lcd/menu/menu_backlash.cpp @@ -66,6 +66,15 @@ void menu_backlash() { #if HAS_K_AXIS && _CAN_CALI(K) EDIT_BACKLASH_DISTANCE(K); #endif + #if HAS_U_AXIS && _CAN_CALI(U) + EDIT_BACKLASH_DISTANCE(U); + #endif + #if HAS_V_AXIS && _CAN_CALI(V) + EDIT_BACKLASH_DISTANCE(V); + #endif + #if HAS_W_AXIS && _CAN_CALI(W) + EDIT_BACKLASH_DISTANCE(W); + #endif #ifdef BACKLASH_SMOOTHING_MM editable.decimal = backlash.get_smoothing_mm(); diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 0a446b1349e3..baed081036a5 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -106,6 +106,15 @@ void lcd_move_x() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_X), X_AXIS); } #if HAS_K_AXIS void lcd_move_k() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_K), K_AXIS); } #endif +#if HAS_U_AXIS + void lcd_move_u() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_U), U_AXIS); } +#endif +#if HAS_V_AXIS + void lcd_move_v() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_V), V_AXIS); } +#endif +#if HAS_W_AXIS + void lcd_move_w() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_W), W_AXIS); } +#endif #if E_MANUAL @@ -263,6 +272,15 @@ void menu_move() { #if HAS_K_AXIS SUBMENU(MSG_MOVE_K, []{ _menu_move_distance(K_AXIS, lcd_move_k); }); #endif + #if HAS_U_AXIS + SUBMENU(MSG_MOVE_U, []{ _menu_move_distance(U_AXIS, lcd_move_u); }); + #endif + #if HAS_V_AXIS + SUBMENU(MSG_MOVE_V, []{ _menu_move_distance(V_AXIS, lcd_move_v); }); + #endif + #if HAS_W_AXIS + SUBMENU(MSG_MOVE_W, []{ _menu_move_distance(W_AXIS, lcd_move_w); }); + #endif } else GCODES_ITEM(MSG_AUTO_HOME, G28_STR); @@ -354,6 +372,15 @@ void menu_move() { #if HAS_K_AXIS GCODES_ITEM_N(K_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_K)); #endif + #if HAS_U_AXIS + GCODES_ITEM_N(U_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_U)); + #endif + #if HAS_V_AXIS + GCODES_ITEM_N(V_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_V)); + #endif + #if HAS_W_AXIS + GCODES_ITEM_N(W_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_W)); + #endif END_MENU(); } @@ -407,6 +434,15 @@ void menu_motion() { #if HAS_K_AXIS GCODES_ITEM_N(K_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_K)); #endif + #if HAS_U_AXIS + GCODES_ITEM_N(U_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_U)); + #endif + #if HAS_V_AXIS + GCODES_ITEM_N(V_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_V)); + #endif + #if HAS_W_AXIS + GCODES_ITEM_N(W_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_W)); + #endif #endif #endif diff --git a/Marlin/src/lcd/menu/menu_tmc.cpp b/Marlin/src/lcd/menu/menu_tmc.cpp index 7e206e8d7990..995bc3b195ed 100644 --- a/Marlin/src/lcd/menu/menu_tmc.cpp +++ b/Marlin/src/lcd/menu/menu_tmc.cpp @@ -134,6 +134,9 @@ void menu_tmc_current() { TERN_( I_SENSORLESS, TMC_EDIT_STORED_SGT(I)); TERN_( J_SENSORLESS, TMC_EDIT_STORED_SGT(J)); TERN_( K_SENSORLESS, TMC_EDIT_STORED_SGT(K)); + TERN_( U_SENSORLESS, TMC_EDIT_STORED_SGT(U)); + TERN_( V_SENSORLESS, TMC_EDIT_STORED_SGT(V)); + TERN_( W_SENSORLESS, TMC_EDIT_STORED_SGT(W)); END_MENU(); } diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp index a8c2695630d6..0aa2a85439c7 100644 --- a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp +++ b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp @@ -37,7 +37,7 @@ L64XX_Marlin L64xxManager; #include "../../module/planner.h" #include "../../HAL/shared/Delay.h" -static const char LINEAR_AXIS_LIST( +static const char NUM_AXIS_LIST( str_X[] PROGMEM = "X ", str_Y[] PROGMEM = "Y ", str_Z[] PROGMEM = "Z ", str_I[] PROGMEM = STR_I " ", str_J[] PROGMEM = STR_J " ", str_K[] PROGMEM = STR_K " " ), @@ -53,7 +53,7 @@ static const char LINEAR_AXIS_LIST( #define _EN_ITEM(N) , str_E##N PGM_P const L64XX_Marlin::index_to_axis[] PROGMEM = { - LINEAR_AXIS_LIST(str_X, str_Y, str_Z, str_I, str_J, str_K), + NUM_AXIS_LIST(str_X, str_Y, str_Z, str_I, str_J, str_K), str_X2, str_Y2, str_Z2, str_Z3, str_Z4 REPEAT(E_STEPPERS, _EN_ITEM) }; @@ -68,7 +68,7 @@ uint8_t L64XX_Marlin::dir_commands[MAX_L64XX]; // array to hold direction comma #define _EN_ITEM(N) , INVERT_E##N##_DIR const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = { - LINEAR_AXIS_LIST(INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR, INVERT_I_DIR, INVERT_J_DIR, INVERT_K_DIR) + NUM_AXIS_LIST(INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR, INVERT_I_DIR, INVERT_J_DIR, INVERT_K_DIR) , (INVERT_X_DIR) ^ BOTH(X_DUAL_STEPPER_DRIVERS, INVERT_X2_VS_X_DIR) // X2 , (INVERT_Y_DIR) ^ BOTH(Y_DUAL_STEPPER_DRIVERS, INVERT_Y2_VS_Y_DIR) // Y2 , (INVERT_Z_DIR) ^ ENABLED(INVERT_Z2_VS_Z_DIR) // Z2 diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.h b/Marlin/src/libs/L64XX/L64XX_Marlin.h index de7c0d605740..d00b5c16cddd 100644 --- a/Marlin/src/libs/L64XX/L64XX_Marlin.h +++ b/Marlin/src/libs/L64XX/L64XX_Marlin.h @@ -36,7 +36,7 @@ #define HAS_L64XX_EXTRUDER (AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7)) #define _EN_ITEM(N) , E##N -enum L64XX_axis_t : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX }; +enum L64XX_axis_t : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX }; #undef _EN_ITEM class L64XX_Marlin : public L64XXHelper { diff --git a/Marlin/src/module/delta.cpp b/Marlin/src/module/delta.cpp index cd40175da4d2..39eb15f896da 100644 --- a/Marlin/src/module/delta.cpp +++ b/Marlin/src/module/delta.cpp @@ -233,6 +233,9 @@ void home_delta() { TERN_(I_SENSORLESS, sensorless_t stealth_states_i = start_sensorless_homing_per_axis(I_AXIS)); TERN_(J_SENSORLESS, sensorless_t stealth_states_j = start_sensorless_homing_per_axis(J_AXIS)); TERN_(K_SENSORLESS, sensorless_t stealth_states_k = start_sensorless_homing_per_axis(K_AXIS)); + TERN_(U_SENSORLESS, sensorless_t stealth_states_u = start_sensorless_homing_per_axis(U_AXIS)); + TERN_(V_SENSORLESS, sensorless_t stealth_states_v = start_sensorless_homing_per_axis(V_AXIS)); + TERN_(W_SENSORLESS, sensorless_t stealth_states_w = start_sensorless_homing_per_axis(W_AXIS)); #endif // Move all carriages together linearly until an endstop is hit. @@ -249,6 +252,9 @@ void home_delta() { TERN_(I_SENSORLESS, end_sensorless_homing_per_axis(I_AXIS, stealth_states_i)); TERN_(J_SENSORLESS, end_sensorless_homing_per_axis(J_AXIS, stealth_states_j)); TERN_(K_SENSORLESS, end_sensorless_homing_per_axis(K_AXIS, stealth_states_k)); + TERN_(U_SENSORLESS, end_sensorless_homing_per_axis(U_AXIS, stealth_states_u)); + TERN_(V_SENSORLESS, end_sensorless_homing_per_axis(V_AXIS, stealth_states_v)); + TERN_(W_SENSORLESS, end_sensorless_homing_per_axis(W_AXIS, stealth_states_w)); #endif endstops.validate_homing_move(); diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index 3dd6d8aeb685..7381e98b01b2 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -319,6 +319,66 @@ void Endstops::init() { #endif #endif + #if HAS_U_MIN + #if ENABLED(ENDSTOPPULLUP_UMIN) + SET_INPUT_PULLUP(U_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_UMIN) + SET_INPUT_PULLDOWN(U_MIN_PIN); + #else + SET_INPUT(U_MIN_PIN); + #endif + #endif + + #if HAS_U_MAX + #if ENABLED(ENDSTOPPULLUP_UMAX) + SET_INPUT_PULLUP(U_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_UMIN) + SET_INPUT_PULLDOWN(U_MAX_PIN); + #else + SET_INPUT(U_MAX_PIN); + #endif + #endif + + #if HAS_V_MIN + #if ENABLED(ENDSTOPPULLUP_VMIN) + SET_INPUT_PULLUP(V_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_VMIN) + SET_INPUT_PULLDOWN(V_MIN_PIN); + #else + SET_INPUT(V_MIN_PIN); + #endif + #endif + + #if HAS_V_MAX + #if ENABLED(ENDSTOPPULLUP_VMAX) + SET_INPUT_PULLUP(V_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_VMIN) + SET_INPUT_PULLDOWN(V_MAX_PIN); + #else + SET_INPUT(V_MAX_PIN); + #endif + #endif + + #if HAS_W_MIN + #if ENABLED(ENDSTOPPULLUP_WMIN) + SET_INPUT_PULLUP(W_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_WMIN) + SET_INPUT_PULLDOWN(W_MIN_PIN); + #else + SET_INPUT(W_MIN_PIN); + #endif + #endif + + #if HAS_W_MAX + #if ENABLED(ENDSTOPPULLUP_WMAX) + SET_INPUT_PULLUP(W_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_WMIN) + SET_INPUT_PULLDOWN(W_MAX_PIN); + #else + SET_INPUT(W_MAX_PIN); + #endif + #endif + #if PIN_EXISTS(CALIBRATION) #if ENABLED(CALIBRATION_PIN_PULLUP) SET_INPUT_PULLUP(CALIBRATION_PIN); @@ -424,7 +484,7 @@ void Endstops::event_handler() { prev_hit_state = hit_state; if (hit_state) { #if HAS_STATUS_MESSAGE - char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '), + char NUM_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' ', chrU = ' ', chrV = ' ', chrW = ' '), chrP = ' '; #define _SET_STOP_CHAR(A,C) (chr## A = C) #else @@ -444,16 +504,22 @@ void Endstops::event_handler() { #define ENDSTOP_HIT_TEST_I() _ENDSTOP_HIT_TEST(I,'I') #define ENDSTOP_HIT_TEST_J() _ENDSTOP_HIT_TEST(J,'J') #define ENDSTOP_HIT_TEST_K() _ENDSTOP_HIT_TEST(K,'K') + #define ENDSTOP_HIT_TEST_U() _ENDSTOP_HIT_TEST(U,'U') + #define ENDSTOP_HIT_TEST_V() _ENDSTOP_HIT_TEST(V,'V') + #define ENDSTOP_HIT_TEST_W() _ENDSTOP_HIT_TEST(W,'W') SERIAL_ECHO_START(); SERIAL_ECHOPGM(STR_ENDSTOPS_HIT); - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( ENDSTOP_HIT_TEST_X(), ENDSTOP_HIT_TEST_Y(), ENDSTOP_HIT_TEST_Z(), _ENDSTOP_HIT_TEST(I,'I'), _ENDSTOP_HIT_TEST(J,'J'), - _ENDSTOP_HIT_TEST(K,'K') + _ENDSTOP_HIT_TEST(K,'K'), + _ENDSTOP_HIT_TEST(U,'U'), + _ENDSTOP_HIT_TEST(V,'V'), + _ENDSTOP_HIT_TEST(W,'W') ); #if USES_Z_MIN_PROBE_PIN @@ -464,9 +530,9 @@ void Endstops::event_handler() { TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, - F(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"), + F(S_FMT GANG_N_1(NUM_AXES, " %c") " %c"), GET_TEXT(MSG_LCD_ENDSTOPS), - LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP + NUM_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK, chrU, chrV, chrW), chrP ) ); @@ -564,6 +630,24 @@ void _O2 Endstops::report_states() { #if HAS_K_MAX ES_REPORT(K_MAX); #endif + #if HAS_U_MIN + ES_REPORT(U_MIN); + #endif + #if HAS_U_MAX + ES_REPORT(U_MAX); + #endif + #if HAS_V_MIN + ES_REPORT(V_MIN); + #endif + #if HAS_V_MAX + ES_REPORT(V_MAX); + #endif + #if HAS_W_MIN + ES_REPORT(W_MIN); + #endif + #if HAS_W_MAX + ES_REPORT(W_MAX); + #endif #if ENABLED(PROBE_ACTIVATION_SWITCH) print_es_state(probe_switch_activated(), F(STR_PROBE_EN)); #endif @@ -649,6 +733,9 @@ void Endstops::update() { #define I_AXIS_HEAD I_AXIS #define J_AXIS_HEAD J_AXIS #define K_AXIS_HEAD K_AXIS + #define U_AXIS_HEAD U_AXIS + #define V_AXIS_HEAD V_AXIS + #define W_AXIS_HEAD W_AXIS /** * Check and update endstops @@ -835,6 +922,82 @@ void Endstops::update() { #endif #endif + #if HAS_U_MIN && !U_SPI_SENSORLESS + #if ENABLED(U_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(U, MIN); + #if HAS_U2_MIN + UPDATE_ENDSTOP_BIT(U2, MIN); + #else + COPY_LIVE_STATE(U_MIN, U2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(U, MIN); + #endif + #endif + + #if HAS_U_MAX && !U_SPI_SENSORLESS + #if ENABLED(U_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(U, MAX); + #if HAS_U2_MAX + UPDATE_ENDSTOP_BIT(U2, MAX); + #else + COPY_LIVE_STATE(U_MAX, U2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(U, MAX); + #endif + #endif + + #if HAS_V_MIN && !V_SPI_SENSORLESS + #if ENABLED(V_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(V, MIN); + #if HAS_V2_MIN + UPDATE_ENDSTOP_BIT(V2, MIN); + #else + COPY_LIVE_STATE(V_MIN, V2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(V, MIN); + #endif + #endif + #if HAS_V_MAX && !V_SPI_SENSORLESS + #if ENABLED(O_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(V, MAX); + #if HAS_V2_MAX + UPDATE_ENDSTOP_BIT(V2, MAX); + #else + COPY_LIVE_STATE(V_MAX, V2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(V, MAX); + #endif + #endif + + #if HAS_W_MIN && !W_SPI_SENSORLESS + #if ENABLED(W_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(W, MIN); + #if HAS_W2_MIN + UPDATE_ENDSTOP_BIT(W2, MIN); + #else + COPY_LIVE_STATE(W_MIN, W2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(W, MIN); + #endif + #endif + #if HAS_W_MAX && !W_SPI_SENSORLESS + #if ENABLED(W_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(W, MAX); + #if HAS_W2_MAX + UPDATE_ENDSTOP_BIT(W2, MAX); + #else + COPY_LIVE_STATE(W_MAX, W2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(W, MAX); + #endif + #endif + #if ENDSTOP_NOISE_THRESHOLD /** @@ -935,7 +1098,7 @@ void Endstops::update() { #define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX) #endif - #if HAS_G38_PROBE + #if HAS_G38_PROBE // TODO (DerAndere): Add support for HAS_I_AXIS #define _G38_OPEN_STATE TERN(G38_PROBE_AWAY, (G38_move >= 4), LOW) // For G38 moves check the probe's pin for ALL movement if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN))) != _G38_OPEN_STATE) { @@ -1105,6 +1268,51 @@ void Endstops::update() { } } #endif + + #if HAS_U_AXIS + if (stepper.axis_is_moving(U_AXIS)) { + if (stepper.motor_direction(U_AXIS_HEAD)) { // -direction + #if HAS_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN) + PROCESS_ENDSTOP(U, MIN); + #endif + } + else { // +direction + #if HAS_U_MAX || (U_SPI_SENSORLESS && U_HOME_TO_MAX) + PROCESS_ENDSTOP(U, MAX); + #endif + } + } + #endif + + #if HAS_V_AXIS + if (stepper.axis_is_moving(V_AXIS)) { + if (stepper.motor_direction(V_AXIS_HEAD)) { // -direction + #if HAS_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN) + PROCESS_ENDSTOP(V, MIN); + #endif + } + else { // +direction + #if HAS_V_MAX || (V_SPI_SENSORLESS && V_HOME_TO_MAX) + PROCESS_ENDSTOP(V, MAX); + #endif + } + } + #endif + + #if HAS_W_AXIS + if (stepper.axis_is_moving(W_AXIS)) { + if (stepper.motor_direction(W_AXIS_HEAD)) { // -direction + #if HAS_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN) + PROCESS_ENDSTOP(W, MIN); + #endif + } + else { // +direction + #if HAS_W_MAX || (W_SPI_SENSORLESS && W_HOME_TO_MAX) + PROCESS_ENDSTOP(W, MAX); + #endif + } + } + #endif } // Endstops::update() #if ENABLED(SPI_ENDSTOPS) @@ -1166,6 +1374,24 @@ void Endstops::update() { hit = true; } #endif + #if U_SPI_SENSORLESS + if (tmc_spi_homing.u && stepperU.test_stall_status()) { + SBI(live_state, U_ENDSTOP); + hit = true; + } + #endif + #if V_SPI_SENSORLESS + if (tmc_spi_homing.v && stepperV.test_stall_status()) { + SBI(live_state, V_ENDSTOP); + hit = true; + } + #endif + #if W_SPI_SENSORLESS + if (tmc_spi_homing.w && stepperW.test_stall_status()) { + SBI(live_state, W_ENDSTOP); + hit = true; + } + #endif if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update(); @@ -1179,6 +1405,9 @@ void Endstops::update() { TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP)); TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP)); TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP)); + TERN_(U_SPI_SENSORLESS, CBI(live_state, U_ENDSTOP)); + TERN_(V_SPI_SENSORLESS, CBI(live_state, V_ENDSTOP)); + TERN_(W_SPI_SENSORLESS, CBI(live_state, W_ENDSTOP)); } #endif // SPI_ENDSTOPS @@ -1273,6 +1502,24 @@ void Endstops::update() { #if HAS_K_MIN ES_GET_STATE(K_MIN); #endif + #if HAS_U_MAX + ES_GET_STATE(U_MAX); + #endif + #if HAS_U_MIN + ES_GET_STATE(U_MIN); + #endif + #if HAS_V_MAX + ES_GET_STATE(V_MAX); + #endif + #if HAS_V_MIN + ES_GET_STATE(V_MIN); + #endif + #if HAS_W_MAX + ES_GET_STATE(W_MAX); + #endif + #if HAS_W_MIN + ES_GET_STATE(W_MIN); + #endif uint16_t endstop_change = live_state_local ^ old_live_state_local; #define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S)) @@ -1347,6 +1594,25 @@ void Endstops::update() { #if HAS_K_MAX ES_REPORT_CHANGE(K_MAX); #endif + #if HAS_U_MIN + ES_REPORT_CHANGE(U_MIN); + #endif + #if HAS_U_MAX + ES_REPORT_CHANGE(U_MAX); + #endif + #if HAS_V_MIN + ES_REPORT_CHANGE(V_MIN); + #endif + #if HAS_V_MAX + ES_REPORT_CHANGE(V_MAX); + #endif + #if HAS_W_MIN + ES_REPORT_CHANGE(W_MIN); + #endif + #if HAS_W_MAX + ES_REPORT_CHANGE(W_MAX); + #endif + SERIAL_ECHOLNPGM("\n"); hal.set_pwm_duty(pin_t(LED_PIN), local_LED_status); local_LED_status ^= 255; diff --git a/Marlin/src/module/endstops.h b/Marlin/src/module/endstops.h index 82a44cf95b83..1848e6cdcf2c 100644 --- a/Marlin/src/module/endstops.h +++ b/Marlin/src/module/endstops.h @@ -45,6 +45,12 @@ enum EndstopEnum : char { _ES_ITEM(HAS_J_MAX, J_MAX) _ES_ITEM(HAS_K_MIN, K_MIN) _ES_ITEM(HAS_K_MAX, K_MAX) + _ES_ITEM(HAS_U_MIN, U_MIN) + _ES_ITEM(HAS_U_MAX, U_MAX) + _ES_ITEM(HAS_V_MIN, V_MIN) + _ES_ITEM(HAS_V_MAX, V_MAX) + _ES_ITEM(HAS_W_MIN, W_MIN) + _ES_ITEM(HAS_W_MAX, W_MAX) // Extra Endstops for XYZ #if ENABLED(X_DUAL_ENDSTOPS) @@ -234,7 +240,7 @@ class Endstops { typedef struct { union { bool any; - struct { bool LINEAR_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); }; + struct { bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); }; }; } tmc_spi_homing_t; static tmc_spi_homing_t tmc_spi_homing; diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index d8df8e12e1ed..3037c38bb0f7 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -84,7 +84,7 @@ bool relative_mode; // = false; #define Z_INIT_POS Z_HOME_POS #endif -xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS, I_HOME_POS, J_HOME_POS, K_HOME_POS); +xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS, I_HOME_POS, J_HOME_POS, K_HOME_POS, U_HOME_POS, V_HOME_POS, W_HOME_POS); /** * Cartesian Destination @@ -189,13 +189,16 @@ inline void report_more_positions() { inline void report_logical_position(const xyze_pos_t &rpos) { const xyze_pos_t lpos = rpos.asLogical(); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z, SP_I_LBL, lpos.i, SP_J_LBL, lpos.j, - SP_K_LBL, lpos.k + SP_K_LBL, lpos.k, + SP_U_LBL, lpos.u, + SP_V_LBL, lpos.v, + SP_W_LBL, lpos.w ) #if HAS_EXTRUDERS , SP_E_LBL, lpos.e @@ -210,7 +213,8 @@ void report_real_position() { xyze_pos_t npos = LOGICAL_AXIS_ARRAY( planner.get_axis_position_mm(E_AXIS), cartes.x, cartes.y, cartes.z, - cartes.i, cartes.j, cartes.k + cartes.i, cartes.j, cartes.k, + cartes.u, cartes.v, cartes.w ); TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true)); @@ -258,13 +262,16 @@ void report_current_position_projected() { const xyz_pos_t lpos = cartes.asLogical(); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z, SP_I_LBL, lpos.i, SP_J_LBL, lpos.j, - SP_K_LBL, lpos.k + SP_K_LBL, lpos.k, + SP_U_LBL, lpos.u, + SP_V_LBL, lpos.v, + SP_W_LBL, lpos.w ) #if HAS_EXTRUDERS , SP_E_LBL, current_position.e @@ -355,13 +362,16 @@ void get_cartesian_from_steppers() { ); cartes.z = planner.get_axis_position_mm(Z_AXIS); #else - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( cartes.x = planner.get_axis_position_mm(X_AXIS), cartes.y = planner.get_axis_position_mm(Y_AXIS), cartes.z = planner.get_axis_position_mm(Z_AXIS), cartes.i = planner.get_axis_position_mm(I_AXIS), cartes.j = planner.get_axis_position_mm(J_AXIS), - cartes.k = planner.get_axis_position_mm(K_AXIS) + cartes.k = planner.get_axis_position_mm(K_AXIS), + cartes.u = planner.get_axis_position_mm(U_AXIS), + cartes.v = planner.get_axis_position_mm(V_AXIS), + cartes.w = planner.get_axis_position_mm(W_AXIS) ); #endif } @@ -468,24 +478,23 @@ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/ * - Delta may lower Z first to get into the free motion zone. * - Before returning, wait for the planner buffer to empty. */ -void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) { +void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) { DEBUG_SECTION(log_move, "do_blocking_move_to", DEBUGGING(LEVELING)); - if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", LINEAR_AXIS_ARGS()); + if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", NUM_AXIS_ARGS()); const feedRate_t xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_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), + const feedRate_t u_feedrate = fr_mm_s ?: homing_feedrate(U_AXIS), + const feedRate_t v_feedrate = fr_mm_s ?: homing_feedrate(V_AXIS), + const feedRate_t w_feedrate = fr_mm_s ?: homing_feedrate(W_AXIS) + ); #if IS_KINEMATIC if (!position_is_reachable(x, y)) return; @@ -554,7 +563,18 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s #if HAS_K_AXIS current_position.k = k; line_to_current_position(k_feedrate); #endif - #if HAS_Z_AXIS // If Z needs to lower, do it after moving XY... + #if HAS_U_AXIS + current_position.u = u; line_to_current_position(u_feedrate); + #endif + #if HAS_V_AXIS + current_position.v = v; line_to_current_position(v_feedrate); + #endif + #if HAS_W_AXIS + current_position.w = w; line_to_current_position(w_feedrate); + #endif + + #if HAS_Z_AXIS + // If Z needs to lower, do it after moving XY if (current_position.z > z) { current_position.z = z; line_to_current_position(z_feedrate); } #endif @@ -564,17 +584,19 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s } void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k), fr_mm_s); + do_blocking_move_to(NUM_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s); } void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s); + do_blocking_move_to(NUM_AXIS_ELEM(raw), fr_mm_s); } void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s); + do_blocking_move_to(NUM_AXIS_ELEM(raw), fr_mm_s); } void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -582,7 +604,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Y_AXIS void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -600,7 +623,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k, raw.u, raw.v, raw.w), fr_mm_s ); } @@ -612,7 +635,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k, raw.u, raw.v, raw.w), fr_mm_s ); } @@ -624,7 +647,43 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k, raw.u, raw.v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_U_AXIS + void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijk_u(current_position, ru, fr_mm_s); + } + void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, u, raw.v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_V_AXIS + void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijku_v(current_position, rv, fr_mm_s); + } + void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_W_AXIS + void do_blocking_move_to_w(const_float_t rw, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijkuv_w(current_position, rw, fr_mm_s); + } + void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const_float_t w, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, raw.v, w), fr_mm_s ); } @@ -633,7 +692,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Y_AXIS void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -645,7 +705,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Z_AXIS void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -680,8 +741,8 @@ void restore_feedrate_and_scaling() { // Software Endstops are based on the configured limits. soft_endstops_t soft_endstop = { true, false, - LINEAR_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS), - LINEAR_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS) + NUM_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS, U_MIN_POS, V_MIN_POS, W_MIN_POS), + NUM_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS, U_MAX_POS, V_MAX_POS, W_MAX_POS) }; /** @@ -860,6 +921,36 @@ void restore_feedrate_and_scaling() { #endif } #endif + #if HAS_U_AXIS + if (axis_was_homed(U_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_U) + NOLESS(target.u, soft_endstop.min.u); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_U) + NOMORE(target.u, soft_endstop.max.u); + #endif + } + #endif + #if HAS_V_AXIS + if (axis_was_homed(V_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_V) + NOLESS(target.v, soft_endstop.min.v); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_V) + NOMORE(target.v, soft_endstop.max.v); + #endif + } + #endif + #if HAS_W_AXIS + if (axis_was_homed(W_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_W) + NOLESS(target.w, soft_endstop.min.w); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_W) + NOMORE(target.w, soft_endstop.max.w); + #endif + } + #endif } #else // !HAS_SOFTWARE_ENDSTOPS @@ -1297,9 +1388,10 @@ void prepare_line_to_destination() { CBI(b, a); }; // Clear test bits that are trusted - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( set_should(axis_bits, X_AXIS), set_should(axis_bits, Y_AXIS), set_should(axis_bits, Z_AXIS), - set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS) + set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS), + set_should(axis_bits, U_AXIS), set_should(axis_bits, V_AXIS), set_should(axis_bits, W_AXIS) ); return axis_bits; } @@ -1309,13 +1401,16 @@ void prepare_line_to_destination() { PGM_P home_first = GET_TEXT(MSG_HOME_FIRST); char msg[strlen_P(home_first)+1]; 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" : "", + NUM_AXIS_LIST( + TEST(axis_bits, X_AXIS) ? STR_A : "", + TEST(axis_bits, Y_AXIS) ? STR_B : "", + TEST(axis_bits, Z_AXIS) ? STR_C : "", TEST(axis_bits, I_AXIS) ? STR_I : "", TEST(axis_bits, J_AXIS) ? STR_J : "", - TEST(axis_bits, K_AXIS) ? STR_K : "" + TEST(axis_bits, K_AXIS) ? STR_K : "", + TEST(axis_bits, U_AXIS) ? STR_U : "", + TEST(axis_bits, V_AXIS) ? STR_V : "", + TEST(axis_bits, W_AXIS) ? STR_W : "" ) ); SERIAL_ECHO_START(); @@ -1395,6 +1490,15 @@ void prepare_line_to_destination() { #if K_SENSORLESS case K_AXIS: stealth_states.k = tmc_enable_stallguard(stepperK); break; #endif + #if U_SENSORLESS + case U_AXIS: stealth_states.u = tmc_enable_stallguard(stepperU); break; + #endif + #if V_SENSORLESS + case V_AXIS: stealth_states.v = tmc_enable_stallguard(stepperV); break; + #endif + #if W_SENSORLESS + case W_AXIS: stealth_states.w = tmc_enable_stallguard(stepperW); break; + #endif } #if ENABLED(SPI_ENDSTOPS) @@ -1415,6 +1519,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = true; break; #endif + #if HAS_U_AXIS + case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = true; break; + #endif + #if HAS_V_AXIS + case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = true; break; + #endif + #if HAS_W_AXIS + case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = true; break; + #endif default: break; } #endif @@ -1471,6 +1584,15 @@ void prepare_line_to_destination() { #if K_SENSORLESS case K_AXIS: tmc_disable_stallguard(stepperK, enable_stealth.k); break; #endif + #if U_SENSORLESS + case U_AXIS: tmc_disable_stallguard(stepperU, enable_stealth.u); break; + #endif + #if V_SENSORLESS + case V_AXIS: tmc_disable_stallguard(stepperV, enable_stealth.v); break; + #endif + #if W_SENSORLESS + case W_AXIS: tmc_disable_stallguard(stepperW, enable_stealth.w); break; + #endif } #if ENABLED(SPI_ENDSTOPS) @@ -1491,6 +1613,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = false; break; #endif + #if HAS_U_AXIS + case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = false; break; + #endif + #if HAS_V_AXIS + case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = false; break; + #endif + #if HAS_W_AXIS + case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = false; break; + #endif default: break; } #endif @@ -1667,6 +1798,30 @@ void prepare_line_to_destination() { stepperBackoutDir = INVERT_K_DIR ? effectorBackoutDir : -effectorBackoutDir; break; #endif + #ifdef U_MICROSTEPS + case U_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(U); + phaseCurrent = stepperU.get_microstep_counter(); + effectorBackoutDir = -U_HOME_DIR; + stepperBackoutDir = INVERT_U_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif + #ifdef V_MICROSTEPS + case V_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(V); + phaseCurrent = stepperV.get_microstep_counter(); + effectorBackoutDir = -V_HOME_DIR; + stepperBackoutDir = INVERT_V_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif + #ifdef W_MICROSTEPS + case W_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(W); + phaseCurrent = stepperW.get_microstep_counter(); + effectorBackoutDir = -W_HOME_DIR; + stepperBackoutDir = INVERT_W_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif default: return; } @@ -1723,13 +1878,16 @@ void prepare_line_to_destination() { || TERN0(A##_HOME_TO_MIN, A##_MIN_PIN > -1) \ || TERN0(A##_HOME_TO_MAX, A##_MAX_PIN > -1) \ )) - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( !_CAN_HOME(X), && !_CAN_HOME(Y), && !_CAN_HOME(Z), && !_CAN_HOME(I), && !_CAN_HOME(J), - && !_CAN_HOME(K)) + && !_CAN_HOME(K), + && !_CAN_HOME(U), + && !_CAN_HOME(V), + && !_CAN_HOME(W)) ) return; #endif @@ -1822,6 +1980,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: es = K_ENDSTOP; break; #endif + #if HAS_U_AXIS + case U_AXIS: es = U_ENDSTOP; break; + #endif + #if HAS_V_AXIS + case V_AXIS: es = V_ENDSTOP; break; + #endif + #if HAS_W_AXIS + case W_AXIS: es = W_ENDSTOP; break; + #endif } if (TEST(endstops.state(), es)) { SERIAL_ECHO_MSG("Bad ", AS_CHAR(AXIS_CHAR(axis)), " Endstop?"); diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 1dd6d8c4ede2..45dae5d6090a 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -44,7 +44,7 @@ extern xyze_pos_t current_position, // High-level current tool position // G60/G61 Position Save and Return #if SAVED_POSITIONS - extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4 + extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS extern xyze_pos_t stored_position[SAVED_POSITIONS]; #endif @@ -77,13 +77,16 @@ constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M; FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z); #if DISABLED(DELTA) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (a == X_AXIS) v = homing_feedrate_mm_m.x, else if (a == Y_AXIS) v = homing_feedrate_mm_m.y, else if (a == Z_AXIS) v = homing_feedrate_mm_m.z, else if (a == I_AXIS) v = homing_feedrate_mm_m.i, else if (a == J_AXIS) v = homing_feedrate_mm_m.j, - else if (a == K_AXIS) v = homing_feedrate_mm_m.k + else if (a == K_AXIS) v = homing_feedrate_mm_m.k, + else if (a == U_AXIS) v = homing_feedrate_mm_m.u, + else if (a == V_AXIS) v = homing_feedrate_mm_m.v, + else if (a == W_AXIS) v = homing_feedrate_mm_m.w ); #endif return MMM_TO_MMS(v); @@ -124,7 +127,7 @@ inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm #define XYZ_DEFS(T, NAME, OPT) \ inline T NAME(const AxisEnum axis) { \ - static const XYZval NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT); \ + static const XYZval NAME##_P DEFS_PROGMEM = NUM_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT, U_##OPT, V_##OPT, W_##OPT); \ return pgm_read_any(&NAME##_P[axis]); \ } XYZ_DEFS(float, base_min_pos, MIN_POS); @@ -198,6 +201,24 @@ inline float home_bump_mm(const AxisEnum axis) { TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k); break; #endif + #if HAS_U_AXIS + case U_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_U, amin = min.u); + TERN_(MIN_SOFTWARE_ENDSTOP_U, amax = max.u); + break; + #endif + #if HAS_V_AXIS + case V_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_V, amin = min.v); + TERN_(MIN_SOFTWARE_ENDSTOP_V, amax = max.v); + break; + #endif + #if HAS_W_AXIS + case W_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_W, amin = min.w); + TERN_(MIN_SOFTWARE_ENDSTOP_W, amax = max.w); + break; + #endif default: break; } #endif @@ -323,7 +344,7 @@ inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f) /** * Blocking movement and shorthand functions */ -void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f); +void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); @@ -347,6 +368,18 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f); #endif +#if HAS_U_AXIS + void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s=0.0f); + void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s=0.0f); +#endif +#if HAS_V_AXIS + void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s=0.0f); + void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s=0.0f); +#endif +#if HAS_W_AXIS + void do_blocking_move_to_w(const float rw, const feedRate_t &fr_mm_s=0.0f); + void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const float w, const feedRate_t &fr_mm_s=0.0f); +#endif #if HAS_Y_AXIS void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f); @@ -374,8 +407,8 @@ 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<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; +constexpr linear_axis_bits_t linear_bits = _BV(NUM_AXES) - 1; void set_axis_is_at_home(const AxisEnum axis); @@ -490,6 +523,18 @@ void home_if_needed(const bool keeplev=false); #define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS) #define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS) #endif +#if HAS_U_AXIS + #define LOGICAL_U_POSITION(POS) NATIVE_TO_LOGICAL(POS, U_AXIS) + #define RAW_U_POSITION(POS) LOGICAL_TO_NATIVE(POS, U_AXIS) +#endif +#if HAS_V_AXIS + #define LOGICAL_V_POSITION(POS) NATIVE_TO_LOGICAL(POS, V_AXIS) + #define RAW_V_POSITION(POS) LOGICAL_TO_NATIVE(POS, V_AXIS) +#endif +#if HAS_W_AXIS + #define LOGICAL_W_POSITION(POS) NATIVE_TO_LOGICAL(POS, W_AXIS) + #define RAW_W_POSITION(POS) LOGICAL_TO_NATIVE(POS, W_AXIS) +#endif /** * position_is_reachable family of functions diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 8c723aa06e80..ae67073b4f16 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1300,7 +1300,7 @@ void Planner::recalculate() { */ void Planner::check_axes_activity() { - #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_E) + #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W, DISABLE_E) xyze_bool_t axis_active = { false }; #endif @@ -1350,7 +1350,10 @@ void Planner::check_axes_activity() { if (TERN0(DISABLE_Z, block->steps.z)) axis_active.z = true, if (TERN0(DISABLE_I, block->steps.i)) axis_active.i = true, if (TERN0(DISABLE_J, block->steps.j)) axis_active.j = true, - if (TERN0(DISABLE_K, block->steps.k)) axis_active.k = true + if (TERN0(DISABLE_K, block->steps.k)) axis_active.k = true, + if (TERN0(DISABLE_U, block->steps.u)) axis_active.u = true, + if (TERN0(DISABLE_V, block->steps.v)) axis_active.v = true, + if (TERN0(DISABLE_W, block->steps.w)) axis_active.w = true ); } #endif @@ -1385,7 +1388,10 @@ void Planner::check_axes_activity() { 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) + if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS), + if (TERN0(DISABLE_U, !axis_active.u)) stepper.disable_axis(U_AXIS), + if (TERN0(DISABLE_V, !axis_active.v)) stepper.disable_axis(V_AXIS), + if (TERN0(DISABLE_W, !axis_active.w)) stepper.disable_axis(W_AXIS) ); // @@ -1453,7 +1459,7 @@ void Planner::check_axes_activity() { float high = 0.0; for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) { block_t *block = &block_buffer[b]; - if (LINEAR_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k)) { + if (NUM_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k, || block->steps.u, || block->steps.v, || block->steps.w)) { const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec; NOLESS(high, se); } @@ -1856,15 +1862,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move, dc = target.c - position.c, di = target.i - position.i, dj = target.j - position.j, - dk = target.k - position.k + dk = target.k - position.k, + du = target.u - position.u, + dv = target.v - position.v, + dw = target.w - position.w ); /* <-- add a slash to enable SERIAL_ECHOLNPGM( " _populate_block FR:", fr_mm_s, " A:", target.a, " (", da, " steps)" - " B:", target.b, " (", db, " steps)" - " C:", target.c, " (", dc, " steps)" + #if HAS_Y_AXIS + " B:", target.b, " (", db, " steps)" + #endif + #if HAS_Z_AXIS + " C:", target.c, " (", dc, " steps)" + #endif #if HAS_I_AXIS " " STR_I ":", target.i, " (", di, " steps)" #endif @@ -1874,6 +1887,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move, #if HAS_K_AXIS " " STR_K ":", target.k, " (", dk, " steps)" #endif + #if HAS_U_AXIS + " " STR_U ":", target.u, " (", du, " steps)" + #endif + #if HAS_V_AXIS + " " STR_V ":", target.v, " (", dv, " steps)" + #endif + #if HAS_W_AXIS + " " STR_W ":", target.w, " (", dw, " steps)" #if HAS_EXTRUDERS " E:", target.e, " (", de, " steps)" #endif @@ -1938,15 +1959,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move, 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 @@ -1954,16 +1966,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move, 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 (du < 0) SBI(dm, U_AXIS), + if (dv < 0) SBI(dm, V_AXIS), + if (dw < 0) SBI(dm, W_AXIS) + ); + #if HAS_EXTRUDERS if (de < 0) SBI(dm, E_AXIS); const float esteps_float = de * e_factor[extruder]; @@ -1988,20 +2006,20 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Number of steps for each axis // See https://www.corexy.com/theory.html #if CORE_IS_XY - block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(da - db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da + db), ABS(da - db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif CORE_IS_XZ - block->steps.set(LINEAR_AXIS_LIST(ABS(da + dc), ABS(db), ABS(da - dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da + dc), ABS(db), ABS(da - dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif CORE_IS_YZ - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #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(NUM_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif ENABLED(MARKFORGED_YX) - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif IS_SCARA - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #else // default non-h-bot planning - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #endif /** @@ -2040,9 +2058,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move, steps_dist_mm.b = (db + dc) * mm_per_step[B_AXIS]; steps_dist_mm.c = CORESIGN(db - dc) * mm_per_step[C_AXIS]; #endif - TERN_(HAS_I_AXIS, steps_dist_mm.i = di * mm_per_step[I_AXIS]); - TERN_(HAS_J_AXIS, steps_dist_mm.j = dj * mm_per_step[J_AXIS]); - TERN_(HAS_K_AXIS, steps_dist_mm.k = dk * mm_per_step[K_AXIS]); #elif ENABLED(MARKFORGED_XY) steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS]; steps_dist_mm.b = db * mm_per_step[B_AXIS]; @@ -2050,27 +2065,40 @@ bool Planner::_populate_block(block_t * const block, bool split_move, 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], + steps_dist_mm.u = du * mm_per_step[U_AXIS], + steps_dist_mm.v = dv * mm_per_step[V_AXIS], + steps_dist_mm.w = dw * mm_per_step[W_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); - if (true LINEAR_AXIS_GANG( + #if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) + bool cartesian_move = true; + #endif + + if (true NUM_AXIS_GANG( && block->steps.a < MIN_STEPS_PER_SEGMENT, && block->steps.b < MIN_STEPS_PER_SEGMENT, && block->steps.c < MIN_STEPS_PER_SEGMENT, && block->steps.i < MIN_STEPS_PER_SEGMENT, && block->steps.j < MIN_STEPS_PER_SEGMENT, - && block->steps.k < MIN_STEPS_PER_SEGMENT + && block->steps.k < MIN_STEPS_PER_SEGMENT, + && block->steps.u < MIN_STEPS_PER_SEGMENT, + && block->steps.v < MIN_STEPS_PER_SEGMENT, + && block->steps.w < MIN_STEPS_PER_SEGMENT ) ) { block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e)); @@ -2079,36 +2107,71 @@ bool Planner::_populate_block(block_t * const block, bool split_move, if (millimeters) block->millimeters = millimeters; else { - block->millimeters = SQRT( - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - LINEAR_AXIS_GANG( - 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) - ) - #elif CORE_IS_XZ - LINEAR_AXIS_GANG( - sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z), - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) - #elif CORE_IS_YZ - LINEAR_AXIS_GANG( - sq(steps_dist_mm.x) + sq(steps_dist_mm.head.y) + sq(steps_dist_mm.head.z) - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) - #elif ENABLED(FOAMCUTTER_XYUV) - // Return the largest distance move from either X/Y or I/J plane + /** + * Distance for interpretation of feedrate in accordance with LinuxCNC (the successor of NIST + * RS274NGC interpreter - version 3) and its default CANON_XYZ feed reference mode. + * Assume that X, Y, Z are the primary linear axes and U, V, W are secondary linear axes and A, B, C are + * rotational axes. Then dX, dY, dZ are the displacements of the primary linear axes and dU, dV, dW are the displacements of linear axes and + * dA, dB, dC are the displacements of rotational axes. + * The time it takes to execute move command with feedrate F is t = D/F, where D is the total distance, calculated as follows: + * D^2 = dX^2 + dY^2 + dZ^2 + * if D^2 == 0 (none of XYZ move but any secondary linear axes move, whether other axes are moved or not): + * D^2 = dU^2 + dV^2 + dW^2 + * if D^2 == 0 (only rotational axes are moved): + * D^2 = dA^2 + dB^2 + dC^2 + */ + float distance_sqr = ( + #if ENABLED(ARTICULATED_ROBOT_ARM) + // For articulated robots, interpreting feedrate like LinuxCNC would require inverse kinematics. As a workaround, pretend that motors sit on n mutually orthogonal + // axes and assume that we could think of distance as magnitude of an n-vector in an n-dimensional Euclidian space. + NUM_AXIS_GANG( + sq(steps_dist_mm.x), + sq(steps_dist_mm.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.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w) + ); + #elif ENABLED(FOAMCUTTER_XYUV) #if HAS_J_AXIS - _MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j)) - #else + // Special 5 axis kinematics. Return the largest distance move from either X/Y or I/J plane + _MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j)) + #else // Foamcutter with only two axes (XY) sq(steps_dist_mm.x) + sq(steps_dist_mm.y) #endif + #elif ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) + XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z)) + #elif CORE_IS_XZ + XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z)) + #elif CORE_IS_YZ + XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.head.z)) #else - LINEAR_AXIS_GANG( - sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z), - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) + XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z)) #endif ); + + #if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM) + if (NEAR_ZERO(distance_sqr)) { + // Move does not involve any primary linear axes (xyz) but might involve secondary linear axes + distance_sqr = (0.0 + SECONDARY_AXIS_GANG( + IF_DISABLED(AXIS4_ROTATES, + sq(steps_dist_mm.i)), + IF_DISABLED(AXIS5_ROTATES, + sq(steps_dist_mm.j)), + IF_DISABLED(AXIS6_ROTATES, + sq(steps_dist_mm.k)), + IF_DISABLED(AXIS7_ROTATES, + sq(steps_dist_mm.u)), + IF_DISABLED(AXIS8_ROTATES, + sq(steps_dist_mm.v)), + IF_DISABLED(AXIS9_ROTATES, + sq(steps_dist_mm.w)) + ) + ); + } + #endif + + #if HAS_ROTATIONAL_AXES && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM) + if (NEAR_ZERO(distance_sqr)) { + // Move involves only rotational axes. Calculate angular distance in accordance with LinuxCNC + TERN_(INCH_MODE_SUPPORT, cartesian_move = false); + distance_sqr = ROTATIONAL_AXIS_GANG(sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k), + sq(steps_dist_mm.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w)); + } + #endif + + block->millimeters = SQRT(distance_sqr); } /** @@ -2125,8 +2188,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, TERN_(HAS_EXTRUDERS, block->steps.e = esteps); - block->step_event_count = _MAX(LOGICAL_AXIS_LIST( - esteps, block->steps.a, block->steps.b, block->steps.c, block->steps.i, block->steps.j, block->steps.k + block->step_event_count = _MAX(LOGICAL_AXIS_LIST(esteps, + block->steps.a, block->steps.b, block->steps.c, + block->steps.i, block->steps.j, block->steps.k, + block->steps.u, block->steps.v, block->steps.w )); // Bail if this is a zero-length block @@ -2148,13 +2213,16 @@ bool Planner::_populate_block(block_t * const block, bool split_move, E_TERN_(block->extruder = extruder); #if ENABLED(AUTO_POWER_CONTROL) - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, - || block->steps.k + || block->steps.k, + || block->steps.u, + || block->steps.v, + || block->steps.w )) powerManager.power_on(); #endif @@ -2180,19 +2248,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move, } if (block->steps.x) stepper.enable_axis(X_AXIS); #else - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( 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) + if (block->steps.k) stepper.enable_axis(K_AXIS), + if (block->steps.u) stepper.enable_axis(U_AXIS), + if (block->steps.v) stepper.enable_axis(V_AXIS), + if (block->steps.w) stepper.enable_axis(W_AXIS) ); #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), + if (block->steps.u) stepper.enable_axis(U_AXIS), + if (block->steps.v) stepper.enable_axis(V_AXIS), + if (block->steps.w) stepper.enable_axis(W_AXIS) + ); #endif // Enable extruder(s) @@ -2239,8 +2315,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move, const float inverse_millimeters = 1.0f / block->millimeters; // Inverse millimeters to remove multiple divides // Calculate inverse time for this move. No divide by zero due to previous checks. - // Example: At 120mm/s a 60mm move takes 0.5s. So this will give 2.0. - float inverse_secs = fr_mm_s * inverse_millimeters; + // Example: At 120mm/s a 60mm move involving XYZ axes takes 0.5s. So this will give 2.0. + // Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0. + float inverse_secs; + #if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) + inverse_secs = inverse_millimeters * (cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s)); + #else + inverse_secs = fr_mm_s * inverse_millimeters; + #endif // Get the number of non busy movements in queue (non busy means that they can be altered) const uint8_t moves_queued = nonbusy_movesplanned(); @@ -2286,13 +2368,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move, filwidth.advance_e(steps_dist_mm.e); #endif - // Calculate and limit speed in mm/sec + // Calculate and limit speed in mm/sec (linear) or degrees/sec (rotational) xyze_float_t current_speed; float speed_factor = 1.0f; // factor <1 decreases speed // Linear axes first with less logic - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { current_speed[i] = steps_dist_mm[i] * inverse_secs; const feedRate_t cs = ABS(current_speed[i]), max_fr = settings.max_feedrate_mm_s[i]; @@ -2380,9 +2462,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Compute and limit the acceleration rate for the trapezoid generator. const float steps_per_mm = block->step_event_count * inverse_millimeters; uint32_t accel; - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( !block->steps.a, && !block->steps.b, && !block->steps.c, - && !block->steps.i, && !block->steps.j, && !block->steps.k) + && !block->steps.i, && !block->steps.j, && !block->steps.k, + && !block->steps.u, && !block->steps.v, && !block->steps.w) ) { // Is this a retract / recover move? accel = CEIL(settings.retract_acceleration * steps_per_mm); // Convert to: acceleration steps/sec^2 TERN_(LIN_ADVANCE, block->use_advance_lead = false); // No linear advance for simple retract/recover @@ -2455,7 +2538,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, LIMIT_ACCEL_LONG(C_AXIS, 0), LIMIT_ACCEL_LONG(I_AXIS, 0), LIMIT_ACCEL_LONG(J_AXIS, 0), - LIMIT_ACCEL_LONG(K_AXIS, 0) + LIMIT_ACCEL_LONG(K_AXIS, 0), + LIMIT_ACCEL_LONG(U_AXIS, 0), + LIMIT_ACCEL_LONG(V_AXIS, 0), + LIMIT_ACCEL_LONG(W_AXIS, 0) ); } else { @@ -2466,7 +2552,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, LIMIT_ACCEL_FLOAT(C_AXIS, 0), LIMIT_ACCEL_FLOAT(I_AXIS, 0), LIMIT_ACCEL_FLOAT(J_AXIS, 0), - LIMIT_ACCEL_FLOAT(K_AXIS, 0) + LIMIT_ACCEL_FLOAT(K_AXIS, 0), + LIMIT_ACCEL_FLOAT(U_AXIS, 0), + LIMIT_ACCEL_FLOAT(V_AXIS, 0), + LIMIT_ACCEL_FLOAT(W_AXIS, 0) ); } } @@ -2531,7 +2620,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, #if HAS_DIST_MM_ARG cart_dist_mm #else - LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k) + LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k, steps_dist_mm.u, steps_dist_mm.v, steps_dist_mm.w) #endif ; @@ -2557,7 +2646,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, + (-prev_unit_vec.z * unit_vec.z), + (-prev_unit_vec.i * unit_vec.i), + (-prev_unit_vec.j * unit_vec.j), - + (-prev_unit_vec.k * unit_vec.k) + + (-prev_unit_vec.k * unit_vec.k), + + (-prev_unit_vec.u * unit_vec.u), + + (-prev_unit_vec.v * unit_vec.v), + + (-prev_unit_vec.w * unit_vec.w) ); // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta). @@ -2704,7 +2796,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, const float extra_xyjerk = TERN0(HAS_EXTRUDERS, de <= 0) ? TRAVEL_EXTRA_XYJERK : 0; uint8_t limited = 0; - TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(i) { + TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(i) { const float jerk = ABS(current_speed[i]), // cs : Starting from zero, change in speed for this axis maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f)); // mj : The max jerk setting for this axis if (jerk > maxj) { // cs > mj : New current speed too fast? @@ -2742,7 +2834,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, vmax_junction = previous_nominal_speed; // Now limit the jerk in all axes. - TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(axis) { + TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(axis) { // Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop. float v_exit = previous_speed[axis] * smaller_speed_factor, v_entry = current_speed[axis]; @@ -2844,7 +2936,7 @@ void Planner::buffer_sync_block(TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_ block->position = position; #if ENABLED(BACKLASH_COMPENSATION) - LOOP_LINEAR_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis); #endif #if BOTH(HAS_FAN, LASER_SYNCHRONOUS_M106_M107) @@ -2906,7 +2998,10 @@ bool Planner::buffer_segment(const abce_pos_t &abce int32_t(LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS])), int32_t(LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS])), int32_t(LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS])), - int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])) + int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])), + int32_t(LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS])), + int32_t(LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS])), + int32_t(LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS])) ) }; @@ -2958,6 +3053,21 @@ bool Planner::buffer_segment(const abce_pos_t &abce SERIAL_ECHOPGM(" (", position.k, "->", target.k); SERIAL_CHAR(')'); #endif + #if HAS_U_AXIS + SERIAL_ECHOPGM_P(SP_U_LBL, abce.u); + SERIAL_ECHOPGM(" (", position.u, "->", target.u); + SERIAL_CHAR(')'); + #endif + #if HAS_V_AXIS + SERIAL_ECHOPGM_P(SP_V_LBL, abce.v); + SERIAL_ECHOPGM(" (", position.v, "->", target.v); + SERIAL_CHAR(')'); + #endif + #if HAS_W_AXIS + SERIAL_ECHOPGM_P(SP_W_LBL, abce.w); + SERIAL_ECHOPGM(" (", position.w, "->", target.w); + SERIAL_CHAR(')'); + #endif #if HAS_EXTRUDERS SERIAL_ECHOPGM_P(SP_E_LBL, abce.e); SERIAL_ECHOLNPGM(" (", position.e, "->", target.e, ")"); @@ -3000,12 +3110,14 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons const xyze_pos_t cart_dist_mm = LOGICAL_AXIS_ARRAY( cart.e - position_cart.e, cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z, - cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k + cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k, + cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w ); #else - const xyz_pos_t cart_dist_mm = LINEAR_AXIS_ARRAY( + const xyz_pos_t cart_dist_mm = NUM_AXIS_ARRAY( cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z, - cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k + cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k, + cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w ); #endif @@ -3110,7 +3222,10 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) { LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS]), LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS]), LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS]), - LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]) + LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]), + LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS]), + LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS]), + LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS]) ) ); @@ -3122,7 +3237,7 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) { else { #if ENABLED(BACKLASH_COMPENSATION) abce_long_t stepper_pos = position; - LOOP_LINEAR_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis); stepper.set_position(stepper_pos); #else stepper.set_position(position); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 5b79e406f5dd..eb4a34cec93e 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -84,7 +84,8 @@ constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE, manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f, _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f, - _mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f); + _mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f, + _mf.u / 60.0f, _mf.v / 60.0f, _mf.w / 60.0f); #endif #if IS_KINEMATIC && HAS_JUNCTION_DEVIATION @@ -843,7 +844,8 @@ class Planner { const abce_pos_t out = LOGICAL_AXIS_ARRAY( get_axis_position_mm(E_AXIS), get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS), - get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS) + get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS), + get_axis_position_mm(U_AXIS), get_axis_position_mm(V_AXIS), get_axis_position_mm(W_AXIS) ); return out; } diff --git a/Marlin/src/module/planner_bezier.cpp b/Marlin/src/module/planner_bezier.cpp index 848906705fa2..fa7e16a387e6 100644 --- a/Marlin/src/module/planner_bezier.cpp +++ b/Marlin/src/module/planner_bezier.cpp @@ -188,7 +188,10 @@ void cubic_b_spline( interp(position.z, target.z, t), // FIXME. Wrong, since t is not linear in the distance. interp(position.i, target.i, t), // FIXME. Wrong, since t is not linear in the distance. interp(position.j, target.j, t), // FIXME. Wrong, since t is not linear in the distance. - interp(position.k, target.k, t) // FIXME. Wrong, since t is not linear in the distance. + interp(position.k, target.k, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.u, target.u, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.v, target.v, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.w, target.w, t) // FIXME. Wrong, since t is not linear in the distance. ); apply_motion_limits(new_bez); bez_target = new_bez; diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 5b0bd77d0de7..f9a64a02d37a 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -794,9 +794,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai #endif // On delta keep Z below clip height or do_blocking_move_to will abort - xyz_pos_t npos = LINEAR_AXIS_ARRAY( + xyz_pos_t npos = NUM_AXIS_ARRAY( rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z), - current_position.i, current_position.j, current_position.k + current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w ); if (!can_reach(npos, probe_relative)) { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable"); @@ -888,7 +889,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai */ void Probe::set_homing_current(const bool onoff) { #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT) - #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z) + #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) || HAS_CURRENT_HOME(U) || HAS_CURRENT_HOME(V) || HAS_CURRENT_HOME(W) #if ENABLED(DELTA) static int16_t saved_current_X, saved_current_Y; #endif diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index f2fca10a8038..c802411be3a1 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -138,7 +138,7 @@ class Probe { #else - static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767 + static constexpr xyz_pos_t offset = xyz_pos_t(NUM_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767 static bool set_deployed(const bool) { return false; } diff --git a/Marlin/src/module/scara.cpp b/Marlin/src/module/scara.cpp index 2527292e160c..bc42b85fbe13 100644 --- a/Marlin/src/module/scara.cpp +++ b/Marlin/src/module/scara.cpp @@ -254,7 +254,7 @@ float segments_per_second = TERN(AXEL_TPARA, TPARA_SEGMENTS_PER_SECOND, SCARA_SE // Do this here all at once for Delta, because // XYZ isn't ABC. Applying this per-tower would // give the impression that they are the same. - LOOP_LINEAR_AXES(i) set_axis_is_at_home((AxisEnum)i); + LOOP_NUM_AXES(i) set_axis_is_at_home((AxisEnum)i); sync_plan_position(); } diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index 5d91a90c655d..2b2aae263350 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -179,10 +179,10 @@ #define _EN_ITEM(N) , E##N -typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t; -typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t; -typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t; -typedef struct { bool LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t; +typedef struct { uint16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t; +typedef struct { uint32_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t; +typedef struct { int16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t; +typedef struct { bool NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t; #undef _EN_ITEM @@ -210,7 +210,7 @@ typedef struct SettingsDataStruct { // // DISTINCT_E_FACTORS // - uint8_t e_factors; // DISTINCT_AXES - LINEAR_AXES + uint8_t e_factors; // DISTINCT_AXES - NUM_AXES // // Planner settings @@ -444,7 +444,7 @@ typedef struct SettingsDataStruct { // HAS_MOTOR_CURRENT_PWM // #ifndef MOTOR_CURRENT_COUNT - #define MOTOR_CURRENT_COUNT LINEAR_AXES + #define MOTOR_CURRENT_COUNT NUM_AXES #endif uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // M907 X Z E ... @@ -590,7 +590,7 @@ void MarlinSettings::postprocess() { #endif // Software endstops depend on home_offset - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { update_workspace_offset((AxisEnum)i); update_software_endstops((AxisEnum)i); } @@ -738,7 +738,7 @@ void MarlinSettings::postprocess() { working_crc = 0; // clear before first "real data" - const uint8_t e_factors = DISTINCT_AXES - (LINEAR_AXES); + const uint8_t e_factors = DISTINCT_AXES - (NUM_AXES); _FIELD_TEST(e_factors); EEPROM_WRITE(e_factors); @@ -755,7 +755,7 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(dummyf); #endif #else - const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4, 0.4, 0.4, 0.4); + const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4); EEPROM_WRITE(planner_max_jerk); #endif @@ -1234,6 +1234,15 @@ void MarlinSettings::postprocess() { #if AXIS_IS_TMC(K) tmc_stepper_current.K = stepperK.getMilliamps(); #endif + #if AXIS_IS_TMC(U) + tmc_stepper_current.U = stepperU.getMilliamps(); + #endif + #if AXIS_IS_TMC(V) + tmc_stepper_current.V = stepperV.getMilliamps(); + #endif + #if AXIS_IS_TMC(W) + tmc_stepper_current.W = stepperW.getMilliamps(); + #endif #if AXIS_IS_TMC(X2) tmc_stepper_current.X2 = stepperX2.getMilliamps(); #endif @@ -1291,6 +1300,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, tmc_hybrid_threshold.I = stepperI.get_pwm_thrs()); TERN_(J_HAS_STEALTHCHOP, tmc_hybrid_threshold.J = stepperJ.get_pwm_thrs()); TERN_(K_HAS_STEALTHCHOP, tmc_hybrid_threshold.K = stepperK.get_pwm_thrs()); + TERN_(U_HAS_STEALTHCHOP, tmc_hybrid_threshold.U = stepperU.get_pwm_thrs()); + TERN_(V_HAS_STEALTHCHOP, tmc_hybrid_threshold.V = stepperV.get_pwm_thrs()); + TERN_(W_HAS_STEALTHCHOP, tmc_hybrid_threshold.W = stepperW.get_pwm_thrs()); TERN_(X2_HAS_STEALTHCHOP, tmc_hybrid_threshold.X2 = stepperX2.get_pwm_thrs()); TERN_(Y2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Y2 = stepperY2.get_pwm_thrs()); TERN_(Z2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z2 = stepperZ2.get_pwm_thrs()); @@ -1307,7 +1319,7 @@ void MarlinSettings::postprocess() { #else #define _EN_ITEM(N) , .E##N = 30 const tmc_hybrid_threshold_t tmc_hybrid_threshold = { - LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3), + NUM_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3, .U = 3, .V = 3, .W = 3), .X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3 REPEAT(E_STEPPERS, _EN_ITEM) }; @@ -1322,13 +1334,16 @@ void MarlinSettings::postprocess() { { tmc_sgt_t tmc_sgt{0}; #if USE_SENSORLESS - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( TERN_(X_SENSORLESS, tmc_sgt.X = stepperX.homing_threshold()), TERN_(Y_SENSORLESS, tmc_sgt.Y = stepperY.homing_threshold()), TERN_(Z_SENSORLESS, tmc_sgt.Z = stepperZ.homing_threshold()), TERN_(I_SENSORLESS, tmc_sgt.I = stepperI.homing_threshold()), TERN_(J_SENSORLESS, tmc_sgt.J = stepperJ.homing_threshold()), - TERN_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold()) + TERN_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold()), + TERN_(U_SENSORLESS, tmc_sgt.U = stepperU.homing_threshold()), + TERN_(V_SENSORLESS, tmc_sgt.V = stepperV.homing_threshold()), + TERN_(W_SENSORLESS, tmc_sgt.W = stepperW.homing_threshold()) ); TERN_(X2_SENSORLESS, tmc_sgt.X2 = stepperX2.homing_threshold()); TERN_(Y2_SENSORLESS, tmc_sgt.Y2 = stepperY2.homing_threshold()); @@ -1352,6 +1367,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, tmc_stealth_enabled.I = stepperI.get_stored_stealthChop()); TERN_(J_HAS_STEALTHCHOP, tmc_stealth_enabled.J = stepperJ.get_stored_stealthChop()); TERN_(K_HAS_STEALTHCHOP, tmc_stealth_enabled.K = stepperK.get_stored_stealthChop()); + TERN_(U_HAS_STEALTHCHOP, tmc_stealth_enabled.U = stepperU.get_stored_stealthChop()); + TERN_(V_HAS_STEALTHCHOP, tmc_stealth_enabled.V = stepperV.get_stored_stealthChop()); + TERN_(W_HAS_STEALTHCHOP, tmc_stealth_enabled.W = stepperW.get_stored_stealthChop()); TERN_(X2_HAS_STEALTHCHOP, tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop()); TERN_(Y2_HAS_STEALTHCHOP, tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop()); TERN_(Z2_HAS_STEALTHCHOP, tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop()); @@ -1441,7 +1459,7 @@ void MarlinSettings::postprocess() { { #if ENABLED(BACKLASH_GCODE) xyz_float_t backlash_distance_mm; - LOOP_LINEAR_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis); + LOOP_NUM_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis); const uint8_t backlash_correction = backlash.get_correction_uint8(); #else const xyz_float_t backlash_distance_mm{0}; @@ -1653,16 +1671,16 @@ void MarlinSettings::postprocess() { { // Get only the number of E stepper parameters previously stored // Any steppers added later are set to their defaults - uint32_t tmp1[LINEAR_AXES + e_factors]; - float tmp2[LINEAR_AXES + e_factors]; - feedRate_t tmp3[LINEAR_AXES + e_factors]; + uint32_t tmp1[NUM_AXES + e_factors]; + float tmp2[NUM_AXES + e_factors]; + feedRate_t tmp3[NUM_AXES + e_factors]; EEPROM_READ((uint8_t *)tmp1, sizeof(tmp1)); // max_acceleration_mm_per_s2 EEPROM_READ(planner.settings.min_segment_time_us); EEPROM_READ((uint8_t *)tmp2, sizeof(tmp2)); // axis_steps_per_mm EEPROM_READ((uint8_t *)tmp3, sizeof(tmp3)); // max_feedrate_mm_s if (!validating) LOOP_DISTINCT_AXES(i) { - const bool in = (i < e_factors + LINEAR_AXES); + const bool in = (i < e_factors + NUM_AXES); planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]); planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]); planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]); @@ -2175,6 +2193,15 @@ void MarlinSettings::postprocess() { #if AXIS_IS_TMC(K) SET_CURR(K); #endif + #if AXIS_IS_TMC(U) + SET_CURR(U); + #endif + #if AXIS_IS_TMC(V) + SET_CURR(V); + #endif + #if AXIS_IS_TMC(W) + SET_CURR(W); + #endif #if AXIS_IS_TMC(E0) SET_CURR(E0); #endif @@ -2222,6 +2249,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, stepperI.set_pwm_thrs(tmc_hybrid_threshold.I)); TERN_(J_HAS_STEALTHCHOP, stepperJ.set_pwm_thrs(tmc_hybrid_threshold.J)); TERN_(K_HAS_STEALTHCHOP, stepperK.set_pwm_thrs(tmc_hybrid_threshold.K)); + TERN_(U_HAS_STEALTHCHOP, stepperU.set_pwm_thrs(tmc_hybrid_threshold.U)); + TERN_(V_HAS_STEALTHCHOP, stepperV.set_pwm_thrs(tmc_hybrid_threshold.V)); + TERN_(W_HAS_STEALTHCHOP, stepperW.set_pwm_thrs(tmc_hybrid_threshold.W)); TERN_(E0_HAS_STEALTHCHOP, stepperE0.set_pwm_thrs(tmc_hybrid_threshold.E0)); TERN_(E1_HAS_STEALTHCHOP, stepperE1.set_pwm_thrs(tmc_hybrid_threshold.E1)); TERN_(E2_HAS_STEALTHCHOP, stepperE2.set_pwm_thrs(tmc_hybrid_threshold.E2)); @@ -2243,13 +2273,16 @@ void MarlinSettings::postprocess() { EEPROM_READ(tmc_sgt); #if USE_SENSORLESS if (!validating) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( TERN_(X_SENSORLESS, stepperX.homing_threshold(tmc_sgt.X)), TERN_(Y_SENSORLESS, stepperY.homing_threshold(tmc_sgt.Y)), TERN_(Z_SENSORLESS, stepperZ.homing_threshold(tmc_sgt.Z)), TERN_(I_SENSORLESS, stepperI.homing_threshold(tmc_sgt.I)), TERN_(J_SENSORLESS, stepperJ.homing_threshold(tmc_sgt.J)), - TERN_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K)) + TERN_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K)), + TERN_(U_SENSORLESS, stepperU.homing_threshold(tmc_sgt.U)), + TERN_(V_SENSORLESS, stepperV.homing_threshold(tmc_sgt.V)), + TERN_(W_SENSORLESS, stepperW.homing_threshold(tmc_sgt.W)) ); TERN_(X2_SENSORLESS, stepperX2.homing_threshold(tmc_sgt.X2)); TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(tmc_sgt.Y2)); @@ -2277,6 +2310,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, SET_STEPPING_MODE(I)); TERN_(J_HAS_STEALTHCHOP, SET_STEPPING_MODE(J)); TERN_(K_HAS_STEALTHCHOP, SET_STEPPING_MODE(K)); + TERN_(U_HAS_STEALTHCHOP, SET_STEPPING_MODE(U)); + TERN_(V_HAS_STEALTHCHOP, SET_STEPPING_MODE(V)); + TERN_(W_HAS_STEALTHCHOP, SET_STEPPING_MODE(W)); TERN_(X2_HAS_STEALTHCHOP, SET_STEPPING_MODE(X2)); TERN_(Y2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Y2)); TERN_(Z2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z2)); @@ -2397,7 +2433,7 @@ void MarlinSettings::postprocess() { EEPROM_READ(backlash_smoothing_mm); #if ENABLED(BACKLASH_GCODE) - LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]); + LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]); backlash.set_correction_uint8(backlash_correction); #ifdef BACKLASH_SMOOTHING_MM backlash.set_smoothing_mm(backlash_smoothing_mm); @@ -2773,8 +2809,17 @@ void MarlinSettings::reset() { #if HAS_K_AXIS && !defined(DEFAULT_KJERK) #define DEFAULT_KJERK 0 #endif + #if HAS_U_AXIS && !defined(DEFAULT_UJERK) + #define DEFAULT_UJERK 0 + #endif + #if HAS_V_AXIS && !defined(DEFAULT_VJERK) + #define DEFAULT_VJERK 0 + #endif + #if HAS_W_AXIS && !defined(DEFAULT_WJERK) + #define DEFAULT_WJERK 0 + #endif planner.max_jerk.set( - LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK) + NUM_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK, DEFAULT_UJERK, DEFAULT_VJERK, DEFAULT_WJERK) ); TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK); #endif @@ -2836,7 +2881,7 @@ void MarlinSettings::reset() { #if ENABLED(BACKLASH_GCODE) backlash.set_correction(BACKLASH_CORRECTION); constexpr xyz_float_t tmp = BACKLASH_DISTANCE_MM; - LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]); + LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]); #ifdef BACKLASH_SMOOTHING_MM backlash.set_smoothing_mm(BACKLASH_SMOOTHING_MM); #endif @@ -2881,11 +2926,11 @@ void MarlinSettings::reset() { // #if HAS_BED_PROBE constexpr float dpo[] = NOZZLE_TO_PROBE_OFFSET; - static_assert(COUNT(dpo) == LINEAR_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z...."); + static_assert(COUNT(dpo) == NUM_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z...."); #if HAS_PROBE_XY_OFFSET - LOOP_LINEAR_AXES(a) probe.offset[a] = dpo[a]; + LOOP_NUM_AXES(a) probe.offset[a] = dpo[a]; #else - probe.offset.set(LINEAR_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0)); + probe.offset.set(NUM_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0, 0, 0, 0)); #endif #endif diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index af64d9f8bf1d..5aa7822e202c 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -447,6 +447,18 @@ xyze_int8_t Stepper::count_direction{0}; #define K_APPLY_DIR(v,Q) K_DIR_WRITE(v) #define K_APPLY_STEP(v,Q) K_STEP_WRITE(v) #endif +#if HAS_U_AXIS + #define U_APPLY_DIR(v,Q) U_DIR_WRITE(v) + #define U_APPLY_STEP(v,Q) U_STEP_WRITE(v) +#endif +#if HAS_V_AXIS + #define V_APPLY_DIR(v,Q) V_DIR_WRITE(v) + #define V_APPLY_STEP(v,Q) V_STEP_WRITE(v) +#endif +#if HAS_W_AXIS + #define W_APPLY_DIR(v,Q) W_DIR_WRITE(v) + #define W_APPLY_STEP(v,Q) W_STEP_WRITE(v) +#endif #if DISABLED(MIXING_EXTRUDER) #define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v) @@ -486,9 +498,10 @@ xyze_int8_t Stepper::count_direction{0}; void Stepper::enable_axis(const AxisEnum axis) { #define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break; switch (axis) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( _CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z), - _CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K) + _CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K), + _CASE_ENABLE(U), _CASE_ENABLE(V), _CASE_ENABLE(W) ); default: break; } @@ -505,9 +518,10 @@ bool Stepper::disable_axis(const AxisEnum axis) { if (can_disable) { #define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break; switch (axis) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( _CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z), - _CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K) + _CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K), + _CASE_DISABLE(U), _CASE_DISABLE(V), _CASE_DISABLE(W) ); default: break; } @@ -550,9 +564,10 @@ bool Stepper::disable_axis(const AxisEnum axis) { void Stepper::enable_all_steppers() { TERN_(AUTO_POWER_CONTROL, powerManager.power_on()); - LINEAR_AXIS_CODE( + NUM_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_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS), + enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS) ); enable_e_steppers(); @@ -560,9 +575,10 @@ void Stepper::enable_all_steppers() { } void Stepper::disable_all_steppers() { - LINEAR_AXIS_CODE( + NUM_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_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS), + disable_axis(U_AXIS), disable_axis(V_AXIS), disable_axis(W_AXIS) ); disable_e_steppers(); @@ -596,6 +612,9 @@ void Stepper::set_directions() { TERN_(HAS_I_DIR, SET_STEP_DIR(I)); TERN_(HAS_J_DIR, SET_STEP_DIR(J)); TERN_(HAS_K_DIR, SET_STEP_DIR(K)); + TERN_(HAS_U_DIR, SET_STEP_DIR(U)); + TERN_(HAS_V_DIR, SET_STEP_DIR(V)); + TERN_(HAS_W_DIR, SET_STEP_DIR(W)); #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -1816,6 +1835,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_PREP(K); #endif + #if HAS_U_STEP + PULSE_PREP(U); + #endif + #if HAS_V_STEP + PULSE_PREP(V); + #endif + #if HAS_W_STEP + PULSE_PREP(W); + #endif #if EITHER(LIN_ADVANCE, MIXING_EXTRUDER) delta_error.e += advance_dividend.e; @@ -1860,6 +1888,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_START(K); #endif + #if HAS_U_STEP + PULSE_START(U); + #endif + #if HAS_V_STEP + PULSE_START(V); + #endif + #if HAS_W_STEP + PULSE_START(W); + #endif #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -1898,6 +1935,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_STOP(K); #endif + #if HAS_U_STEP + PULSE_STOP(U); + #endif + #if HAS_V_STEP + PULSE_STOP(V); + #endif + #if HAS_W_STEP + PULSE_STOP(W); + #endif #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -2243,13 +2289,16 @@ uint32_t Stepper::block_phase_isr() { #endif axis_bits_t axis_bits = 0; - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (X_MOVE_TEST) SBI(axis_bits, A_AXIS), if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS), if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS), if (current_block->steps.i) SBI(axis_bits, I_AXIS), if (current_block->steps.j) SBI(axis_bits, J_AXIS), - if (current_block->steps.k) SBI(axis_bits, K_AXIS) + if (current_block->steps.k) SBI(axis_bits, K_AXIS), + if (current_block->steps.u) SBI(axis_bits, U_AXIS), + if (current_block->steps.v) SBI(axis_bits, V_AXIS), + if (current_block->steps.w) SBI(axis_bits, W_AXIS) ); //if (current_block->steps.e) SBI(axis_bits, E_AXIS); //if (current_block->steps.a) SBI(axis_bits, X_HEAD); @@ -2589,6 +2638,15 @@ void Stepper::init() { #if HAS_K_DIR K_DIR_INIT(); #endif + #if HAS_U_DIR + U_DIR_INIT(); + #endif + #if HAS_V_DIR + V_DIR_INIT(); + #endif + #if HAS_W_DIR + W_DIR_INIT(); + #endif #if HAS_E0_DIR E0_DIR_INIT(); #endif @@ -2659,6 +2717,18 @@ void Stepper::init() { K_ENABLE_INIT(); if (!K_ENABLE_ON) K_ENABLE_WRITE(HIGH); #endif + #if HAS_U_ENABLE + U_ENABLE_INIT(); + if (!U_ENABLE_ON) U_ENABLE_WRITE(HIGH); + #endif + #if HAS_V_ENABLE + V_ENABLE_INIT(); + if (!V_ENABLE_ON) V_ENABLE_WRITE(HIGH); + #endif + #if HAS_W_ENABLE + W_ENABLE_INIT(); + if (!W_ENABLE_ON) W_ENABLE_WRITE(HIGH); + #endif #if HAS_E0_ENABLE E0_ENABLE_INIT(); if (!E_ENABLE_ON) E0_ENABLE_WRITE(HIGH); @@ -2744,6 +2814,15 @@ void Stepper::init() { #if HAS_K_STEP AXIS_INIT(K, K); #endif + #if HAS_U_STEP + AXIS_INIT(U, U); + #endif + #if HAS_V_STEP + AXIS_INIT(V, V); + #endif + #if HAS_W_STEP + AXIS_INIT(W, W); + #endif #if E_STEPPERS && HAS_E0_STEP E_AXIS_INIT(0); @@ -2778,13 +2857,16 @@ void Stepper::init() { // Init direction bits for first moves set_directions(0 - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( | TERN0(INVERT_X_DIR, _BV(X_AXIS)), | TERN0(INVERT_Y_DIR, _BV(Y_AXIS)), | TERN0(INVERT_Z_DIR, _BV(Z_AXIS)), | TERN0(INVERT_I_DIR, _BV(I_AXIS)), | TERN0(INVERT_J_DIR, _BV(J_AXIS)), - | TERN0(INVERT_K_DIR, _BV(K_AXIS)) + | TERN0(INVERT_K_DIR, _BV(K_AXIS)), + | TERN0(INVERT_U_DIR, _BV(U_AXIS)), + | TERN0(INVERT_V_DIR, _BV(V_AXIS)), + | TERN0(INVERT_W_DIR, _BV(W_AXIS)) ) ); @@ -2820,6 +2902,14 @@ 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, + count_position.u = spos.u, + count_position.v = spos.v, + count_position.w = spos.w + ); TERN_(HAS_EXTRUDERS, count_position.e = spos.e); #else // default non-h-bot planning @@ -2934,13 +3024,16 @@ int32_t Stepper::triggered_position(const AxisEnum axis) { void Stepper::report_a_position(const xyz_long_t &pos) { SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), TERN(SAYS_A, PSTR(STR_COUNT_A), PSTR(STR_COUNT_X)), pos.x, TERN(SAYS_B, PSTR("B:"), SP_Y_LBL), pos.y, TERN(SAYS_C, PSTR("C:"), SP_Z_LBL), pos.z, SP_I_LBL, pos.i, SP_J_LBL, pos.j, - SP_K_LBL, pos.k + SP_K_LBL, pos.k, + SP_U_LBL, pos.u, + SP_V_LBL, pos.v, + SP_W_LBL, pos.w ) ); } @@ -3091,16 +3184,18 @@ void Stepper::report_positions() { const bool z_direction = direction ^ BABYSTEP_INVERT_Z; - LINEAR_AXIS_CODE( + NUM_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_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS), + enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS) ); DIR_WAIT_BEFORE(); - const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY( + const xyz_byte_t old_dir = NUM_AXIS_ARRAY( X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ(), - I_DIR_READ(), J_DIR_READ(), K_DIR_READ() + I_DIR_READ(), J_DIR_READ(), K_DIR_READ(), + U_DIR_READ(), V_DIR_READ(), W_DIR_READ() ); X_DIR_WRITE(INVERT_X_DIR ^ z_direction); @@ -3119,6 +3214,15 @@ void Stepper::report_positions() { #ifdef K_DIR_WRITE K_DIR_WRITE(INVERT_K_DIR ^ z_direction); #endif + #ifdef U_DIR_WRITE + U_DIR_WRITE(INVERT_U_DIR ^ z_direction); + #endif + #ifdef V_DIR_WRITE + V_DIR_WRITE(INVERT_V_DIR ^ z_direction); + #endif + #ifdef W_DIR_WRITE + W_DIR_WRITE(INVERT_W_DIR ^ z_direction); + #endif DIR_WAIT_AFTER(); @@ -3140,6 +3244,15 @@ void Stepper::report_positions() { #ifdef K_STEP_WRITE K_STEP_WRITE(!INVERT_K_STEP_PIN); #endif + #ifdef U_STEP_WRITE + U_STEP_WRITE(!INVERT_U_STEP_PIN); + #endif + #ifdef V_STEP_WRITE + V_STEP_WRITE(!INVERT_V_STEP_PIN); + #endif + #ifdef W_STEP_WRITE + W_STEP_WRITE(!INVERT_W_STEP_PIN); + #endif _PULSE_WAIT(); @@ -3159,6 +3272,15 @@ void Stepper::report_positions() { #ifdef K_STEP_WRITE K_STEP_WRITE(INVERT_K_STEP_PIN); #endif + #ifdef U_STEP_WRITE + U_STEP_WRITE(INVERT_U_STEP_PIN); + #endif + #ifdef V_STEP_WRITE + V_STEP_WRITE(INVERT_V_STEP_PIN); + #endif + #ifdef W_STEP_WRITE + W_STEP_WRITE(INVERT_W_STEP_PIN); + #endif // Restore direction bits EXTRA_DIR_WAIT_BEFORE(); @@ -3179,6 +3301,15 @@ void Stepper::report_positions() { #ifdef K_DIR_WRITE K_DIR_WRITE(old_dir.k); #endif + #ifdef U_DIR_WRITE + U_DIR_WRITE(old_dir.u); + #endif + #ifdef V_DIR_WRITE + V_DIR_WRITE(old_dir.v); + #endif + #ifdef W_DIR_WRITE + W_DIR_WRITE(old_dir.w); + #endif EXTRA_DIR_WAIT_AFTER(); @@ -3195,6 +3326,15 @@ void Stepper::report_positions() { #if HAS_K_AXIS case K_AXIS: BABYSTEP_AXIS(K, 0, direction); break; #endif + #if HAS_U_AXIS + case U_AXIS: BABYSTEP_AXIS(U, 0, direction); break; + #endif + #if HAS_V_AXIS + case V_AXIS: BABYSTEP_AXIS(V, 0, direction); break; + #endif + #if HAS_W_AXIS + case W_AXIS: BABYSTEP_AXIS(W, 0, direction); break; + #endif default: break; } @@ -3423,6 +3563,24 @@ void Stepper::report_positions() { SET_OUTPUT(K_MS3_PIN); #endif #endif + #if HAS_U_MS_PINS + SET_OUTPUT(U_MS1_PIN); SET_OUTPUT(U_MS2_PIN); + #if PIN_EXISTS(U_MS3) + SET_OUTPUT(U_MS3_PIN); + #endif + #endif + #if HAS_V_MS_PINS + SET_OUTPUT(V_MS1_PIN); SET_OUTPUT(V_MS2_PIN); + #if PIN_EXISTS(V_MS3) + SET_OUTPUT(V_MS3_PIN); + #endif + #endif + #if HAS_W_MS_PINS + SET_OUTPUT(W_MS1_PIN); SET_OUTPUT(W_MS2_PIN); + #if PIN_EXISTS(W_MS3) + SET_OUTPUT(W_MS3_PIN); + #endif + #endif #if HAS_E0_MS_PINS SET_OUTPUT(E0_MS1_PIN); SET_OUTPUT(E0_MS2_PIN); #if PIN_EXISTS(E0_MS3) @@ -3548,6 +3706,15 @@ void Stepper::report_positions() { #if HAS_K_MS_PINS case 13: WRITE(K_MS1_PIN, ms1); break #endif + #if HAS_U_MS_PINS + case 14: WRITE(U_MS1_PIN, ms1); break + #endif + #if HAS_V_MS_PINS + case 15: WRITE(V_MS1_PIN, ms1); break + #endif + #if HAS_W_MS_PINS + case 16: WRITE(W_MS1_PIN, ms1); break + #endif } if (ms2 >= 0) switch (driver) { #if HAS_X_MS_PINS || HAS_X2_MS_PINS @@ -3619,6 +3786,15 @@ void Stepper::report_positions() { #if HAS_K_MS_PINS case 13: WRITE(K_MS2_PIN, ms2); break #endif + #if HAS_U_MS_PINS + case 14: WRITE(U_MS2_PIN, ms2); break + #endif + #if HAS_V_MS_PINS + case 15: WRITE(V_MS2_PIN, ms2); break + #endif + #if HAS_W_MS_PINS + case 16: WRITE(W_MS2_PIN, ms2); break + #endif } if (ms3 >= 0) switch (driver) { #if HAS_X_MS_PINS || HAS_X2_MS_PINS @@ -3755,6 +3931,24 @@ void Stepper::report_positions() { PIN_CHAR(K_MS3); #endif #endif + #if HAS_U_MS_PINS + MS_LINE(U); + #if PIN_EXISTS(U_MS3) + PIN_CHAR(U_MS3); + #endif + #endif + #if HAS_V_MS_PINS + MS_LINE(V); + #if PIN_EXISTS(V_MS3) + PIN_CHAR(V_MS3); + #endif + #endif + #if HAS_W_MS_PINS + MS_LINE(W); + #if PIN_EXISTS(W_MS3) + PIN_CHAR(W_MS3); + #endif + #endif #if HAS_E0_MS_PINS MS_LINE(E0); #if PIN_EXISTS(E0_MS3) diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 4c9fbb9556b9..8cc8610fd4ca 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -159,12 +159,21 @@ #if HAS_K_STEP #define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES #endif +#if HAS_U_STEP + #define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif +#if HAS_V_STEP + #define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif +#if HAS_W_STEP + #define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif #if HAS_EXTRUDERS #define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders #endif // And the total minimum loop time, not including the base -#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES)) +#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES, + ISR_U_STEPPER_CYCLES, + ISR_V_STEPPER_CYCLES, + ISR_W_STEPPER_CYCLES)) // Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate #define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N)) @@ -236,7 +245,7 @@ // 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) +#define ENABLE_COUNT (NUM_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 @@ -244,25 +253,25 @@ typedef struct { union { ena_mask_t bits; struct { - bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1); + bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W: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; } + constexpr ena_mask_t linear_bits() { return _BV(NUM_AXES) - 1; } + constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << NUM_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), + NUM_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN, U_ENABLE_PIN, V_ENABLE_PIN, W_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)); + return uint8_t(axis) + (E_TERN0(axis < NUM_AXES ? 0 : eindex)); } //#define __IAX_N(N,V...) _IAX_##N(V) //#define _IAX_N(N,V...) __IAX_N(N,V) @@ -292,7 +301,7 @@ constexpr bool any_enable_overlap(const uint8_t a=0) { // (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) + REPEAT(NUM_AXES, _OVERLAP) #if HAS_EXTRUDERS #define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)), REPEAT(E_STEPPERS, _E_OVERLAP) @@ -320,7 +329,7 @@ class Stepper { #ifndef MOTOR_CURRENT_PWM_FREQUENCY #define MOTOR_CURRENT_PWM_FREQUENCY 31400 #endif - #define MOTOR_CURRENT_COUNT LINEAR_AXES + #define MOTOR_CURRENT_COUNT NUM_AXES #elif HAS_MOTOR_CURRENT_SPI static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT; #define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count) diff --git a/Marlin/src/module/stepper/L64xx.cpp b/Marlin/src/module/stepper/L64xx.cpp index 27816fb4f742..5b607463969f 100644 --- a/Marlin/src/module/stepper/L64xx.cpp +++ b/Marlin/src/module/stepper/L64xx.cpp @@ -64,6 +64,15 @@ #if AXIS_IS_L64XX(K) L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN); #endif +#if AXIS_IS_L64XX(U) + L64XX_CLASS(u) stepperU(L6470_CHAIN_SS_PIN); +#endif +#if AXIS_IS_L64XX(V) + L64XX_CLASS(v) stepperV(L6470_CHAIN_SS_PIN); +#endif +#if AXIS_IS_L64XX(W) + L64XX_CLASS(w) stepperW(L6470_CHAIN_SS_PIN); +#endif #if AXIS_IS_L64XX(E0) L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN); #endif @@ -217,6 +226,15 @@ void L64XX_Marlin::init_to_defaults() { #if AXIS_IS_L64XX(K) L6470_INIT_CHIP(K); #endif + #if AXIS_IS_L64XX(U) + L6470_INIT_CHIP(U); + #endif + #if AXIS_IS_L64XX(V) + L6470_INIT_CHIP(V); + #endif + #if AXIS_IS_L64XX(W) + L6470_INIT_CHIP(W); + #endif #if AXIS_IS_L64XX(E0) L6470_INIT_CHIP(E0); #endif diff --git a/Marlin/src/module/stepper/L64xx.h b/Marlin/src/module/stepper/L64xx.h index 9f7e6623b140..870b0414f8eb 100644 --- a/Marlin/src/module/stepper/L64xx.h +++ b/Marlin/src/module/stepper/L64xx.h @@ -266,6 +266,72 @@ #endif #endif +// U Stepper +#if HAS_U_AXIS + #if AXIS_IS_L64XX(U) + extern L64XX_CLASS(U) stepperU; + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) (STATE ? stepperU.hardStop() : stepperU.free()) + #define U_ENABLE_READ() (stepperU.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_U(L6474) + #define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN) + #define U_DIR_WRITE(STATE) L6474_DIR_WRITE(U, STATE) + #define U_DIR_READ() READ(U_DIR_PIN) + #else + #define U_DIR_INIT() NOOP + #define U_DIR_WRITE(STATE) L64XX_DIR_WRITE(U, STATE) + #define U_DIR_READ() (stepper##U.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_U(L6470) + #define DISABLE_STEPPER_U() stepperU.free() + #endif + #endif + #endif +#endif + +// V Stepper +#if HAS_V_AXIS + #if AXIS_IS_L64XX(V) + extern L64XX_CLASS(V) stepperV; + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) (STATE ? stepperV.hardStop() : stepperV.free()) + #define V_ENABLE_READ() (stepperV.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_V(L6474) + #define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN) + #define V_DIR_WRITE(STATE) L6474_DIR_WRITE(V, STATE) + #define V_DIR_READ() READ(V_DIR_PIN) + #else + #define V_DIR_INIT() NOOP + #define V_DIR_WRITE(STATE) L64XX_DIR_WRITE(V, STATE) + #define V_DIR_READ() (stepper##V.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_V(L6470) + #define DISABLE_STEPPER_V() stepperV.free() + #endif + #endif + #endif +#endif + +// W Stepper +#if HAS_W_AXIS + #if AXIS_IS_L64XX(W) + extern L64XX_CLASS(w) stepperW; + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) (STATE ? stepperW.hardStop() : stepperW.free()) + #define W_ENABLE_READ() (stepperW.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_W(L6474) + #define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN) + #define W_DIR_WRITE(STATE) L6474_DIR_WRITE(W, STATE) + #define W_DIR_READ() READ(W_DIR_PIN) + #else + #define W_DIR_INIT() NOOP + #define W_DIR_WRITE(STATE) L64XX_DIR_WRITE(W, STATE) + #define W_DIR_READ() (stepper##W.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_W(L6470) + #define DISABLE_STEPPER_W() stepperW.free() + #endif + #endif + #endif +#endif + // E0 Stepper #if AXIS_IS_L64XX(E0) extern L64XX_CLASS(E0) stepperE0; diff --git a/Marlin/src/module/stepper/TMC26X.cpp b/Marlin/src/module/stepper/TMC26X.cpp index 26f91bfeb9da..52d84f84101c 100644 --- a/Marlin/src/module/stepper/TMC26X.cpp +++ b/Marlin/src/module/stepper/TMC26X.cpp @@ -69,6 +69,15 @@ #if AXIS_DRIVER_TYPE_K(TMC26X) _TMC26X_DEFINE(K); #endif +#if AXIS_DRIVER_TYPE_U(TMC26X) + _TMC26X_DEFINE(U); +#endif +#if AXIS_DRIVER_TYPE_V(TMC26X) + _TMC26X_DEFINE(V); +#endif +#if AXIS_DRIVER_TYPE_W(TMC26X) + _TMC26X_DEFINE(W); +#endif #if AXIS_DRIVER_TYPE_E0(TMC26X) _TMC26X_DEFINE(E0); #endif @@ -133,6 +142,15 @@ void tmc26x_init_to_defaults() { #if AXIS_DRIVER_TYPE_K(TMC26X) _TMC26X_INIT(K); #endif + #if AXIS_DRIVER_TYPE_U(TMC26X) + _TMC26X_INIT(U); + #endif + #if AXIS_DRIVER_TYPE_V(TMC26X) + _TMC26X_INIT(V); + #endif + #if AXIS_DRIVER_TYPE_W(TMC26X) + _TMC26X_INIT(W); + #endif #if AXIS_DRIVER_TYPE_E0(TMC26X) _TMC26X_INIT(E0); #endif diff --git a/Marlin/src/module/stepper/TMC26X.h b/Marlin/src/module/stepper/TMC26X.h index 988bebe0f20f..1fd94b26a8d8 100644 --- a/Marlin/src/module/stepper/TMC26X.h +++ b/Marlin/src/module/stepper/TMC26X.h @@ -123,6 +123,30 @@ void tmc26x_init_to_defaults(); #define K_ENABLE_READ() stepperK.isEnabled() #endif +// U Stepper +#if HAS_U_ENABLE && AXIS_DRIVER_TYPE_U(TMC26X) + extern TMC26XStepper stepperU; + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) stepperU.setEnabled(STATE) + #define U_ENABLE_READ() stepperU.isEnabled() +#endif + +// V Stepper +#if HAS_V_ENABLE && AXIS_DRIVER_TYPE_V(TMC26X) + extern TMC26XStepper stepperV; + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) stepperV.setEnabled(STATE) + #define V_ENABLE_READ() stepperV.isEnabled() +#endif + +// W Stepper +#if HAS_W_ENABLE && AXIS_DRIVER_TYPE_W(TMC26X) + extern TMC26XStepper stepperW; + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) stepperW.setEnabled(STATE) + #define W_ENABLE_READ() stepperW.isEnabled() +#endif + // E0 Stepper #if AXIS_DRIVER_TYPE_E0(TMC26X) extern TMC26XStepper stepperE0; diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h index 7aea67753403..879185ca14ef 100644 --- a/Marlin/src/module/stepper/indirection.h +++ b/Marlin/src/module/stepper/indirection.h @@ -262,6 +262,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define K_STEP_READ() bool(READ(K_STEP_PIN)) #endif +// U Stepper +#if HAS_U_AXIS + #ifndef U_ENABLE_INIT + #define U_ENABLE_INIT() SET_OUTPUT(U_ENABLE_PIN) + #define U_ENABLE_WRITE(STATE) WRITE(U_ENABLE_PIN,STATE) + #define U_ENABLE_READ() bool(READ(U_ENABLE_PIN)) + #endif + #ifndef U_DIR_INIT + #define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN) + #define U_DIR_WRITE(STATE) WRITE(U_DIR_PIN,STATE) + #define U_DIR_READ() bool(READ(U_DIR_PIN)) + #endif + #define U_STEP_INIT() SET_OUTPUT(U_STEP_PIN) + #ifndef U_STEP_WRITE + #define U_STEP_WRITE(STATE) WRITE(U_STEP_PIN,STATE) + #endif + #define U_STEP_READ() bool(READ(U_STEP_PIN)) +#endif + +// V Stepper +#if HAS_V_AXIS + #ifndef V_ENABLE_INIT + #define V_ENABLE_INIT() SET_OUTPUT(V_ENABLE_PIN) + #define V_ENABLE_WRITE(STATE) WRITE(V_ENABLE_PIN,STATE) + #define V_ENABLE_READ() bool(READ(V_ENABLE_PIN)) + #endif + #ifndef V_DIR_INIT + #define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN) + #define V_DIR_WRITE(STATE) WRITE(V_DIR_PIN,STATE) + #define V_DIR_READ() bool(READ(V_DIR_PIN)) + #endif + #define V_STEP_INIT() SET_OUTPUT(V_STEP_PIN) + #ifndef V_STEP_WRITE + #define V_STEP_WRITE(STATE) WRITE(V_STEP_PIN,STATE) + #endif + #define V_STEP_READ() bool(READ(V_STEP_PIN)) +#endif + +// W Stepper +#if HAS_W_AXIS + #ifndef W_ENABLE_INIT + #define W_ENABLE_INIT() SET_OUTPUT(W_ENABLE_PIN) + #define W_ENABLE_WRITE(STATE) WRITE(W_ENABLE_PIN,STATE) + #define W_ENABLE_READ() bool(READ(W_ENABLE_PIN)) + #endif + #ifndef W_DIR_INIT + #define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN) + #define W_DIR_WRITE(STATE) WRITE(W_DIR_PIN,STATE) + #define W_DIR_READ() bool(READ(W_DIR_PIN)) + #endif + #define W_STEP_INIT() SET_OUTPUT(W_STEP_PIN) + #ifndef W_STEP_WRITE + #define W_STEP_WRITE(STATE) WRITE(W_STEP_PIN,STATE) + #endif + #define W_STEP_READ() bool(READ(W_STEP_PIN)) +#endif + // E0 Stepper #ifndef E0_ENABLE_INIT #define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN) @@ -743,6 +800,51 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP) #endif +#ifndef ENABLE_STEPPER_U + #if HAS_U_ENABLE + #define ENABLE_STEPPER_U() U_ENABLE_WRITE( U_ENABLE_ON) + #else + #define ENABLE_STEPPER_U() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_U + #if HAS_U_ENABLE + #define DISABLE_STEPPER_U() U_ENABLE_WRITE(!U_ENABLE_ON) + #else + #define DISABLE_STEPPER_U() NOOP + #endif +#endif + +#ifndef ENABLE_STEPPER_V + #if HAS_V_ENABLE + #define ENABLE_STEPPER_V() V_ENABLE_WRITE( V_ENABLE_ON) + #else + #define ENABLE_STEPPER_V() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_V + #if HAS_V_ENABLE + #define DISABLE_STEPPER_V() V_ENABLE_WRITE(!V_ENABLE_ON) + #else + #define DISABLE_STEPPER_V() NOOP + #endif +#endif + +#ifndef ENABLE_STEPPER_W + #if HAS_W_ENABLE + #define ENABLE_STEPPER_W() W_ENABLE_WRITE( W_ENABLE_ON) + #else + #define ENABLE_STEPPER_W() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_W + #if HAS_W_ENABLE + #define DISABLE_STEPPER_W() W_ENABLE_WRITE(!W_ENABLE_ON) + #else + #define DISABLE_STEPPER_W() NOOP + #endif +#endif + #ifndef ENABLE_STEPPER_E0 #define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP) #endif @@ -917,6 +1019,28 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define DISABLE_AXIS_K() NOOP #endif +#if HAS_U_AXIS + #define ENABLE_AXIS_U() if (SHOULD_ENABLE(u)) { ENABLE_STEPPER_U(); AFTER_CHANGE(u, true); } + #define DISABLE_AXIS_U() if (SHOULD_DISABLE(u)) { DISABLE_STEPPER_U(); AFTER_CHANGE(u, false); set_axis_untrusted(U_AXIS); } +#else + #define ENABLE_AXIS_U() NOOP + #define DISABLE_AXIS_U() NOOP +#endif +#if HAS_V_AXIS + #define ENABLE_AXIS_V() if (SHOULD_ENABLE(v)) { ENABLE_STEPPER_V(); AFTER_CHANGE(v, true); } + #define DISABLE_AXIS_V() if (SHOULD_DISABLE(v)) { DISABLE_STEPPER_V(); AFTER_CHANGE(v, false); set_axis_untrusted(V_AXIS); } +#else + #define ENABLE_AXIS_V() NOOP + #define DISABLE_AXIS_V() NOOP +#endif +#if HAS_W_AXIS + #define ENABLE_AXIS_W() if (SHOULD_ENABLE(w)) { ENABLE_STEPPER_W(); AFTER_CHANGE(w, true); } + #define DISABLE_AXIS_W() if (SHOULD_DISABLE(w)) { DISABLE_STEPPER_W(); AFTER_CHANGE(w, false); set_axis_untrusted(W_AXIS); } +#else + #define ENABLE_AXIS_W() NOOP + #define DISABLE_AXIS_W() NOOP +#endif + // // Extruder steppers enable / disable macros // diff --git a/Marlin/src/module/stepper/trinamic.cpp b/Marlin/src/module/stepper/trinamic.cpp index af09623dc1bb..ee156a198629 100644 --- a/Marlin/src/module/stepper/trinamic.cpp +++ b/Marlin/src/module/stepper/trinamic.cpp @@ -36,7 +36,7 @@ #include enum StealthIndex : uint8_t { - LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K) + LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K, STEALTH_AXIS_U, STEALTH_AXIS_V, STEALTH_AXIS_W) }; #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE, ST##_HOLD_MULTIPLIER) @@ -106,6 +106,15 @@ enum StealthIndex : uint8_t { #if AXIS_HAS_SPI(K) TMC_SPI_DEFINE(K, K); #endif +#if AXIS_HAS_SPI(U) + TMC_SPI_DEFINE(U, U); +#endif +#if AXIS_HAS_SPI(V) + TMC_SPI_DEFINE(V, V); +#endif +#if AXIS_HAS_SPI(W) + TMC_SPI_DEFINE(W, W); +#endif #if AXIS_HAS_SPI(E0) TMC_SPI_DEFINE_E(0); #endif @@ -173,6 +182,15 @@ enum StealthIndex : uint8_t { #ifndef TMC_K_BAUD_RATE #define TMC_K_BAUD_RATE TMC_BAUD_RATE #endif +#ifndef TMC_U_BAUD_RATE + #define TMC_U_BAUD_RATE TMC_BAUD_RATE +#endif +#ifndef TMC_V_BAUD_RATE + #define TMC_V_BAUD_RATE TMC_BAUD_RATE +#endif +#ifndef TMC_W_BAUD_RATE + #define TMC_W_BAUD_RATE TMC_BAUD_RATE +#endif #ifndef TMC_E0_BAUD_RATE #define TMC_E0_BAUD_RATE TMC_BAUD_RATE #endif @@ -374,6 +392,32 @@ enum StealthIndex : uint8_t { #define K_HAS_SW_SERIAL 1 #endif #endif + #if AXIS_HAS_UART(U) + #ifdef U_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, U, U); + #define U_HAS_HW_SERIAL 1 + #else + TMC_UART_DEFINE(SW, U, U); + #define U_HAS_SW_SERIAL 1 + #endif + #endif + #if AXIS_HAS_UART(V) + #ifdef V_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, V, V); + #else + TMC_UART_DEFINE(SW, V, V); + #define V_HAS_SW_SERIAL 1 + #endif + #endif + #if AXIS_HAS_UART(W) + #ifdef W_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, W, W); + #define W_HAS_HW_SERIAL 1 + #else + TMC_UART_DEFINE(SW, W, W); + #define W_HAS_SW_SERIAL 1 + #endif + #endif #if AXIS_HAS_UART(E0) #ifdef E0_HARDWARE_SERIAL @@ -449,7 +493,7 @@ enum StealthIndex : uint8_t { #endif #define _EN_ITEM(N) , E##N - enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL }; + enum TMCAxis : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL }; #undef _EN_ITEM void tmc_serial_begin() { @@ -543,6 +587,27 @@ enum StealthIndex : uint8_t { stepperK.beginSerial(TMC_BAUD_RATE); #endif #endif + #if AXIS_HAS_UART(U) + #ifdef U_HARDWARE_SERIAL + HW_SERIAL_BEGIN(U); + #else + stepperU.beginSerial(TMC_BAUD_RATE); + #endif + #endif + #if AXIS_HAS_UART(V) + #ifdef V_HARDWARE_SERIAL + HW_SERIAL_BEGIN(V); + #else + stepperV.beginSerial(TMC_BAUD_RATE); + #endif + #endif + #if AXIS_HAS_UART(W) + #ifdef W_HARDWARE_SERIAL + HW_SERIAL_BEGIN(W); + #else + stepperW.beginSerial(TMC_BAUD_RATE); + #endif + #endif #if AXIS_HAS_UART(E0) #ifdef E0_HARDWARE_SERIAL HW_SERIAL_BEGIN(E0); @@ -814,6 +879,15 @@ void restore_trinamic_drivers() { #if AXIS_IS_TMC(K) stepperK.push(); #endif + #if AXIS_IS_TMC(U) + stepperU.push(); + #endif + #if AXIS_IS_TMC(V) + stepperV.push(); + #endif + #if AXIS_IS_TMC(W) + stepperW.push(); + #endif #if AXIS_IS_TMC(E0) stepperE0.push(); #endif @@ -844,7 +918,8 @@ void reset_trinamic_drivers() { static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY( ENABLED(STEALTHCHOP_E), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z), - ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K) + ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K), + ENABLED(STEALTHCHOP_U), ENABLED(STEALTHCHOP_V), ENABLED(STEALTHCHOP_W) ); #if AXIS_IS_TMC(X) @@ -880,6 +955,15 @@ void reset_trinamic_drivers() { #if AXIS_IS_TMC(K) TMC_INIT(K, STEALTH_AXIS_K); #endif + #if AXIS_IS_TMC(U) + TMC_INIT(U, STEALTH_AXIS_U); + #endif + #if AXIS_IS_TMC(V) + TMC_INIT(V, STEALTH_AXIS_V); + #endif + #if AXIS_IS_TMC(W) + TMC_INIT(W, STEALTH_AXIS_W); + #endif #if AXIS_IS_TMC(E0) TMC_INIT(E0, STEALTH_AXIS_E); #endif @@ -917,6 +1001,9 @@ void reset_trinamic_drivers() { TERN_(I_SENSORLESS, stepperI.homing_threshold(I_STALL_SENSITIVITY)); TERN_(J_SENSORLESS, stepperJ.homing_threshold(J_STALL_SENSITIVITY)); TERN_(K_SENSORLESS, stepperK.homing_threshold(K_STALL_SENSITIVITY)); + TERN_(U_SENSORLESS, stepperU.homing_threshold(U_STALL_SENSITIVITY)); + TERN_(V_SENSORLESS, stepperV.homing_threshold(V_STALL_SENSITIVITY)); + TERN_(W_SENSORLESS, stepperW.homing_threshold(W_STALL_SENSITIVITY)); #endif #ifdef TMC_ADV @@ -946,7 +1033,7 @@ void reset_trinamic_drivers() { TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2), TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2), TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4), - TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), + TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), TMC_HW_DETAIL(U), TMC_HW_DETAIL(V), TMC_HW_DETAIL(W), TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7) }; @@ -969,7 +1056,7 @@ void reset_trinamic_drivers() { SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2); SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2); SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4); - SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); + SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); SA_NO_TMC_HW_C(U); SA_NO_TMC_HW_C(V); SA_NO_TMC_HW_C(W); SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7); #endif @@ -981,7 +1068,7 @@ void reset_trinamic_drivers() { TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2), TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2), TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4), - TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), + TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), TMC_SW_DETAIL(U), TMC_SW_DETAIL(V), TMC_SW_DETAIL(W), TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7) }; @@ -999,7 +1086,7 @@ void reset_trinamic_drivers() { SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2); SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2); SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4); - SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); + SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); SA_NO_TMC_SW_C(U); SA_NO_TMC_SW_C(V); SA_NO_TMC_SW_C(W); SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7); #endif diff --git a/Marlin/src/module/stepper/trinamic.h b/Marlin/src/module/stepper/trinamic.h index dd3a64240f20..95bab7652c1a 100644 --- a/Marlin/src/module/stepper/trinamic.h +++ b/Marlin/src/module/stepper/trinamic.h @@ -49,6 +49,9 @@ #define TMC_I_LABEL 'I', '0' #define TMC_J_LABEL 'J', '0' #define TMC_K_LABEL 'K', '0' +#define TMC_U_LABEL 'U', '0' +#define TMC_V_LABEL 'V', '0' +#define TMC_W_LABEL 'W', '0' #define TMC_X2_LABEL 'X', '2' #define TMC_Y2_LABEL 'Y', '2' @@ -92,6 +95,15 @@ #if HAS_K_AXIS && !defined(CHOPPER_TIMING_K) #define CHOPPER_TIMING_K CHOPPER_TIMING #endif +#if HAS_U_AXIS && !defined(CHOPPER_TIMING_U) + #define CHOPPER_TIMING_U CHOPPER_TIMING +#endif +#if HAS_V_AXIS && !defined(CHOPPER_TIMING_V) + #define CHOPPER_TIMING_V CHOPPER_TIMING +#endif +#if HAS_W_AXIS && !defined(CHOPPER_TIMING_W) + #define CHOPPER_TIMING_W CHOPPER_TIMING +#endif #if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E) #define CHOPPER_TIMING_E CHOPPER_TIMING #endif @@ -274,6 +286,48 @@ void reset_trinamic_drivers(); #endif #endif +// U Stepper +#if AXIS_IS_TMC(U) + extern TMC_CLASS(U, U) stepperU; + static constexpr chopper_timing_t chopper_timing_U = CHOPPER_TIMING_U; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) stepperU.toff((STATE)==U_ENABLE_ON ? chopper_timing_U.toff : 0) + #define U_ENABLE_READ() stepperU.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(U) + #define U_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(U_STEP_PIN); }while(0) + #endif +#endif + +// V Stepper +#if AXIS_IS_TMC(V) + extern TMC_CLASS(V, V) stepperV; + static constexpr chopper_timing_t chopper_timing_V = CHOPPER_TIMING_V; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) stepperV.toff((STATE)==V_ENABLE_ON ? chopper_timing_V.toff : 0) + #define V_ENABLE_READ() stepperV.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(V) + #define V_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(V_STEP_PIN); }while(0) + #endif +#endif + +// W Stepper +#if AXIS_IS_TMC(W) + extern TMC_CLASS(W, W) stepperW; + static constexpr chopper_timing_t chopper_timing_W = CHOPPER_TIMING_W; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) stepperW.toff((STATE)==W_ENABLE_ON ? chopper_timing_W.toff : 0) + #define W_ENABLE_READ() stepperW.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(W) + #define W_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(W_STEP_PIN); }while(0) + #endif +#endif + // E0 Stepper #if AXIS_IS_TMC(E0) extern TMC_CLASS_E(0) stepperE0; diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 26815642db02..8a62d00782d5 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -926,6 +926,16 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. if (ok) { IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x); IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y); + #if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY) + SECONDARY_AXIS_CODE( + current_position.i = toolchange_settings.change_point.i, + current_position.j = toolchange_settings.change_point.j, + current_position.k = toolchange_settings.change_point.k, + current_position.u = toolchange_settings.change_point.u, + current_position.v = toolchange_settings.change_point.v, + current_position.w = toolchange_settings.change_point.w, + ); + #endif planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), active_extruder); planner.synchronize(); } @@ -1121,6 +1131,16 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { if (can_move_away && toolchange_settings.enable_park) { IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x); IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y); + #if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY) + SECONDARY_AXIS_CODE( + current_position.i = toolchange_settings.change_point.i, + current_position.j = toolchange_settings.change_point.j, + current_position.k = toolchange_settings.change_point.k, + current_position.u = toolchange_settings.change_point.u, + current_position.v = toolchange_settings.change_point.v, + current_position.w = toolchange_settings.change_point.w, + ); + #endif planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), old_tool); planner.synchronize(); } @@ -1175,7 +1195,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { sync_plan_position(); #if ENABLED(DELTA) - //LOOP_LINEAR_AXES(i) update_software_endstops(i); // or modify the constrain function + //LOOP_NUM_AXES(i) update_software_endstops(i); // or modify the constrain function const bool safe_to_move = current_position.z < delta_clip_start_height - 1; #else constexpr bool safe_to_move = true; diff --git a/Marlin/src/module/tool_change.h b/Marlin/src/module/tool_change.h index bbdc0b686278..82ed0d610566 100644 --- a/Marlin/src/module/tool_change.h +++ b/Marlin/src/module/tool_change.h @@ -34,7 +34,7 @@ #endif #if ENABLED(TOOLCHANGE_PARK) bool enable_park; - xy_pos_t change_point; + xyz_pos_t change_point; #endif float z_raise; } toolchange_settings_t; diff --git a/Marlin/src/pins/pinsDebug_list.h b/Marlin/src/pins/pinsDebug_list.h index d7e84b996605..8969997e9a54 100644 --- a/Marlin/src/pins/pinsDebug_list.h +++ b/Marlin/src/pins/pinsDebug_list.h @@ -1547,6 +1547,105 @@ #if PIN_EXISTS(K_STOP) REPORT_NAME_DIGITAL(__LINE__, K_STOP_PIN) #endif +#if PIN_EXISTS(U_ATT) + REPORT_NAME_DIGITAL(__LINE__, U_ATT_PIN) +#endif +#if PIN_EXISTS(U_CS) + REPORT_NAME_DIGITAL(__LINE__, U_CS_PIN) +#endif +#if PIN_EXISTS(U_DIR) + REPORT_NAME_DIGITAL(__LINE__, U_DIR_PIN) +#endif +#if PIN_EXISTS(U_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, U_ENABLE_PIN) +#endif +#if PIN_EXISTS(U_MAX) + REPORT_NAME_DIGITAL(__LINE__, U_MAX_PIN) +#endif +#if PIN_EXISTS(U_MIN) + REPORT_NAME_DIGITAL(__LINE__, U_MIN_PIN) +#endif +#if PIN_EXISTS(U_MS1) + REPORT_NAME_DIGITAL(__LINE__, U_MS1_PIN) +#endif +#if PIN_EXISTS(U_MS2) + REPORT_NAME_DIGITAL(__LINE__, U_MS2_PIN) +#endif +#if PIN_EXISTS(U_MS3) + REPORT_NAME_DIGITAL(__LINE__, U_MS3_PIN) +#endif +#if PIN_EXISTS(U_STEP) + REPORT_NAME_DIGITAL(__LINE__, U_STEP_PIN) +#endif +#if PIN_EXISTS(U_STOP) + REPORT_NAME_DIGITAL(__LINE__, U_STOP_PIN) +#endif +#if PIN_EXISTS(V_ATT) + REPORT_NAME_DIGITAL(__LINE__, V_ATT_PIN) +#endif +#if PIN_EXISTS(V_CS) + REPORT_NAME_DIGITAL(__LINE__, V_CS_PIN) +#endif +#if PIN_EXISTS(V_DIR) + REPORT_NAME_DIGITAL(__LINE__, V_DIR_PIN) +#endif +#if PIN_EXISTS(V_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, V_ENABLE_PIN) +#endif +#if PIN_EXISTS(V_MAX) + REPORT_NAME_DIGITAL(__LINE__, V_MAX_PIN) +#endif +#if PIN_EXISTS(V_MIN) + REPORT_NAME_DIGITAL(__LINE__, V_MIN_PIN) +#endif +#if PIN_EXISTS(V_MS1) + REPORT_NAME_DIGITAL(__LINE__, V_MS1_PIN) +#endif +#if PIN_EXISTS(V_MS2) + REPORT_NAME_DIGITAL(__LINE__, V_MS2_PIN) +#endif +#if PIN_EXISTS(V_MS3) + REPORT_NAME_DIGITAL(__LINE__, V_MS3_PIN) +#endif +#if PIN_EXISTS(V_STEP) + REPORT_NAME_DIGITAL(__LINE__, V_STEP_PIN) +#endif +#if PIN_EXISTS(V_STOP) + REPORT_NAME_DIGITAL(__LINE__, V_STOP_PIN) +#endif +#if PIN_EXISTS(W_ATT) + REPORT_NAME_DIGITAL(__LINE__, W_ATT_PIN) +#endif +#if PIN_EXISTS(W_CS) + REPORT_NAME_DIGITAL(__LINE__, W_CS_PIN) +#endif +#if PIN_EXISTS(W_DIR) + REPORT_NAME_DIGITAL(__LINE__, W_DIR_PIN) +#endif +#if PIN_EXISTS(W_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, W_ENABLE_PIN) +#endif +#if PIN_EXISTS(W_MAX) + REPORT_NAME_DIGITAL(__LINE__, W_MAX_PIN) +#endif +#if PIN_EXISTS(W_MIN) + REPORT_NAME_DIGITAL(__LINE__, W_MIN_PIN) +#endif +#if PIN_EXISTS(W_MS1) + REPORT_NAME_DIGITAL(__LINE__, W_MS1_PIN) +#endif +#if PIN_EXISTS(W_MS2) + REPORT_NAME_DIGITAL(__LINE__, W_MS2_PIN) +#endif +#if PIN_EXISTS(W_MS3) + REPORT_NAME_DIGITAL(__LINE__, W_MS3_PIN) +#endif +#if PIN_EXISTS(W_STEP) + REPORT_NAME_DIGITAL(__LINE__, W_STEP_PIN) +#endif +#if PIN_EXISTS(W_STOP) + REPORT_NAME_DIGITAL(__LINE__, W_STOP_PIN) +#endif #if PIN_EXISTS(ZRIB_V20_D6) REPORT_NAME_DIGITAL(__LINE__, ZRIB_V20_D6_PIN) #endif @@ -1619,6 +1718,24 @@ #if PIN_EXISTS(K_SERIAL_RX) REPORT_NAME_DIGITAL(__LINE__, K_SERIAL_RX_PIN) #endif +#if PIN_EXISTS(U_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, U_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(U_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, U_SERIAL_RX_PIN) +#endif +#if PIN_EXISTS(V_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, V_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(V_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, V_SERIAL_RX_PIN) +#endif +#if PIN_EXISTS(W_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, W_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(W_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, W_SERIAL_RX_PIN) +#endif #if PIN_EXISTS(E0_DIAG) REPORT_NAME_DIGITAL(__LINE__, E0_DIAG_PIN) #endif diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h index aabe0da85873..8da2b969bc02 100644 --- a/Marlin/src/pins/pins_postprocess.h +++ b/Marlin/src/pins/pins_postprocess.h @@ -221,6 +221,15 @@ #if !AXIS_HAS_SPI(K) #undef K_CS_PIN #endif +#if !AXIS_HAS_SPI(U) + #undef U_CS_PIN +#endif +#if !AXIS_HAS_SPI(V) + #undef V_CS_PIN +#endif +#if !AXIS_HAS_SPI(W) + #undef W_CS_PIN +#endif #if E_STEPPERS && !AXIS_HAS_SPI(E0) #undef E0_CS_PIN #endif @@ -264,6 +273,15 @@ #ifndef K_CS_PIN #define K_CS_PIN -1 #endif +#ifndef U_CS_PIN + #define U_CS_PIN -1 +#endif +#ifndef V_CS_PIN + #define V_CS_PIN -1 +#endif +#ifndef W_CS_PIN + #define W_CS_PIN -1 +#endif #ifndef E0_CS_PIN #define E0_CS_PIN -1 #endif @@ -546,6 +564,75 @@ #undef K_MAX_PIN #endif +#if HAS_U_AXIS + #ifdef U_STOP_PIN + #if U_HOME_TO_MIN + #define U_MIN_PIN U_STOP_PIN + #ifndef U_MAX_PIN + #define U_MAX_PIN -1 + #endif + #else + #define U_MAX_PIN U_STOP_PIN + #ifndef U_MIN_PIN + #define U_MIN_PIN -1 + #endif + #endif + #elif U_HOME_TO_MIN + #define U_STOP_PIN U_MIN_PIN + #else + #define U_STOP_PIN U_MAX_PIN + #endif +#else + #undef U_MIN_PIN + #undef U_MAX_PIN +#endif + +#if HAS_V_AXIS + #ifdef V_STOP_PIN + #if V_HOME_TO_MIN + #define V_MIN_PIN V_STOP_PIN + #ifndef V_MAX_PIN + #define V_MAX_PIN -1 + #endif + #else + #define V_MAX_PIN V_STOP_PIN + #ifndef V_MIN_PIN + #define V_MIN_PIN -1 + #endif + #endif + #elif V_HOME_TO_MIN + #define V_STOP_PIN V_MIN_PIN + #else + #define V_STOP_PIN V_MAX_PIN + #endif +#else + #undef V_MIN_PIN + #undef V_MAX_PIN +#endif + +#if HAS_W_AXIS + #ifdef W_STOP_PIN + #if W_HOME_TO_MIN + #define W_MIN_PIN W_STOP_PIN + #ifndef W_MAX_PIN + #define W_MAX_PIN -1 + #endif + #else + #define W_MAX_PIN W_STOP_PIN + #ifndef W_MIN_PIN + #define W_MIN_PIN -1 + #endif + #endif + #elif W_HOME_TO_MIN + #define W_STOP_PIN W_MIN_PIN + #else + #define W_STOP_PIN W_MAX_PIN + #endif +#else + #undef W_MIN_PIN + #undef W_MAX_PIN +#endif + // Filament Sensor first pin alias #if HAS_FILAMENT_SENSOR #define FIL_RUNOUT1_PIN FIL_RUNOUT_PIN // Filament Sensor first pin alias @@ -1204,6 +1291,12 @@ #define J_MS3_PIN -1 #endif +#if HAS_K_AXIS && !defined(K_DIAG_PIN) && !defined(K_STEP_PIN) && !PIN_EXISTS(K_CS_PIN) + #define U_E_INDEX INCREMENT(K_E_INDEX) +#else + #define U_E_INDEX K_E_INDEX +#endif + // The K axis, if any, should be the next open extruder port #if HAS_K_AXIS #ifndef K_STEP_PIN @@ -1284,6 +1377,258 @@ #define K_MS3_PIN -1 #endif +#if HAS_U_AXIS && !defined(U_DIAG_PIN) && !defined(U_STEP_PIN) && !PIN_EXISTS(U_CS_PIN) + #define V_E_INDEX INCREMENT(U_E_INDEX) +#else + #define V_E_INDEX U_E_INDEX +#endif + +// The U axis, if any, should be the next open extruder port +#if HAS_U_AXIS + #ifndef U_STEP_PIN + #define U_STEP_PIN _EPIN(U_E_INDEX, STEP) + #define U_DIR_PIN _EPIN(U_E_INDEX, DIR) + #define U_ENABLE_PIN _EPIN(U_E_INDEX, ENABLE) + #if M_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(U_STEP) + #error "No E stepper plug left for U!" + #else + #define AUTO_ASSIGNED_U_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(U) && !defined(U_CS_PIN) + #define U_CS_PIN _EPIN(U_E_INDEX, CS) + #if PIN_EXISTS(U_CS) + #define AUTO_ASSIGNED_U_CS 1 + #endif + #endif + #ifndef U_MS1_PIN + #define U_MS1_PIN _EPIN(U_E_INDEX, MS1) + #if PIN_EXISTS(U_MS1) + #define AUTO_ASSIGNED_U_MS1 1 + #endif + #endif + #ifndef U_MS2_PIN + #define U_MS2_PIN _EPIN(U_E_INDEX, MS2) + #if PIN_EXISTS(U_MS2) + #define AUTO_ASSIGNED_U_MS2 1 + #endif + #endif + #ifndef U_MS3_PIN + #define U_MS3_PIN _EPIN(U_E_INDEX, MS3) + #if PIN_EXISTS(U_MS3) + #define AUTO_ASSIGNED_U_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(U) + #ifndef U_SERIAL_TX_PIN + #define U_SERIAL_TX_PIN _EPIN(U_E_INDEX, SERIAL_TX) + #endif + #ifndef U_SERIAL_RX_PIN + #define U_SERIAL_RX_PIN _EPIN(U_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(U_DIAG_PIN) && !defined(U_USE_ENDSTOP) && defined(U_STALL_SENSITIVITY) && _PEXI(U_E_INDEX, DIAG) + #define U_DIAG_PIN _EPIN(U_E_INDEX, DIAG) + #if DIAG_REMAPPED(U, X_MIN) + #define U_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(U, Y_MIN) + #define U_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(U, Z_MIN) + #define U_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(U, X_MAX) + #define U_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(U, Y_MAX) + #define U_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(U, Z_MAX) + #define U_USE_ENDSTOP _ZMAX_ + #else + #define U_USE_ENDSTOP _En_DIAG_(U_E_INDEX) + #endif + #define AUTO_ASSIGNED_U_DIAG 1 + #undef U_DIAG_PIN // Defined in Conditionals_post.h based on U_USE_ENDSTOP + #endif +#endif + +#ifndef U_CS_PIN + #define U_CS_PIN -1 +#endif +#ifndef U_MS1_PIN + #define U_MS1_PIN -1 +#endif +#ifndef U_MS2_PIN + #define U_MS2_PIN -1 +#endif +#ifndef U_MS3_PIN + #define U_MS3_PIN -1 +#endif + +#if HAS_V_AXIS && !defined(V_DIAG_PIN) && !defined(V_STEP_PIN) && !PIN_EXISTS(V_CS_PIN) + #define W_E_INDEX INCREMENT(V_E_INDEX) +#else + #define W_E_INDEX V_E_INDEX +#endif + +// The V axis, if any, should be the next open extruder port +#if HAS_V_AXIS + #ifndef V_STEP_PIN + #define V_STEP_PIN _EPIN(V_E_INDEX, STEP) + #define V_DIR_PIN _EPIN(V_E_INDEX, DIR) + #define V_ENABLE_PIN _EPIN(V_E_INDEX, ENABLE) + #if V_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(V_STEP) + #error "No E stepper plug left for V!" + #else + #define AUTO_ASSIGNED_V_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(V) && !defined(V_CS_PIN) + #define V_CS_PIN _EPIN(V_E_INDEX, CS) + #if PIN_EXISTS(V_CS) + #define AUTO_ASSIGNED_V_CS 1 + #endif + #endif + #ifndef V_MS1_PIN + #define V_MS1_PIN _EPIN(V_E_INDEX, MS1) + #if PIN_EXISTS(V_MS1) + #define AUTO_ASSIGNED_V_MS1 1 + #endif + #endif + #ifndef V_MS2_PIN + #define V_MS2_PIN _EPIN(V_E_INDEX, MS2) + #if PIN_EXISTS(V_MS2) + #define AUTO_ASSIGNED_V_MS2 1 + #endif + #endif + #ifndef V_MS3_PIN + #define V_MS3_PIN _EPIN(V_E_INDEX, MS3) + #if PIN_EXISTS(V_MS3) + #define AUTO_ASSIGNED_V_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(V) + #ifndef V_SERIAL_TX_PIN + #define V_SERIAL_TX_PIN _EPIN(V_E_INDEX, SERIAL_TX) + #endif + #ifndef V_SERIAL_RX_PIN + #define V_SERIAL_RX_PIN _EPIN(V_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(V_DIAG_PIN) && !defined(V_USE_ENDSTOP) && defined(V_STALL_SENSITIVITY) && _PEXI(V_E_INDEX, DIAG) + #define V_DIAG_PIN _EPIN(V_E_INDEX, DIAG) + #if DIAG_REMAPPED(V, X_MIN) + #define V_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(V, Y_MIN) + #define V_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(V, Z_MIN) + #define V_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(V, X_MAX) + #define V_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(V, Y_MAX) + #define V_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(V, Z_MAX) + #define V_USE_ENDSTOP _ZMAX_ + #else + #define V_USE_ENDSTOP _En_DIAG_(V_E_INDEX) + #endif + #define AUTO_ASSIGNED_V_DIAG 1 + #undef V_DIAG_PIN // Defined in Conditionals_post.h based on O_USE_ENDSTOP + #endif +#endif + +#ifndef V_CS_PIN + #define V_CS_PIN -1 +#endif +#ifndef V_MS1_PIN + #define V_MS1_PIN -1 +#endif +#ifndef V_MS2_PIN + #define V_MS2_PIN -1 +#endif +#ifndef V_MS3_PIN + #define V_MS3_PIN -1 +#endif + +// The W axis, if any, should be the next open extruder port +#if HAS_W_AXIS + #ifndef W_STEP_PIN + #define W_STEP_PIN _EPIN(W_E_INDEX, STEP) + #define W_DIR_PIN _EPIN(W_E_INDEX, DIR) + #define W_ENABLE_PIN _EPIN(W_E_INDEX, ENABLE) + #if W_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(W_STEP) + #error "No E stepper plug left for W!" + #else + #define AUTO_ASSIGNED_W_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(W) && !defined(W_CS_PIN) + #define W_CS_PIN _EPIN(W_E_INDEX, CS) + #if PIN_EXISTS(W_CS) + #define AUTO_ASSIGNED_W_CS 1 + #endif + #endif + #ifndef W_MS1_PIN + #define W_MS1_PIN _EPIN(W_E_INDEX, MS1) + #if PIN_EXISTS(W_MS1) + #define AUTO_ASSIGNED_W_MS1 1 + #endif + #endif + #ifndef W_MS2_PIN + #define W_MS2_PIN _EPIN(W_E_INDEX, MS2) + #if PIN_EXISTS(W_MS2) + #define AUTO_ASSIGNED_W_MS2 1 + #endif + #endif + #ifndef W_MS3_PIN + #define W_MS3_PIN _EPIN(W_E_INDEX, MS3) + #if PIN_EXISTS(W_MS3) + #define AUTO_ASSIGNED_W_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(W) + #ifndef W_SERIAL_TX_PIN + #define W_SERIAL_TX_PIN _EPIN(W_E_INDEX, SERIAL_TX) + #endif + #ifndef W_SERIAL_RX_PIN + #define W_SERIAL_RX_PIN _EPIN(W_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(W_DIAG_PIN) && !defined(W_USE_ENDSTOP) && defined(W_STALL_SENSITIVITY) && _PEXI(W_E_INDEX, DIAG) + #define W_DIAG_PIN _EPIN(W_E_INDEX, DIAG) + #if DIAG_REMAPPED(W, X_MIN) + #define W_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(W, Y_MIN) + #define W_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(W, Z_MIN) + #define W_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(W, X_MAX) + #define W_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(W, Y_MAX) + #define W_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(W, Z_MAX) + #define W_USE_ENDSTOP _ZMAX_ + #else + #define W_USE_ENDSTOP _En_DIAG_(W_E_INDEX) + #endif + #define AUTO_ASSIGNED_W_DIAG 1 + #undef W_DIAG_PIN // Defined in Conditionals_post.h based on Q_USE_ENDSTOP + #endif +#endif + +#ifndef W_CS_PIN + #define W_CS_PIN -1 +#endif +#ifndef W_MS1_PIN + #define W_MS1_PIN -1 +#endif +#ifndef W_MS2_PIN + #define W_MS2_PIN -1 +#endif +#ifndef W_MS3_PIN + #define W_MS3_PIN -1 +#endif + // // Disable unused endstop / probe pins // @@ -1359,6 +1704,30 @@ #undef K_MAX_PIN #define K_MAX_PIN -1 #endif +#if DISABLED(USE_UMIN_PLUG) + #undef U_MIN_PIN + #define U_MIN_PIN -1 +#endif +#if DISABLED(USE_UMAX_PLUG) + #undef U_MAX_PIN + #define U_MAX_PIN -1 +#endif +#if DISABLED(USE_VMIN_PLUG) + #undef V_MIN_PIN + #define V_MIN_PIN -1 +#endif +#if DISABLED(USE_VMAX_PLUG) + #undef V_MAX_PIN + #define V_MAX_PIN -1 +#endif +#if DISABLED(USE_WMIN_PLUG) + #undef W_MIN_PIN + #define W_MIN_PIN -1 +#endif +#if DISABLED(USE_WMAX_PLUG) + #undef W_MAX_PIN + #define W_MAX_PIN -1 +#endif #if DISABLED(X_DUAL_ENDSTOPS) || X_HOME_TO_MAX #undef X2_MIN_PIN diff --git a/Marlin/src/pins/sensitive_pins.h b/Marlin/src/pins/sensitive_pins.h index f9911cc863fa..db6cb2353b3f 100644 --- a/Marlin/src/pins/sensitive_pins.h +++ b/Marlin/src/pins/sensitive_pins.h @@ -293,6 +293,126 @@ #endif +#if HAS_U_AXIS + #if PIN_EXISTS(U_MIN) + #define _U_MIN U_MIN_PIN, + #else + #define _U_MIN + #endif + #if PIN_EXISTS(U_MAX) + #define _U_MAX U_MAX_PIN, + #else + #define _U_MAX + #endif + #if PIN_EXISTS(U_CS) && AXIS_HAS_SPI(U) + #define _U_CS U_CS_PIN, + #else + #define _U_CS + #endif + #if PIN_EXISTS(U_MS1) + #define _U_MS1 U_MS1_PIN, + #else + #define _U_MS1 + #endif + #if PIN_EXISTS(U_MS2) + #define _U_MS2 U_MS2_PIN, + #else + #define _U_MS2 + #endif + #if PIN_EXISTS(U_MS3) + #define _U_MS3 U_MS3_PIN, + #else + #define _U_MS3 + #endif + + #define _U_PINS U_STEP_PIN, U_DIR_PIN, U_ENABLE_PIN, _U_MIN _U_MAX _U_MS1 _U_MS2 _U_MS3 _U_CS + +#else + + #define _U_PINS + +#endif + +#if HAS_V_AXIS + #if PIN_EXISTS(V_MIN) + #define _V_MIN V_MIN_PIN, + #else + #define _V_MIN + #endif + #if PIN_EXISTS(V_MAX) + #define _V_MAX V_MAX_PIN, + #else + #define _V_MAX + #endif + #if PIN_EXISTS(V_CS) && AXIS_HAS_SPI(V) + #define _V_CS V_CS_PIN, + #else + #define _V_CS + #endif + #if PIN_EXISTS(V_MS1) + #define _V_MS1 V_MS1_PIN, + #else + #define _V_MS1 + #endif + #if PIN_EXISTS(V_MS2) + #define _V_MS2 V_MS2_PIN, + #else + #define _V_MS2 + #endif + #if PIN_EXISTS(V_MS3) + #define _V_MS3 V_MS3_PIN, + #else + #define _V_MS3 + #endif + + #define _V_PINS V_STEP_PIN, V_DIR_PIN, V_ENABLE_PIN, _V_MIN _V_MAX _V_MS1 _V_MS2 _V_MS3 _V_CS + +#else + + #define _V_PINS + +#endif + +#if HAS_W_AXIS + #if PIN_EXISTS(W_MIN) + #define _W_MIN W_MIN_PIN, + #else + #define _W_MIN + #endif + #if PIN_EXISTS(W_MAX) + #define _W_MAX W_MAX_PIN, + #else + #define _W_MAX + #endif + #if PIN_EXISTS(W_CS) && AXIS_HAS_SPI(W) + #define _W_CS W_CS_PIN, + #else + #define _W_CS + #endif + #if PIN_EXISTS(W_MS1) + #define _W_MS1 W_MS1_PIN, + #else + #define _W_MS1 + #endif + #if PIN_EXISTS(W_MS2) + #define _W_MS2 W_MS2_PIN, + #else + #define _W_MS2 + #endif + #if PIN_EXISTS(W_MS3) + #define _W_MS3 W_MS3_PIN, + #else + #define _W_MS3 + #endif + + #define _W_PINS W_STEP_PIN, W_DIR_PIN, W_ENABLE_PIN, _W_MIN _W_MAX _W_MS1 _W_MS2 _W_MS3 _W_CS + +#else + + #define _W_PINS + +#endif + // // Extruder Chip Select, Digital Micro-steps // @@ -886,7 +1006,7 @@ #endif #define SENSITIVE_PINS \ - _X_PINS _Y_PINS _Z_PINS _I_PINS _J_PINS _K_PINS \ + _X_PINS _Y_PINS _Z_PINS _I_PINS _J_PINS _K_PINS _U_PINS _V_PINS _W_PINS \ _X2_PINS _Y2_PINS _Z2_PINS _Z3_PINS _Z4_PINS _Z_PROBE \ _E0_PINS _E1_PINS _E2_PINS _E3_PINS _E4_PINS _E5_PINS _E6_PINS _E7_PINS \ _H0_PINS _H1_PINS _H2_PINS _H3_PINS _H4_PINS _H5_PINS _H6_PINS _H7_PINS \