Compare commits

...

20 Commits

Author SHA1 Message Date
Scott Lahteine
b412a1a03e 🔖 Marlin 2.1.0.1 2023-07-20 13:43:19 -05:00
Scott Lahteine
8fd6f9a2b0 🔨 PlatformIO 6 compatibility 2023-07-20 13:43:19 -05:00
Scott Lahteine
5c225ba887 🔖 Marlin 2.1 2022-06-05 23:11:32 -05:00
ellensp
2685119332 🩹 Fix EXTRUDERS 0 manual move compile (#24255) 2022-06-05 23:11:32 -05:00
tombrazier
fc350701b2 💥 More M306 M => M306 H (#24258)
Followup to #24253
2022-06-05 23:11:32 -05:00
Miguel Risco-Castillo
0ad695d45a 🚸 Fix, improve, update ProUI (#24251) 2022-06-05 23:11:32 -05:00
elimisback
f1802bc7fe 🔨 BTT STM32G0B1RE xfer build (#24245) 2022-06-05 23:11:32 -05:00
Scott Lahteine
d6c673b9de ♻️ More updates for multi-axis 2022-06-05 23:11:32 -05:00
Scott Lahteine
6a2a592c26 🧑‍💻 Combined axis strings 2022-06-05 23:11:32 -05:00
Scott Lahteine
c4ac695c15 🧑‍💻 Forward-compatible axis strings (167672d, #24259) 2022-06-05 23:11:32 -05:00
Keith Bennett
8465818754 🎨 Fix/adjust warnings (#24225) 2022-06-05 23:11:32 -05:00
Scott Lahteine
3c482a9ba1 🧑‍💻 MAP macro for axis lists, etc. (#24191) 2022-06-05 23:11:32 -05:00
DerAndere
ecfe7b6400 🩹 Fix some parameters w/out values (#24051) 2022-06-05 23:11:32 -05:00
DerAndere
85599abba7 🚸 Better M350, M114 with more axes (#23986) 2022-06-05 23:11:32 -05:00
Scott Lahteine
494a2fc80c 🚨 Fix some compiler warnings 2022-06-05 23:11:31 -05:00
Scott Lahteine
f7bea2846f 🏗️ Axis name arrays
Co-Authored-By: DerAndere <26200979+DerAndere1@users.noreply.github.com>
2022-06-05 23:11:31 -05:00
Scott Lahteine
d56731cd07 🏗️ Extend AXIS_CHAR to include E
Co-Authored-By: DerAndere <26200979+DerAndere1@users.noreply.github.com>
2022-06-05 23:11:31 -05:00
DerAndere
0041de1a8a 💥 Update Motor Current G-codes for extra axes (#23975) 2022-06-05 23:11:31 -05:00
ellensp
d58497bc8e 🐛 Fix BACKLASH_COMPENSATION compile (#24072)
Followup to #23826
2022-06-05 23:11:31 -05:00
Scott Lahteine
fd13a928c1 Support for up to 9 axes (#23112, #24036, #24231) 2022-06-05 23:11:31 -05:00
245 changed files with 5588 additions and 1657 deletions

View File

@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02000904
#define CONFIGURATION_H_VERSION 02010000
//===========================================================================
//============================= Getting Started =============================
@@ -176,6 +176,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
@@ -186,20 +189,25 @@
//#define E7_DRIVER_TYPE A4988
/**
* 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.
*/
#ifdef I_DRIVER_TYPE
#define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
#define AXIS4_ROTATES
#endif
#ifdef J_DRIVER_TYPE
#define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W']
@@ -209,6 +217,18 @@
#define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W']
#define AXIS6_ROTATES
#endif
#ifdef U_DRIVER_TYPE
#define AXIS7_NAME 'U' // :['U', 'V', 'W']
//#define AXIS7_ROTATES
#endif
#ifdef V_DRIVER_TYPE
#define AXIS8_NAME 'V' // :['V', 'W']
//#define AXIS8_ROTATES
#endif
#ifdef W_DRIVER_TYPE
#define AXIS9_NAME 'W' // :['W']
//#define AXIS9_ROTATES
#endif
// @section extruder
@@ -860,12 +880,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
@@ -877,12 +903,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
@@ -896,12 +928,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
@@ -912,12 +950,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.
// Enable this feature if all enabled endstop pins are interrupt-capable.
@@ -962,16 +1006,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 }
@@ -981,10 +1025,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 }
@@ -994,7 +1038,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
@@ -1007,7 +1051,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
@@ -1021,6 +1065,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
@@ -1359,6 +1406,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!
@@ -1368,6 +1418,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
@@ -1386,6 +1439,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
@@ -1424,6 +1480,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
@@ -1431,7 +1490,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
@@ -1444,6 +1503,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
@@ -1463,6 +1528,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
@@ -1474,6 +1542,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)
@@ -1788,6 +1859,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.
@@ -1803,7 +1877,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

View File

@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02000904
#define CONFIGURATION_ADV_H_VERSION 02010000
//===========================================================================
//============================= Thermal Settings ============================
@@ -832,12 +832,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
@@ -1023,6 +1023,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
/**
@@ -1037,11 +1040,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.
@@ -1077,7 +1083,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
@@ -1154,6 +1160,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.
@@ -2630,6 +2657,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
@@ -2818,6 +2863,36 @@
//#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
//#define U_HOLD_MULTIPLIER 0.5
#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
//#define V_HOLD_MULTIPLIER 0.5
#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
//#define W_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E0)
#define E0_CURRENT 800
#define E0_MICROSTEPS 16
@@ -2905,6 +2980,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
@@ -2947,6 +3025,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
@@ -2974,6 +3055,9 @@
#define STEALTHCHOP_I
#define STEALTHCHOP_J
#define STEALTHCHOP_K
#define STEALTHCHOP_U
#define STEALTHCHOP_V
#define STEALTHCHOP_W
#define STEALTHCHOP_E
/**
@@ -3000,9 +3084,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
@@ -3048,9 +3135,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
@@ -3100,6 +3190,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
@@ -3267,6 +3360,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

View File

@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
//#define SHORT_BUILD_VERSION "2.0.9.4"
//#define SHORT_BUILD_VERSION "2.1.0.1"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2022-06-04"
//#define STRING_DISTRIBUTION_DATE "2023-07-19"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.

View File

@@ -19,6 +19,10 @@
*/
#pragma once
/**
* HAL for Arduino AVR
*/
#include "../shared/Marduino.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -443,6 +443,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, bedlevel.steppers_were_disabled());
@@ -1003,6 +1006,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

View File

@@ -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) (HAS_X2_STEPPER && _AXIS_DRIVER_TYPE(X2,T))
#define AXIS_DRIVER_TYPE_Y2(T) (HAS_DUAL_Y_STEPPERS && _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)

View File

@@ -457,6 +457,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

View File

@@ -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) }
@@ -700,13 +712,22 @@
#define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V))
#define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V)
// See https://github.com/swansontec/map-macro
#define MAP_OUT
#define MAP_END(...)
#define MAP_GET_END() 0, MAP_END
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL512 (MAP1 (f, __VA_ARGS__, (), 0))
// Call OP(A) with each item as an argument
#define _MAP(_MAP_OP,A,V...) \
_MAP_OP(A) \
IF_ELSE(HAS_ARGS(V)) \
( DEFER2(__MAP)()(_MAP_OP,V) ) \
( /* Do nothing */ )
#define __MAP() _MAP
#define MAP(OP,V...) EVAL(_MAP(OP,V))
// Emit a list of OP(A) with the given items
#define _MAPLIST(_MAP_OP,A,V...) \
_MAP_OP(A) \
IF_ELSE(HAS_ARGS(V)) \
( , DEFER2(__MAPLIST)()(_MAP_OP,V) ) \
( /* Do nothing */ )
#define __MAPLIST() _MAPLIST
#define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V))

View File

@@ -30,16 +30,15 @@
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(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:");
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_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":");
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(NUL_STR, "");
#define _N_STR(N) PGMSTR(N##_STR, STR_##N);
#define _N_LBL(N) PGMSTR(N##_LBL, STR_##N ":");
#define _SP_N_STR(N) PGMSTR(SP_##N##_STR, " " STR_##N);
#define _SP_N_LBL(N) PGMSTR(SP_##N##_LBL, " " STR_##N ":");
MAP(_N_STR, LOGICAL_AXIS_NAMES); MAP(_SP_N_STR, LOGICAL_AXIS_NAMES);
MAP(_N_LBL, LOGICAL_AXIS_NAMES); MAP(_SP_N_LBL, LOGICAL_AXIS_NAMES);
// Hook Meatpack if it's enabled on the first leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
@@ -102,10 +101,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();
}

View File

@@ -28,19 +28,6 @@
#include "../feature/meatpack.h"
#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[];
//
// Debugging flags for use by M111
//
@@ -348,11 +335,40 @@ 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)
#define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, F(PREFIX)); }while(0)
//
// Commonly-used strings in serial output
//
#define _N_STR(N) N##_STR
#define _N_LBL(N) N##_LBL
#define _N_STR_A(N) _N_STR(N)[]
#define _N_LBL_A(N) _N_LBL(N)[]
#define _SP_N_STR(N) SP_##N##_STR
#define _SP_N_LBL(N) SP_##N##_LBL
#define _SP_N_STR_A(N) _SP_N_STR(N)[]
#define _SP_N_LBL_A(N) _SP_N_LBL(N)[]
extern const char SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_P_STR[], SP_T_STR[], NUL_STR[],
MAPLIST(_N_STR_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_STR_A, LOGICAL_AXIS_NAMES),
MAPLIST(_N_LBL_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_LBL_A, LOGICAL_AXIS_NAMES);
PGM_P const SP_AXIS_LBL[] PROGMEM = { MAPLIST(_SP_N_LBL, LOGICAL_AXIS_NAMES) };
PGM_P const SP_AXIS_STR[] PROGMEM = { MAPLIST(_SP_N_STR, LOGICAL_AXIS_NAMES) };
#undef _N_STR
#undef _N_LBL
#undef _N_STR_A
#undef _N_LBL_A
#undef _SP_N_STR
#undef _SP_N_LBL
#undef _SP_N_STR_A
#undef _SP_N_LBL_A

View File

@@ -43,7 +43,9 @@ public:
}
constexpr SerialMask(const uint8_t mask) : mask(mask) {}
constexpr SerialMask(const SerialMask & other) : mask(other.mask) {} // Can't use = default here since not all framework support this
constexpr SerialMask(const SerialMask &rs) : mask(rs.mask) {} // Can't use = default here since not all frameworks support this
SerialMask& operator=(const SerialMask &rs) { mask = rs.mask; return *this; }
static constexpr uint8_t All = 0xFF;
};

View File

@@ -36,23 +36,41 @@ struct IF { typedef R type; };
template <class L, class R>
struct IF<true, L, R> { 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 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_LIST_1(V) LIST_N_1(NUM_AXES, V)
#define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) }
#define NUM_AXIS_ARRAY_1(V) { NUM_AXIS_LIST_1(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 MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W)
#define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES)
#define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#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 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_LIST_1(V) NUM_AXIS_LIST_1(V) LIST_ITEM_E(V)
#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_ARRAY_1(V) { LOGICAL_AXIS_LIST_1(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_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K, U, V, W)
#define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES)
#define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K)
#define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V)
#define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V)
#define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V)
#define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V)
#if HAS_ROTATIONAL_AXES
#define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V)
#endif
#if HAS_EXTRUDERS
#define LIST_ITEM_E(N) , N
@@ -64,7 +82,7 @@ struct IF<true, L, R> { 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)
// General Flags for some number of states
template<size_t N>
@@ -81,9 +99,9 @@ struct Flags {
void set(const int n) { b |= (bits_t)_BV(n); }
void clear(const int n) { b &= ~(bits_t)_BV(n); }
bool test(const int n) const { return TEST(b, n); }
bool operator[](const int n) { return test(n); }
const bool operator[](const int n) const { return test(n); }
const int size() const { return sizeof(b); }
bool operator[](const int n) { return test(n); }
bool operator[](const int n) const { return test(n); }
int size() const { return sizeof(b); }
};
// Specialization for a single bool flag
@@ -95,9 +113,9 @@ struct Flags<1> {
void set(const int) { b = true; }
void clear(const int) { b = false; }
bool test(const int) const { return b; }
bool operator[](const int) { return b; }
const bool operator[](const int) const { return b; }
const int size() const { return sizeof(b); }
bool operator[](const int) { return b; }
bool operator[](const int) const { return b; }
int size() const { return sizeof(b); }
};
typedef Flags<8> flags_8_t;
@@ -114,9 +132,9 @@ typedef struct AxisFlags {
void set(const int n, const bool onoff) { flags.set(n, onoff); }
void clear(const int n) { flags.clear(n); }
bool test(const int n) const { return flags.test(n); }
bool operator[](const int n) { return flags[n]; }
const bool operator[](const int n) const { return flags[n]; }
const int size() const { return sizeof(flags); }
bool operator[](const int n) { return flags[n]; }
bool operator[](const int n) const { return flags[n]; }
int size() const { return sizeof(flags); }
} axis_flags_t;
//
@@ -129,7 +147,7 @@ typedef struct AxisFlags {
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
@@ -168,7 +186,7 @@ typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type 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)
@@ -313,10 +331,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]; }
@@ -438,60 +456,69 @@ struct XYval {
template<typename T>
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<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const XYval<T> pxy, const T pz) { LINEAR_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); }
FI void set(const XYval<T> 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<T> copy() const { XYZval<T> o = *this; return o; }
FI XYZval<T> 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<int16_t> 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<int16_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<float> asFloat() { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
FI XYZval<float> asFloat() const { return LINEAR_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
FI XYZval<float> reciprocal() const { return LINEAR_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
FI XYZval<T> 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<int16_t> 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<int16_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<float> asFloat() { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI XYZval<float> 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<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
@@ -502,78 +529,78 @@ struct XYZval {
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
// Cast to a type with more fields by making a new object
FI operator XYZEval<T>() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); }
FI operator XYZEval<T>() 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<T>& operator= (const T v) { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; }
FI XYZval<T>& operator= (const T v) { set(ARRAY_N_1(NUM_AXES, v)); return *this; }
FI XYZval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y ); return *this; }
FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
FI XYZval<T>& operator= (const XYZEval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
// Override other operators to get intuitive behaviors
FI XYZval<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZval<T> &rs) { XYZval<T> 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<T> operator- (const XYZval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZval<T> &rs) { XYZval<T> 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<T> operator* (const XYZval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) { XYZval<T> 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<T> operator- (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZEval<T> &rs) { XYZval<T> 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<T> operator* (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZEval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZEval<T> &rs) { XYZval<T> 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<T> operator* (const float &v) const { XYZval<T> 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<T> operator* (const float &v) { XYZval<T> 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<T> operator* (const int &v) const { XYZval<T> 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<T> operator* (const int &v) { XYZval<T> 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<T> operator/ (const float &v) const { XYZval<T> 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<T> operator/ (const float &v) { XYZval<T> 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<T> operator/ (const int &v) const { XYZval<T> 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<T> operator/ (const int &v) { XYZval<T> 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<T> operator>>(const int &v) const { XYZval<T> 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<T> operator>>(const int &v) { XYZval<T> 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<T> operator<<(const int &v) const { XYZval<T> 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<T> operator<<(const int &v) { XYZval<T> 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<T> operator-() const { XYZval<T> 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<T> operator-() { XYZval<T> 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<T> operator+ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator- (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator* (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) const { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator/ (const XYval<T> &rs) { XYZval<T> ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; }
FI XYZval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZval<T> &rs) { XYZval<T> 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<T> operator- (const XYZval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZval<T> &rs) { XYZval<T> 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<T> operator* (const XYZval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) { XYZval<T> 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<T> operator- (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZEval<T> &rs) { XYZval<T> 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<T> operator* (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZEval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZEval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZEval<T> &rs) { XYZval<T> 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<T> operator* (const float &v) const { XYZval<T> 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<T> operator* (const float &v) { XYZval<T> 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<T> operator* (const int &v) const { XYZval<T> 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<T> operator* (const int &v) { XYZval<T> 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<T> operator/ (const float &v) const { XYZval<T> 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<T> operator/ (const float &v) { XYZval<T> 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<T> operator/ (const int &v) const { XYZval<T> 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<T> operator/ (const int &v) { XYZval<T> 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<T> operator>>(const int &v) const { XYZval<T> 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<T> operator>>(const int &v) { XYZval<T> 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<T> operator<<(const int &v) const { XYZval<T> 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<T> operator<<(const int &v) { XYZval<T> 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<T> operator-() const { XYZval<T> 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<T> operator-() { XYZval<T> 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<T>& operator+=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator-=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator*=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator/=(const XYval<T> &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator+=(const XYZval<T> &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<T>& operator-=(const XYZval<T> &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<T>& operator*=(const XYZval<T> &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<T>& operator/=(const XYZval<T> &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<T>& operator+=(const XYZEval<T> &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<T>& operator-=(const XYZEval<T> &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<T>& operator*=(const XYZEval<T> &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<T>& operator/=(const XYZEval<T> &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<T>& operator*=(const float &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
FI XYZval<T>& operator*=(const int &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; }
FI XYZval<T>& operator>>=(const int &v) { LINEAR_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; }
FI XYZval<T>& operator<<=(const int &v) { LINEAR_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; }
FI XYZval<T>& operator+=(const XYval<T> &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator-=(const XYval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator*=(const XYval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator/=(const XYval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; }
FI XYZval<T>& operator+=(const XYZval<T> &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<T>& operator-=(const XYZval<T> &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<T>& operator*=(const XYZval<T> &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<T>& operator/=(const XYZval<T> &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<T>& operator+=(const XYZEval<T> &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<T>& operator-=(const XYZEval<T> &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<T>& operator*=(const XYZEval<T> &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<T>& operator/=(const XYZEval<T> &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<T>& 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<T>& 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<T>& 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<T>& 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<T> &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<T> &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<T> &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<T> &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<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
};
@@ -585,56 +612,66 @@ template<typename T>
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<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const XYZval<T> pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); }
FI void set(const XYval<T> pxy) { x = pxy.x; y = pxy.y; }
FI void set(const XYZval<T> 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<T> pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); }
#if LOGICAL_AXES > LINEAR_AXES
FI void set(const XYval<T> pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); }
#if LOGICAL_AXES > NUM_AXES
FI void set(const XYval<T> pxy, const T pz, const T pe) { set(pxy, pz); e = pe; }
FI void set(const XYZval<T> 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<T> 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<T> copy() const { XYZEval<T> o = *this; return o; }
FI XYZEval<T> 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<int16_t> 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<int16_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<float> asFloat() { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
FI XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k)); }
FI XYZEval<float> reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); }
FI XYZEval<T> copy() const { XYZEval<T> v = *this; return v; }
FI XYZEval<T> 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<int16_t> 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<int16_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<int32_t> 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<float> asFloat() { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
FI XYZEval<float> 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<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
@@ -651,9 +688,9 @@ struct XYZEval {
FI const T& operator[](const int n) const { return pos[n]; }
// Assignment operator overrides do the expected thing
FI XYZEval<T>& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; }
FI XYZEval<T>& operator= (const T v) { set(LIST_N_1(NUM_AXES, v)); return *this; }
FI XYZEval<T>& operator= (const XYval<T> &rs) { set(rs.x, rs.y); return *this; }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; }
FI XYZEval<T>& operator= (const XYZval<T> &rs) { set(NUM_AXIS_ELEM(rs)); return *this; }
// Override other operators to get intuitive behaviors
FI XYZEval<T> operator+ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; }
@@ -664,57 +701,57 @@ struct XYZEval {
FI XYZEval<T> operator* (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) const { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator/ (const XYval<T> &rs) { XYZEval<T> ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; }
FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZval<T> &rs) { XYZval<T> 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<T> operator- (const XYZval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZval<T> &rs) { XYZval<T> 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<T> operator* (const XYZval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator- (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator* (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator* (const float &v) const { XYZEval<T> 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<T> operator* (const float &v) { XYZEval<T> 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<T> operator* (const int &v) const { XYZEval<T> 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<T> operator* (const int &v) { XYZEval<T> 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<T> operator/ (const float &v) const { XYZEval<T> 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<T> operator/ (const float &v) { XYZEval<T> 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<T> operator/ (const int &v) const { XYZEval<T> 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<T> operator/ (const int &v) { XYZEval<T> 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<T> operator>>(const int &v) const { XYZEval<T> 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<T> operator>>(const int &v) { XYZEval<T> 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<T> operator<<(const int &v) const { XYZEval<T> 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<T> operator<<(const int &v) { XYZEval<T> 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<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); }
FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); }
FI XYZEval<T> operator+ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator+ (const XYZval<T> &rs) { XYZval<T> 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<T> operator- (const XYZval<T> &rs) const { XYZval<T> 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<T> operator- (const XYZval<T> &rs) { XYZval<T> 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<T> operator* (const XYZval<T> &rs) const { XYZval<T> 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<T> operator* (const XYZval<T> &rs) { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) const { XYZval<T> 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<T> operator/ (const XYZval<T> &rs) { XYZval<T> 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<T> operator+ (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator+ (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator- (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator- (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator* (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator* (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator/ (const XYZEval<T> &rs) const { XYZEval<T> 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<T> operator/ (const XYZEval<T> &rs) { XYZEval<T> 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<T> operator* (const float &v) const { XYZEval<T> 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<T> operator* (const float &v) { XYZEval<T> 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<T> operator* (const int &v) const { XYZEval<T> 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<T> operator* (const int &v) { XYZEval<T> 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<T> operator/ (const float &v) const { XYZEval<T> 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<T> operator/ (const float &v) { XYZEval<T> 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<T> operator/ (const int &v) const { XYZEval<T> 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<T> operator/ (const int &v) { XYZEval<T> 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<T> operator>>(const int &v) const { XYZEval<T> 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<T> operator>>(const int &v) { XYZEval<T> 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<T> operator<<(const int &v) const { XYZEval<T> 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<T> operator<<(const int &v) { XYZEval<T> 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<T> operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
FI XYZEval<T> operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); }
// Modifier operators
FI XYZEval<T>& operator+=(const XYval<T> &rs) { x += rs.x; y += rs.y; return *this; }
FI XYZEval<T>& operator-=(const XYval<T> &rs) { x -= rs.x; y -= rs.y; return *this; }
FI XYZEval<T>& operator*=(const XYval<T> &rs) { x *= rs.x; y *= rs.y; return *this; }
FI XYZEval<T>& operator/=(const XYval<T> &rs) { x /= rs.x; y /= rs.y; return *this; }
FI XYZEval<T>& operator+=(const XYZval<T> &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<T>& operator-=(const XYZval<T> &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<T>& operator*=(const XYZval<T> &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<T>& operator/=(const XYZval<T> &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<T>& operator+=(const XYZEval<T> &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<T>& operator-=(const XYZEval<T> &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<T>& operator*=(const XYZEval<T> &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<T>& operator/=(const XYZEval<T> &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<T>& 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<T>& 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<T>& 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<T>& operator+=(const XYZval<T> &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<T>& operator-=(const XYZval<T> &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<T>& operator*=(const XYZval<T> &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<T>& operator/=(const XYZval<T> &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<T>& operator+=(const XYZEval<T> &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<T>& operator-=(const XYZEval<T> &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<T>& operator*=(const XYZEval<T> &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<T>& operator/=(const XYZEval<T> &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<T>& 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<T>& 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<T>& 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<T> &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<T> &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<T> &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<T> &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<T> &rs) { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
};

View File

@@ -125,8 +125,8 @@ void safe_delay(millis_t ms) {
#endif
#if ABL_PLANAR
SERIAL_ECHOPGM("ABL Adjustment");
LOOP_LINEAR_AXES(a) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
LOOP_NUM_AXES(a) {
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]));
serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]);
}
#else

View File

@@ -77,10 +77,13 @@ public:
// in the range 0-100 while avoiding rounding artifacts
constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) / 255; }
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 && !HAS_EXTRUDERS
#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

View File

@@ -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);
@@ -162,32 +162,37 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) {
}
class Backlash::StepAdjuster {
xyz_long_t applied_steps;
public:
StepAdjuster() {
LOOP_LINEAR_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];
}
private:
xyz_long_t applied_steps;
public:
StepAdjuster() {
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_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis];
}
};
void Backlash::set_correction_uint8(const uint8_t v) {
StepAdjuster adjuster;
correction = v;
}
#if ENABLED(BACKLASH_GCODE)
void Backlash::set_distance_mm(const AxisEnum axis, const float v) {
StepAdjuster adjuster;
distance_mm[axis] = v;
}
#ifdef BACKLASH_SMOOTHING_MM
void Backlash::set_smoothing_mm(const float v) {
void Backlash::set_correction_uint8(const uint8_t v) {
StepAdjuster adjuster;
smoothing_mm = v;
correction = v;
}
void Backlash::set_distance_mm(const AxisEnum axis, const float v) {
StepAdjuster adjuster;
distance_mm[axis] = v;
}
#ifdef BACKLASH_SMOOTHING_MM
void Backlash::set_smoothing_mm(const float v) {
StepAdjuster adjuster;
smoothing_mm = v;
}
#endif
#endif
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)

View File

@@ -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.

View File

@@ -59,7 +59,7 @@ int StepperDAC::init() {
}
void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) {
if (!dac_present) return;
if (!(dac_present && channel < LOGICAL_AXES)) return;
NOMORE(val, uint16_t(DAC_STEPPER_MAX));
@@ -84,13 +84,11 @@ void StepperDAC::print_values() {
if (!dac_present) return;
SERIAL_ECHO_MSG("Stepper current values in % (Amps):");
SERIAL_ECHO_START();
SERIAL_ECHOPGM_P(SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")"));
#if HAS_Y_AXIS
SERIAL_ECHOPGM_P(SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_AXIS), PSTR(")"));
#endif
#if HAS_Z_AXIS
SERIAL_ECHOPGM_P(SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")"));
#endif
LOOP_LOGICAL_AXES(a) {
SERIAL_CHAR(' ', IAXIS_CHAR(a), ':');
SERIAL_ECHO(dac_perc(a));
SERIAL_ECHOPGM_P(PSTR(" ("), dac_amps(AxisEnum(a)), PSTR(")"));
}
#if HAS_EXTRUDERS
SERIAL_ECHOLNPGM_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")"));
#endif

View File

@@ -49,7 +49,7 @@ void I2CPositionEncoder::init(const uint8_t address, const AxisEnum axis) {
initialized = true;
SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(axis_codes[encoderAxis]), " axis, addr = ", address);
SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis, addr = ", address);
position = get_position();
}
@@ -67,7 +67,7 @@ void I2CPositionEncoder::update() {
/*
if (trusted) { //commented out as part of the note below
trusted = false;
SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(axis_codes[encoderAxis]), " axis encoder. Disengaging error correction until module is trusted again.");
SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis encoder. Disengaging error correction until module is trusted again.");
}
*/
return;
@@ -92,7 +92,7 @@ void I2CPositionEncoder::update() {
if (millis() - lastErrorTime > I2CPE_TIME_TRUSTED) {
trusted = true;
SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(axis_codes[encoderAxis]), " axis has been fault-free for set duration, reinstating error correction.");
SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis has been fault-free for set duration, reinstating error correction.");
//the encoder likely lost its place when the error occurred, so we'll reset and use the printer's
//idea of where it the axis is to re-initialize
@@ -172,7 +172,7 @@ void I2CPositionEncoder::update() {
float sumP = 0;
LOOP_L_N(i, I2CPE_ERR_PRST_ARRAY_SIZE) sumP += errPrst[i];
const int32_t errorP = int32_t(sumP * RECIPROCAL(I2CPE_ERR_PRST_ARRAY_SIZE));
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" : CORRECT ERR ", errorP * planner.mm_per_step[encoderAxis], "mm");
babystep.add_steps(encoderAxis, -LROUND(errorP));
errPrstIdx = 0;
@@ -192,7 +192,7 @@ void I2CPositionEncoder::update() {
if (ABS(error) > I2CPE_ERR_CNT_THRESH * planner.settings.axis_steps_per_mm[encoderAxis]) {
const millis_t ms = millis();
if (ELAPSED(ms, nextErrorCountTime)) {
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" : LARGE ERR ", error, "; diffSum=", diffSum);
errorCount++;
nextErrorCountTime = ms + I2CPE_ERR_CNT_DEBOUNCE_MS;
@@ -212,7 +212,7 @@ void I2CPositionEncoder::set_homed() {
homed = trusted = true;
#ifdef I2CPE_DEBUG
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" axis encoder homed, offset of ", zeroOffset, " ticks.");
#endif
}
@@ -223,7 +223,7 @@ void I2CPositionEncoder::set_unhomed() {
homed = trusted = false;
#ifdef I2CPE_DEBUG
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" axis encoder unhomed.");
#endif
}
@@ -231,7 +231,7 @@ void I2CPositionEncoder::set_unhomed() {
bool I2CPositionEncoder::passes_test(const bool report) {
if (report) {
if (H != I2CPE_MAG_SIG_GOOD) SERIAL_ECHOPGM("Warning. ");
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
serial_ternary(H == I2CPE_MAG_SIG_BAD, F(" axis "), F("magnetic strip "), F("encoder "));
switch (H) {
case I2CPE_MAG_SIG_GOOD:
@@ -252,7 +252,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) {
error = ABS(diff) > 10000 ? 0 : diff; // Huge error is a bad reading
if (report) {
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" axis target=", target, "mm; actual=", actual, "mm; err=", error, "mm");
}
@@ -262,7 +262,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) {
int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) {
if (!active) {
if (report) {
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" axis encoder not active!");
}
return 0;
@@ -287,7 +287,7 @@ int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) {
errorPrev = error;
if (report) {
SERIAL_CHAR(axis_codes[encoderAxis]);
SERIAL_CHAR(AXIS_CHAR(encoderAxis));
SERIAL_ECHOLNPGM(" axis target=", target, "; actual=", encoderCountInStepperTicksScaled, "; err=", error);
}
@@ -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);
}
@@ -657,7 +657,7 @@ void I2CPositionEncodersMgr::report_position(const int8_t idx, const bool units,
else {
if (noOffset) {
const int32_t raw_count = encoders[idx].get_raw_count();
SERIAL_CHAR(axis_codes[encoders[idx].get_axis()], ' ');
SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()], ' ');
for (uint8_t j = 31; j > 0; j--)
SERIAL_ECHO((bool)(0x00000001 & (raw_count >> j)));
@@ -712,7 +712,7 @@ void I2CPositionEncodersMgr::change_module_address(const uint8_t oldaddr, const
// and enable it (it will likely have failed initialization on power-up, before the address change).
const int8_t idx = idx_from_addr(newaddr);
if (idx >= 0 && !encoders[idx].get_active()) {
SERIAL_CHAR(axis_codes[encoders[idx].get_axis()]);
SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()]);
SERIAL_ECHOLNPGM(" axis encoder was not detected on printer startup. Trying again.");
encoders[idx].set_active(encoders[idx].passes_test(true));
}
@@ -814,7 +814,7 @@ void I2CPositionEncodersMgr::M860() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen_test(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_position(idx, hasU, hasO);
}
@@ -841,7 +841,7 @@ void I2CPositionEncodersMgr::M861() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_status(idx);
}
@@ -869,7 +869,7 @@ void I2CPositionEncodersMgr::M862() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) test_axis(idx);
}
@@ -900,7 +900,7 @@ void I2CPositionEncodersMgr::M863() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations);
}
@@ -976,7 +976,7 @@ void I2CPositionEncodersMgr::M865() {
if (!I2CPE_addr) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address());
}
@@ -1007,7 +1007,7 @@ void I2CPositionEncodersMgr::M866() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
if (hasR)
@@ -1045,7 +1045,7 @@ void I2CPositionEncodersMgr::M867() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
const bool ena = onoff == -1 ? !encoders[I2CPE_idx].get_ec_enabled() : !!onoff;
@@ -1081,7 +1081,7 @@ void I2CPositionEncodersMgr::M868() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) {
if (newThreshold != -9999)
@@ -1115,7 +1115,7 @@ void I2CPositionEncodersMgr::M869() {
if (I2CPE_idx == 0xFF) {
LOOP_LOGICAL_AXES(i) {
if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) {
if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) {
const uint8_t idx = idx_from_axis(AxisEnum(i));
if ((int8_t)idx >= 0) report_error(idx);
}

View File

@@ -261,32 +261,32 @@ class I2CPositionEncodersMgr {
static void report_error_count(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis is ", encoders[idx].get_error_count());
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", encoders[idx].get_error_count());
}
static void reset_error_count(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_error_count(0);
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis has been reset.");
SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis has been reset.");
}
static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_ec_enabled(enabled);
SERIAL_ECHOPGM("Error correction on ", AS_CHAR(axis_codes[axis]));
SERIAL_ECHOPGM("Error correction on ", AS_CHAR(AXIS_CHAR(axis)));
SERIAL_ECHO_TERNARY(encoders[idx].get_ec_enabled(), " axis is ", "en", "dis", "abled.\n");
}
static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_ec_threshold(newThreshold);
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis set to ", newThreshold, "mm.");
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis set to ", newThreshold, "mm.");
}
static void get_ec_threshold(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
const float threshold = encoders[idx].get_ec_threshold();
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis is ", threshold, "mm.");
SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", threshold, "mm.");
}
static int8_t idx_from_axis(const AxisEnum axis) {

View File

@@ -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]);
}

View File

@@ -567,7 +567,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
@@ -617,7 +617,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]);
}
@@ -626,7 +626,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]);
}

View File

@@ -41,8 +41,6 @@
#define PCT_TO_PWM(X) ((X) * 255 / 100)
#define PCT_TO_SERVO(X) ((X) * 180 / 100)
// #define _MAP(N,S1,S2,D1,D2) ((N)*_MAX((D2)-(D1),0)/_MAX((S2)-(S1),1)+(D1))
class SpindleLaser {
public:
static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); }

View File

@@ -65,15 +65,18 @@ void stepper_driver_backward_check() {
TEST_BACKWARD(I, 8);
TEST_BACKWARD(J, 9);
TEST_BACKWARD(K, 10);
TEST_BACKWARD(U, 11);
TEST_BACKWARD(V, 12);
TEST_BACKWARD(W, 13);
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(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(U, 11);
REPORT_BACKWARD(V, 12);
REPORT_BACKWARD(W, 13);
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(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

View File

@@ -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

View File

@@ -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;

View File

@@ -453,6 +453,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);

View File

@@ -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;

View File

@@ -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
#if SENSORLESS_STALLGUARD_DELAY
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
#endif
@@ -367,23 +367,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
@@ -397,7 +402,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);
@@ -437,32 +442,52 @@ 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);
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(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();
}
#if BOTH(FOAMCUTTER_XYUV, HAS_J_AXIS)
// Home J (after Y)
if (doJ) homeaxis(J_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));
TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(saved_motion_state));
#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
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
sync_plan_position();
@@ -545,6 +570,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
#if SENSORLESS_STALLGUARD_DELAY
safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle
#endif
@@ -568,7 +602,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)
};

View File

@@ -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;
@@ -557,7 +557,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:
@@ -605,14 +605,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);

View File

@@ -79,7 +79,7 @@ void GcodeSuite::G34() {
stepper.set_digipot_current(Z_AXIS, target_current);
#elif HAS_MOTOR_CURRENT_PWM
const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT);
const uint32_t previous_current = stepper.motor_current_setting[Z_AXIS];
const uint32_t previous_current = stepper.motor_current_setting[1]; // Z
stepper.set_digipot_current(1, target_current);
#elif HAS_MOTOR_CURRENT_DAC
const float target_current = parser.floatval('S', GANTRY_CALIBRATION_CURRENT);

View File

@@ -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_ECHOLNPGM(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_UMAX)
SERIAL_ECHOLNPGM(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]);
#endif
#endif
#if HAS_V_AXIS
#if ENABLED(CALIBRATION_MEASURE_VMIN)
SERIAL_ECHOLNPGM(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_VMAX)
SERIAL_ECHOLNPGM(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]);
#endif
#endif
#if HAS_W_AXIS
#if ENABLED(CALIBRATION_MEASURE_WMIN)
SERIAL_ECHOLNPGM(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_WMAX)
SERIAL_ECHOLNPGM(" " 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();
}

View File

@@ -47,23 +47,17 @@ void GcodeSuite::M425() {
bool noArgs = true;
auto axis_can_calibrate = [](const uint8_t a) {
#define _CAN_CASE(N) case N##_AXIS: return AXIS_CAN_CALIBRATE(N);
switch (a) {
default: return false;
LINEAR_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)
);
MAIN_AXIS_MAP(_CAN_CASE)
}
};
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,10 +82,8 @@ 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)) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a)));
SERIAL_EOL();
LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) {
SERIAL_ECHOLNPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_distance_mm((AxisEnum)a));
}
#ifdef BACKLASH_SMOOTHING_MM
@@ -101,9 +93,8 @@ 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))) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.get_measurement(AxisEnum(a)));
LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_measurement((AxisEnum)a));
}
}
else
@@ -120,13 +111,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))
)
);
}

View File

@@ -44,8 +44,8 @@
void GcodeSuite::M666() {
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
bool is_err = false, is_set = false;
LOOP_LINEAR_AXES(i) {
if (parser.seen(AXIS_CHAR(i))) {
LOOP_NUM_AXES(i) {
if (parser.seenval(AXIS_CHAR(i))) {
is_set = true;
const float v = parser.value_linear_units();
if (v > 0)

View File

@@ -122,7 +122,7 @@
* S<percent> : Speed factor percentage.
*/
void GcodeSuite::M201() {
if (!parser.seen("T" LOGICAL_AXES_STRING TERN_(XY_FREQUENCY_LIMIT, "FS")))
if (!parser.seen("T" STR_AXES_LOGICAL TERN_(XY_FREQUENCY_LIMIT, "FS")))
return M201_report();
const int8_t target_extruder = get_target_extruder_from_command();
@@ -134,9 +134,9 @@ void GcodeSuite::M201() {
#endif
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) {
const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
if (parser.seenval(AXIS_CHAR(i))) {
const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i);
planner.set_max_acceleration(a, parser.value_axis_units(a));
}
}
}
@@ -144,13 +144,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])
@@ -173,29 +176,32 @@ void GcodeSuite::M201_report(const bool forReplay/*=true*/) {
* With multiple extruders use T to specify which one.
*/
void GcodeSuite::M203() {
if (!parser.seen("T" LOGICAL_AXES_STRING))
if (!parser.seen("T" STR_AXES_LOGICAL))
return M203_report();
const int8_t target_extruder = get_target_extruder_from_command();
if (target_extruder < 0) return;
LOOP_LOGICAL_AXES(i)
if (parser.seenval(axis_codes[i])) {
const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i);
planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
if (parser.seenval(AXIS_CHAR(i))) {
const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i);
planner.set_max_feedrate(a, parser.value_axis_units(a));
}
}
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])
@@ -282,9 +288,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)
@@ -298,9 +307,10 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
"Advanced (B<min_segment_time_us> S<min_feedrate> T<min_travel_feedrate>"
TERN_(HAS_JUNCTION_DEVIATION, " J<junc_dev>")
#if HAS_CLASSIC_JERK
LINEAR_AXIS_GANG(
NUM_AXIS_GANG(
" X<max_jerk>", " Y<max_jerk>", " Z<max_jerk>",
" " STR_I "<max_jerk>", " " STR_J "<max_jerk>", " " STR_K "<max_jerk>"
" " STR_I "<max_jerk>", " " STR_J "<max_jerk>", " " STR_K "<max_jerk>",
" " STR_U "<max_jerk>", " " STR_V "<max_jerk>", " " STR_W "<max_jerk>"
)
#endif
TERN_(HAS_CLASSIC_E_JERK, " E<max_jerk>")
@@ -314,13 +324,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)

View File

@@ -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[speed] Fan Speed 0-255
* D[seconds] 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)
, SP_I_STR, I_AXIS_UNIT(toolchange_settings.change_point.i)
, SP_J_STR, J_AXIS_UNIT(toolchange_settings.change_point.j)
, SP_K_STR, K_AXIS_UNIT(toolchange_settings.change_point.k)
, 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)

View File

@@ -47,8 +47,8 @@ void GcodeSuite::M281() {
return;
}
#endif
if (parser.seen('L')) servo_angles[servo_index][0] = parser.value_int();
if (parser.seen('U')) servo_angles[servo_index][1] = parser.value_int();
if (parser.seenval('L')) servo_angles[servo_index][0] = parser.value_int();
if (parser.seenval('U')) servo_angles[servo_index][1] = parser.value_int();
}
else
SERIAL_ERROR_MSG("Servo ", servo_index, " out of range");

View File

@@ -36,9 +36,9 @@
*/
void GcodeSuite::M304() {
if (!parser.seen("PID")) return M304_report();
if (parser.seen('P')) thermalManager.temp_bed.pid.Kp = parser.value_float();
if (parser.seen('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float());
if (parser.seen('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float());
if (parser.seenval('P')) thermalManager.temp_bed.pid.Kp = parser.value_float();
if (parser.seenval('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float());
if (parser.seenval('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float());
}
void GcodeSuite::M304_report(const bool forReplay/*=true*/) {

View File

@@ -52,19 +52,19 @@ void GcodeSuite::M305() {
if (t_index >= (USER_THERMISTORS) || (do_set && t_index < 0))
SERIAL_ECHO_MSG("!Invalid index. (0 <= P <= ", USER_THERMISTORS - 1, ")");
else if (do_set) {
if (parser.seen('R')) // Pullup resistor value
if (parser.seenval('R')) // Pullup resistor value
if (!thermalManager.set_pull_up_res(t_index, parser.value_float()))
SERIAL_ECHO_MSG("!Invalid series resistance. (0 < R < 1000000)");
if (parser.seen('T')) // Resistance at 25C
if (parser.seenval('T')) // Resistance at 25C
if (!thermalManager.set_res25(t_index, parser.value_float()))
SERIAL_ECHO_MSG("!Invalid 25C resistance. (0 < T < 10000000)");
if (parser.seen('B')) // Beta value
if (parser.seenval('B')) // Beta value
if (!thermalManager.set_beta(t_index, parser.value_float()))
SERIAL_ECHO_MSG("!Invalid beta. (0 < B < 1000000)");
if (parser.seen('C')) // Steinhart-Hart C coefficient
if (parser.seenval('C')) // Steinhart-Hart C coefficient
if (!thermalManager.set_sh_coeff(t_index, parser.value_float()))
SERIAL_ECHO_MSG("!Invalid Steinhart-Hart C coeff. (-0.01 < C < +0.01)");
} // If not setting then report parameters

View File

@@ -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.
@@ -43,11 +43,11 @@ void GcodeSuite::M92() {
if (target_extruder < 0) return;
// No arguments? Show M92 report.
if (!parser.seen(LOGICAL_AXES_STRING TERN_(MAGIC_NUMBERS_GCODE, "HL")))
if (!parser.seen(STR_AXES_LOGICAL TERN_(MAGIC_NUMBERS_GCODE, "HL")))
return M92_report(true, target_extruder);
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) {
if (parser.seenval(AXIS_CHAR(i))) {
if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
else {
@@ -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

View File

@@ -49,7 +49,7 @@ void GcodeSuite::M111() {
LOOP_L_N(i, COUNT(debug_strings)) {
if (TEST(marlin_debug_flags, i)) {
if (comma++) SERIAL_CHAR(',');
SERIAL_ECHOPGM_P((char*)pgm_read_ptr(&debug_strings[i]));
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&debug_strings[i]));
}
}
}

View File

@@ -23,6 +23,7 @@
#include "../gcode.h"
#include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers
#include "../../lcd/marlinui.h"
#include "../../module/motion.h" // for e_axis_mask
#include "../../module/stepper.h"
#if ENABLED(AUTO_BED_LEVELING_UBL)
@@ -43,16 +44,19 @@ inline stepper_flags_t selected_axis_bits() {
selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e));
}
else
selected.bits = selected.e_bits();
selected.bits = e_axis_mask;
}
#endif
selected.bits |= LINEAR_AXIS_GANG(
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,10 +73,10 @@ void do_enable(const stepper_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));
DEBUG_ECHOLNPGM("Enabled ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits));
also_enabled |= enable_overlap[a];
}
}
@@ -89,7 +93,7 @@ void do_enable(const stepper_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_CHAR(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,14 +129,8 @@ void GcodeSuite::M17() {
stepper.enable_e_steppers();
}
#endif
LINEAR_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)
);
LOOP_NUM_AXES(a)
if (parser.seen_test(AXIS_CHAR(a))) stepper.enable_axis((AxisEnum)a);
}
}
else {
@@ -149,9 +147,9 @@ void try_to_disable(const stepper_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]), " ... ");
DEBUG_ECHOPGM("Try to disable ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable
DEBUG_ECHOPGM("OK");
still_enabled &= ~(_BV(a) | enable_overlap[a]); // If actually disabled, clear one or more tracked bits
@@ -178,7 +176,7 @@ void try_to_disable(const stepper_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_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[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,9 +185,9 @@ void try_to_disable(const stepper_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]);
SERIAL_CHAR(AXIS_CHAR(a));
overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
}
}
@@ -238,14 +236,8 @@ void GcodeSuite::M18_M84() {
stepper.disable_e_steppers();
}
#endif
LINEAR_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)
);
LOOP_NUM_AXES(a)
if (parser.seen_test(AXIS_CHAR(a))) stepper.disable_axis((AxisEnum)a);
}
}
else

View File

@@ -48,7 +48,7 @@ void GcodeSuite::M280() {
const int anew = parser.value_int();
if (anew >= 0) {
#if ENABLED(POLARGRAPH)
if (parser.seen('T')) { // (ms) Total duration of servo move
if (parser.seenval('T')) { // (ms) Total duration of servo move
const int16_t t = constrain(parser.value_int(), 0, 10000);
const int aold = servo[servo_index].read();
millis_t now = millis();

View File

@@ -93,7 +93,7 @@ void GcodeSuite::M3_M4(const bool is_M4) {
// Laser power in inline mode
cutter.inline_direction(is_M4); // Should always be unused
#if ENABLED(SPINDLE_LASER_USE_PWM)
if (parser.seen('O')) {
if (parser.seenval('O')) {
cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0);
cutter.inline_ocr_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t)
}

View File

@@ -27,35 +27,45 @@
#include "../gcode.h"
#include "../../module/stepper.h"
#if NUM_AXES == XYZ && EXTRUDERS >= 1
#define HAS_M350_B_PARAM 1 // "5th axis" (after E0) for an original XYZEB setup.
#if AXIS_COLLISION('B')
#error "M350 parameter 'B' collision with axis name."
#endif
#endif
/**
* M350: Set axis microstepping modes. S sets mode for all drivers.
*
* Warning: Steps-per-unit remains unchanged.
*/
void GcodeSuite::M350() {
if (parser.seen('S')) LOOP_LE_N(i, 4) stepper.microstep_mode(i, parser.value_byte());
LOOP_LOGICAL_AXES(i) if (parser.seen(axis_codes[i])) stepper.microstep_mode(i, parser.value_byte());
if (parser.seen('B')) stepper.microstep_mode(4, parser.value_byte());
if (parser.seen('S')) LOOP_DISTINCT_AXES(i) stepper.microstep_mode(i, parser.value_byte());
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_mode(i, parser.value_byte());
TERN_(HAS_M350_B_PARAM, if (parser.seenval('B')) stepper.microstep_mode(E_AXIS + 1, parser.value_byte()));
stepper.microstep_readings();
}
/**
* M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B
* M351: Toggle MS1 MS2 pins directly with axis codes X Y Z . . . E [B]
* S# determines MS1, MS2 or MS3, X# sets the pin high/low.
*
* Parameter 'B' sets "5th axis" (after E0) only for an original XYZEB setup.
*/
void GcodeSuite::M351() {
const int8_t bval = TERN(HAS_M350_B_PARAM, parser.byteval('B', -1), -1); UNUSED(bval);
if (parser.seenval('S')) switch (parser.value_byte()) {
case 1:
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1, -1);
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, bval != 0, -1, -1));
break;
case 2:
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte(), -1);
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, bval != 0, -1));
break;
case 3:
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, -1, parser.value_byte());
if (parser.seenval('B')) stepper.microstep_ms(4, -1, -1, parser.value_byte());
LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, -1, parser.value_byte());
TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, -1, bval != 0));
break;
}
stepper.microstep_readings();

View File

@@ -64,7 +64,7 @@
void GcodeSuite::M605() {
planner.synchronize();
if (parser.seen('S')) {
if (parser.seenval('S')) {
const DualXMode previous_mode = dual_x_carriage_mode;
dual_x_carriage_mode = (DualXMode)parser.value_byte();
@@ -78,8 +78,8 @@
case DXC_DUPLICATION_MODE:
// Set the X offset, but no less than the safety gap
if (parser.seen('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
if (parser.seen('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
if (parser.seenval('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
if (parser.seenval('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
// Always switch back to tool 0
if (active_extruder != 0) tool_change(0);
break;
@@ -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();

View File

@@ -25,7 +25,7 @@
#if HAS_L64XX
#if AXIS_COLLISION('I')
#error "M906 parameter collision with axis name."
#error "M906 parameter 'I' collision with axis name."
#endif
#include "../../gcode.h"
@@ -211,7 +211,7 @@ void L64XX_report_current(L64XX &motor, const L64XX_axis_t axis) {
* 1 - monitor only X2, Y2, Z2
* 2 - monitor only Z3
* 3 - monitor only Z4
* Xxxx, Yxxx, Zxxx, Exxx - axis to change (optional)
* Xxxx, Yxxx, Zxxx, Axxx, Bxxx, Cxxx, Uxxx, Vxxx, Wxxx, Exxx - axis to change (optional)
* L6474 - current in mA (4A max)
* All others - 0-255
*
@@ -236,7 +236,7 @@ void GcodeSuite::M906() {
constexpr int8_t index = -1;
#endif
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(axis_codes[i])) {
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(AXIS_CHAR(i))) {
report_current = false;
@@ -285,6 +285,25 @@ void GcodeSuite::M906() {
break;
#endif
#if AXIS_IS_L64XX(I)
case I_AXIS: L6470_SET_KVAL_HOLD(I); break;
#endif
#if AXIS_IS_L64XX(J)
case J_AXIS: L6470_SET_KVAL_HOLD(J); break;
#endif
#if AXIS_IS_L64XX(K)
case K_AXIS: L6470_SET_KVAL_HOLD(K); break;
#endif
#if AXIS_IS_L64XX(U)
case U_AXIS: L6470_SET_KVAL_HOLD(U); break;
#endif
#if AXIS_IS_L64XX(V)
case V_AXIS: L6470_SET_KVAL_HOLD(V); break;
#endif
#if AXIS_IS_L64XX(W)
case W_AXIS: L6470_SET_KVAL_HOLD(W); break;
#endif
#if 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)
case E_AXIS: {
const int8_t eindex = get_target_e_stepper_from_command(-2);
@@ -346,6 +365,24 @@ void GcodeSuite::M906() {
#if AXIS_IS_L64XX(Z4)
L64XX_REPORT_CURRENT(Z4);
#endif
#if AXIS_IS_L64XX(I)
L64XX_REPORT_CURRENT(I);
#endif
#if AXIS_IS_L64XX(J)
L64XX_REPORT_CURRENT(J);
#endif
#if AXIS_IS_L64XX(K)
L64XX_REPORT_CURRENT(K);
#endif
#if AXIS_IS_L64XX(U)
L64XX_REPORT_CURRENT(U);
#endif
#if AXIS_IS_L64XX(V)
L64XX_REPORT_CURRENT(V);
#endif
#if AXIS_IS_L64XX(W)
L64XX_REPORT_CURRENT(W);
#endif
#if AXIS_IS_L64XX(E0)
L64XX_REPORT_CURRENT(E0);
#endif

View File

@@ -44,14 +44,14 @@ void GcodeSuite::M486() {
cancelable.object_count = parser.intval('T', 1);
}
if (parser.seen('S'))
if (parser.seenval('S'))
cancelable.set_active_object(parser.value_int());
if (parser.seen('C')) cancelable.cancel_active_object();
if (parser.seen('P')) cancelable.cancel_object(parser.value_int());
if (parser.seenval('P')) cancelable.cancel_object(parser.value_int());
if (parser.seen('U')) cancelable.uncancel_object(parser.value_int());
if (parser.seenval('U')) cancelable.uncancel_object(parser.value_int());
}
#endif // CANCEL_OBJECTS

View File

@@ -45,9 +45,10 @@
* X, Y, Z : Specify axes to move during cleaning. Default: ALL.
*/
void GcodeSuite::G12() {
// Don't allow nozzle cleaning without homing first
if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS)))
return;
constexpr main_axes_bits_t clean_axis_mask = main_axes_mask & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS);
if (homing_needed_error(clean_axis_mask)) return;
#ifdef WIPE_SEQUENCE_COMMANDS
if (!parser.seen_any()) {

View File

@@ -39,53 +39,77 @@
#endif
/**
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E]
* B<current> - Special case for 4th (E) axis
* S<current> - Special case to set first 3 axes
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [U] [V] [W] [E]
* B<current> - Special case for E1 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451)
* C<current> - Special case for E2 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451)
* S<current> - Set current in mA for all axes (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451), or
* Set percentage of max current for all axes (Requires HAS_DIGIPOT_DAC)
*/
void GcodeSuite::M907() {
#if HAS_MOTOR_CURRENT_SPI
if (!parser.seen("BS" LOGICAL_AXES_STRING))
if (!parser.seen("BS" STR_AXES_LOGICAL))
return M907_report();
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[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());
if (parser.seenval('S')) LOOP_L_N(i, MOTOR_CURRENT_COUNT) 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()); // X Y Z (I J K U V W) E (map to drivers according to DIGIPOT_CHANNELS. Default with NUM_AXES 3: map X Y Z E to X Y Z E0)
// Additional extruders use B,C.
// TODO: Change these parameters because 'E' is used and D should be reserved for debugging. B<index>?
#if E_STEPPERS >= 2
if (parser.seenval('B')) stepper.set_digipot_current(E_AXIS + 1, parser.value_int());
#if E_STEPPERS >= 3
if (parser.seenval('C')) stepper.set_digipot_current(E_AXIS + 2, parser.value_int());
#endif
#endif
#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)
#define HAS_X_Y_XY_I_J_K_U_V_W 1
#endif
#if HAS_X_Y_XY_I_J_K_U_V_W || ANY_PIN(MOTOR_CURRENT_PWM_E, MOTOR_CURRENT_PWM_Z)
if (!parser.seen("S"
#if HAS_X_Y_XY_I_J_K_U_V_W
"XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W")
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
"Z"
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
"E"
#endif
)) return M907_report();
if (parser.seenval('S')) LOOP_L_N(a, MOTOR_CURRENT_COUNT) stepper.set_digipot_current(a, parser.value_int());
#if HAS_X_Y_XY_I_J_K_U_V_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)
"Z"
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
"E"
if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int());
#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());
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int());
#endif
#endif // HAS_MOTOR_CURRENT_PWM
#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());
// Additional extruders use B,C,D for channels 4,5,6.
// TODO: Change these parameters because 'E' is used. B<index>?
#if HAS_EXTRUDERS
for (uint8_t i = E_AXIS + 1; i < DIGIPOT_I2C_NUM_CHANNELS; i++)
if (parser.seenval('S')) LOOP_L_N(q, DIGIPOT_I2C_NUM_CHANNELS) digipot_i2c.set_current(q, parser.value_float());
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); // X Y Z (I J K U V W) E (map to drivers according to pots adresses. Default with NUM_AXES 3 X Y Z E: map to X Y Z E0)
// Additional extruders use B,C,D.
// TODO: Change these parameters because 'E' is used and because 'D' should be reserved for debugging. B<index>?
#if E_STEPPERS >= 2
for (uint8_t i = E_AXIS + 1; i < _MAX(DIGIPOT_I2C_NUM_CHANNELS, (NUM_AXES + 3)); i++)
if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c.set_current(i, parser.value_float());
#endif
#endif
@@ -93,9 +117,9 @@ void GcodeSuite::M907() {
#if HAS_MOTOR_CURRENT_DAC
if (parser.seenval('S')) {
const float dac_percent = parser.value_float();
LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent);
LOOP_LOGICAL_AXES(i) 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()); // X Y Z (I J K U V W) E (map to drivers according to DAC_STEPPER_ORDER. Default with NUM_AXES 3: X Y Z E map to X Y Z E0)
#endif
}
@@ -104,19 +128,25 @@ 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)
SERIAL_ECHOLN(stepper.motor_current_setting[4]);
#if E_STEPPERS >= 2
SERIAL_ECHOPGM_P(PSTR(" B"), stepper.motor_current_setting[E_AXIS + 1] // B (maps to E1 with NUM_AXES 3 according to DIGIPOT_CHANNELS)
#if E_STEPPERS >= 3
, PSTR(" C"), stepper.motor_current_setting[E_AXIS + 2] // C (mapping to E2 must be defined by DIGIPOT_CHANNELS)
#endif
);
#endif
SERIAL_EOL();
#endif
}

View File

@@ -45,10 +45,10 @@
*/
void GcodeSuite::M260() {
// Set the target address
if (parser.seen('A')) i2c.address(parser.value_byte());
if (parser.seenval('A')) i2c.address(parser.value_byte());
// Add a new byte to the buffer
if (parser.seen('B')) i2c.addbyte(parser.value_byte());
if (parser.seenval('B')) i2c.addbyte(parser.value_byte());
// Flush the buffer to the bus
if (parser.seen('S')) i2c.send();
@@ -63,7 +63,7 @@ void GcodeSuite::M260() {
* Usage: M261 A<slave device address base 10> B<number of bytes> S<style>
*/
void GcodeSuite::M261() {
if (parser.seen('A')) i2c.address(parser.value_byte());
if (parser.seenval('A')) i2c.address(parser.value_byte());
const uint8_t bytes = parser.byteval('B', 1), // Bytes to request
style = parser.byteval('S'); // Serial output style (ASCII, HEX etc)

View File

@@ -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_ECHOLNPGM_P(
LIST_N(DOUBLE(LINEAR_AXES), PSTR(" : X"), pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k)
LIST_N(DOUBLE(NUM_AXES),
SP_X_LBL, pos.x, SP_Y_LBL, pos.y, SP_Z_LBL, pos.z,
SP_I_LBL, pos.i, SP_J_LBL, pos.j, SP_K_LBL, pos.k,
SP_U_LBL, pos.u, SP_V_LBL, pos.v, SP_W_LBL, pos.w
)
#if HAS_EXTRUDERS
, SP_E_LBL, pos.e
#endif

View File

@@ -68,10 +68,10 @@ 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(STR_AXES_MAIN)) {
DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot);
LOOP_LINEAR_AXES(i) {
destination[i] = parser.seen(AXIS_CHAR(i))
LOOP_NUM_AXES(i) {
destination[i] = parser.seenval(AXIS_CHAR(i))
? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i)
: current_position[i];
DEBUG_CHAR(' ', AXIS_CHAR(i));

View File

@@ -52,6 +52,9 @@
* A<pos> = Override park position A (requires AXIS*_NAME 'A')
* B<pos> = Override park position B (requires AXIS*_NAME 'B')
* C<pos> = Override park position C (requires AXIS*_NAME 'C')
* U<pos> = Override park position U (requires AXIS*_NAME 'U')
* V<pos> = Override park position V (requires AXIS*_NAME 'V')
* W<pos> = Override park position W (requires AXIS*_NAME 'W')
* Z<linear> = 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];

View File

@@ -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

View File

@@ -48,7 +48,7 @@ void GcodeSuite::M603() {
if (target_extruder < 0) return;
// Unload length
if (parser.seen('U')) {
if (parser.seenval('U')) {
fc_settings[target_extruder].unload_length = ABS(parser.value_axis_units(E_AXIS));
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
NOMORE(fc_settings[target_extruder].unload_length, EXTRUDE_MAXLENGTH);
@@ -56,7 +56,7 @@ void GcodeSuite::M603() {
}
// Load length
if (parser.seen('L')) {
if (parser.seenval('L')) {
fc_settings[target_extruder].load_length = ABS(parser.value_axis_units(E_AXIS));
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
NOMORE(fc_settings[target_extruder].load_length, EXTRUDE_MAXLENGTH);

View File

@@ -106,7 +106,7 @@ void GcodeSuite::M701() {
#else
constexpr float purge_length = ADVANCED_PAUSE_PURGE_LENGTH,
slow_load_length = FILAMENT_CHANGE_SLOW_LOAD_LENGTH;
const float fast_load_length = ABS(parser.seen('L') ? parser.value_axis_units(E_AXIS)
const float fast_load_length = ABS(parser.seenval('L') ? parser.value_axis_units(E_AXIS)
: fc_settings[active_extruder].load_length);
load_filament(
slow_load_length, fast_load_length, purge_length,

View File

@@ -48,7 +48,7 @@ void GcodeSuite::M412() {
if (seenR || seenS) runout.reset();
if (seenS) runout.enabled = parser.value_bool();
#if HAS_FILAMENT_RUNOUT_DISTANCE
if (parser.seen('D')) runout.set_runout_distance(parser.value_linear_units());
if (parser.seenval('D')) runout.set_runout_distance(parser.value_linear_units());
#endif
}
else {

View File

@@ -35,7 +35,7 @@ void GcodeSuite::M122() {
xyze_bool_t print_axis = ARRAY_N_1(LOGICAL_AXES, false);
bool print_all = true;
LOOP_LOGICAL_AXES(i) if (parser.seen_test(axis_codes[i])) { print_axis[i] = true; print_all = false; }
LOOP_LOGICAL_AXES(i) if (parser.seen_test(AXIS_CHAR(i))) { print_axis[i] = true; print_all = false; }
if (print_all) LOOP_LOGICAL_AXES(i) print_axis[i] = true;

View File

@@ -25,7 +25,7 @@
#if HAS_STEALTHCHOP
#if AXIS_COLLISION('I')
#error "M569 parameter collision with axis name."
#error "M569 parameter 'I' collision with axis name."
#endif
#include "../../gcode.h"
@@ -53,7 +53,7 @@ static void set_stealth_status(const bool enable, const int8_t eindex) {
constexpr int8_t index = -1;
#endif
LOOP_LOGICAL_AXES(i) if (parser.seen(axis_codes[i])) {
LOOP_LOGICAL_AXES(i) if (parser.seen(AXIS_CHAR(i))) {
switch (i) {
case X_AXIS:
TERN_(X_HAS_STEALTHCHOP, if (index < 0 || index == 0) TMC_SET_STEALTH(X));
@@ -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();
}
@@ -186,11 +204,24 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) {
if (TERN0(Z3_HAS_STEALTHCHOP, stepperZ3.get_stored_stealthChop())) { say_M569(forReplay, F("I2 Z"), true); }
if (TERN0(Z4_HAS_STEALTHCHOP, stepperZ4.get_stored_stealthChop())) { say_M569(forReplay, F("I3 Z"), 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 HAS_I_AXIS
if (TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_I_STR), true); }
#endif
#if HAS_J_AXIS
if (TERN0(J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_J_STR), true); }
#endif
#if HAS_K_AXIS
if (TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_K_STR), true); }
#endif
#if HAS_U_AXIS
if (TERN0(U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_U_STR), true); }
#endif
#if HAS_V_AXIS
if (TERN0(V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_V_STR), true); }
#endif
#if HAS_W_AXIS
if (TERN0(W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_W_STR), true); }
#endif
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); }
if (TERN0(E2_HAS_STEALTHCHOP, stepperE2.get_stored_stealthChop())) { say_M569(forReplay, F("T2 E"), true); }

View File

@@ -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.)
@@ -63,7 +66,7 @@ void GcodeSuite::M906() {
constexpr int8_t index = -1;
#endif
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(axis_codes[i])) {
LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(AXIS_CHAR(i))) {
report = false;
switch (i) {
#if AXIS_IS_TMC(X) || AXIS_IS_TMC(X2)
@@ -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

View File

@@ -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));
@@ -261,7 +288,7 @@
#elif AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z)
constexpr uint8_t index = 0;
#endif
LOOP_LOGICAL_AXES(i) if (int32_t value = parser.longval(axis_codes[i])) {
LOOP_LOGICAL_AXES(i) if (int32_t value = parser.longval(AXIS_CHAR(i))) {
report = false;
switch (i) {
#if X_HAS_STEALTHCHOP || X2_HAS_STEALTHCHOP
@@ -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

View File

@@ -25,7 +25,7 @@
#if HAS_TRINAMIC_CONFIG
#if AXIS_COLLISION('I')
#error "M919 parameter collision with axis name."
#error "M919 parameter 'I' collision with axis name."
#endif
#include "../../gcode.h"
@@ -112,13 +112,13 @@ void GcodeSuite::M919() {
int8_t eindex = -1;
#endif
bool report = true;
LOOP_LOGICAL_AXES(i) if (parser.seen_test(axis_codes[i])) {
LOOP_LOGICAL_AXES(i) if (parser.seen_test(AXIS_CHAR(i))) {
report = false;
// Get the chopper timing for the specified axis and index
switch (i) {
default: // A specified axis isn't Trinamic
SERIAL_ECHOLNPGM("?Axis ", AS_CHAR(axis_codes[i]), " has no TMC drivers.");
SERIAL_ECHOLNPGM("?Axis ", AS_CHAR(AXIS_CHAR(i)), " has no TMC drivers.");
break;
#if AXIS_IS_TMC(X) || AXIS_IS_TMC(X2)

View File

@@ -88,7 +88,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)
@@ -179,7 +182,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)

View File

@@ -339,7 +339,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
@@ -365,7 +365,8 @@ public:
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

View File

@@ -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);

View File

@@ -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);
}
@@ -74,7 +74,7 @@ void GcodeSuite::G92() {
#if ENABLED(POWER_LOSS_RECOVERY)
case 9: // G92.9 - Set Current Position directly (like Marlin 1.0)
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) {
if (parser.seenval(AXIS_CHAR(i))) {
if (TERN1(HAS_EXTRUDERS, i != E_AXIS))
sync_XYZE = true;
else {
@@ -88,7 +88,7 @@ void GcodeSuite::G92() {
case 0:
LOOP_LOGICAL_AXES(i) {
if (parser.seenval(axis_codes[i])) {
if (parser.seenval(AXIS_CHAR(i))) {
const float l = parser.value_axis_units((AxisEnum)i), // Given axis coordinate value, converted to millimeters
v = TERN0(HAS_EXTRUDERS, i == E_AXIS) ? l : LOGICAL_TO_NATIVE(l, i), // Axis position in NATIVE space (applying the existing offset)
d = v - current_position[i]; // How much is the current axis position altered by?

View File

@@ -39,14 +39,11 @@
*/
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());
LOOP_NUM_AXES(a)
if (parser.seenval(AXIS_CHAR(a))) set_home_offset((AxisEnum)a, parser.value_axis_units((AxisEnum)a));
#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
if (parser.seenval('T')) set_home_offset(A_AXIS, parser.value_float()); // Theta
if (parser.seenval('P')) set_home_offset(B_AXIS, parser.value_float()); // Psi
#endif
report_current_position();
@@ -56,13 +53,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 +85,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 +97,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();

View File

@@ -34,10 +34,10 @@
#include "../../core/debug_out.h"
#endif
void report_all_axis_pos(const xyze_pos_t &pos, const uint8_t n=XYZE, const uint8_t precision=3) {
void report_all_axis_pos(const xyze_pos_t &pos, const uint8_t n=LOGICAL_AXES, const uint8_t precision=3) {
char str[12];
LOOP_L_N(a, n) {
SERIAL_CHAR(' ', axis_codes[a], ':');
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_LBL[a]));
if (pos[a] >= 0) SERIAL_CHAR(' ');
SERIAL_ECHO(dtostrf(pos[a], 1, precision, str));
}
@@ -47,10 +47,7 @@
void report_linear_axis_pos(const xyz_pos_t &pos, const uint8_t precision=3) {
char str[12];
LOOP_LINEAR_AXES(a) {
SERIAL_CHAR(' ', AXIS_CHAR(a), ':');
SERIAL_ECHO(dtostrf(pos[a], 1, precision, str));
}
LOOP_NUM_AXES(a) SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_LBL[a]), dtostrf(pos[a], 1, precision, str));
SERIAL_EOL();
}
@@ -134,6 +131,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
@@ -163,8 +169,7 @@
SERIAL_ECHOPGM("Stepper:");
LOOP_LOGICAL_AXES(i) {
SERIAL_CHAR(' ', axis_codes[i], ':');
SERIAL_ECHO(stepper.position((AxisEnum)i));
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_LBL[i]), stepper.position((AxisEnum)i));
}
SERIAL_EOL();
@@ -184,7 +189,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);

View File

@@ -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

View File

@@ -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(STR_AXES_MAIN)
) {
const float echange = destination.e - current_position.e;
// Is this a retract or recover move?

View File

@@ -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);

View File

@@ -25,7 +25,7 @@
#if ENABLED(BEZIER_CURVE_SUPPORT)
#if AXIS_COLLISION('I') || AXIS_COLLISION('J')
#error "G5 parameter collision with axis name."
#error "G5 parameter 'I' or 'J' collision with axis name."
#endif
#include "../../module/motion.h"

View File

@@ -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(STR_AXES_MAIN) || parser.seen('R')) {
SERIAL_ECHO_START();
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)

View File

@@ -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';

View File

@@ -225,7 +225,7 @@ public:
#endif // !FASTER_GCODE_PARSER
// Seen any axis parameter
static bool seen_axis() { return seen(LOGICAL_AXES_STRING); }
static bool seen_axis() { return seen(STR_AXES_LOGICAL); }
#if ENABLED(GCODE_QUOTED_STRINGS)
static char* unescape_string(char* &src);
@@ -309,13 +309,18 @@ public:
}
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 @@ public:
#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()); }

View File

@@ -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

View File

@@ -74,7 +74,7 @@ void GcodeSuite::M306_report(const bool forReplay/*=true*/) {
#if ENABLED(MPC_INCLUDE_FAN)
SERIAL_ECHOPAIR_F(" F", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4);
#endif
SERIAL_ECHOPAIR_F(" M", constants.filament_heat_capacity_permm, 4);
SERIAL_ECHOPAIR_F(" H", constants.filament_heat_capacity_permm, 4);
SERIAL_EOL();
}
}

View File

@@ -666,7 +666,7 @@
#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
*/
#ifdef LINEAR_AXES
@@ -674,22 +674,28 @@
#define LINEAR_AXES_WARNING 1
#endif
#ifdef K_DRIVER_TYPE
#define LINEAR_AXES 6
#ifdef W_DRIVER_TYPE
#define NUM_AXES 9
#elif defined(V_DRIVER_TYPE)
#define NUM_AXES 8
#elif defined(U_DRIVER_TYPE)
#define NUM_AXES 7
#elif defined(K_DRIVER_TYPE)
#define NUM_AXES 6
#elif defined(J_DRIVER_TYPE)
#define LINEAR_AXES 5
#define NUM_AXES 5
#elif defined(I_DRIVER_TYPE)
#define LINEAR_AXES 4
#define NUM_AXES 4
#elif defined(Z_DRIVER_TYPE)
#define LINEAR_AXES 3
#define NUM_AXES 3
#elif defined(Y_DRIVER_TYPE)
#define LINEAR_AXES 2
#define NUM_AXES 2
#else
#define LINEAR_AXES 1
#define NUM_AXES 1
#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
#ifdef Z4_DRIVER_TYPE
#define NUM_Z_STEPPERS 4
@@ -700,12 +706,21 @@
#else
#define NUM_Z_STEPPERS 1
#endif
#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
@@ -863,14 +878,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 NUM_AXES >= 3
#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
/**
@@ -888,7 +947,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
@@ -1118,6 +1177,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

View File

@@ -911,30 +911,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_STEPPERS
#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_STEPPERS
#undef CNC_WORKSPACE_PLANES
#if NUM_AXES < 2
#undef STEALTHCHOP_Y
#endif
#endif
#endif
#endif
#endif
#endif

View File

@@ -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

View File

@@ -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
@@ -806,6 +806,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)
@@ -818,6 +824,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
/**
@@ -1453,16 +1465,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
/**
@@ -1470,33 +1484,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
@@ -1886,49 +1943,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
@@ -1951,9 +2020,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
@@ -2453,7 +2522,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
@@ -2475,6 +2546,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)
@@ -2498,6 +2578,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
@@ -2994,6 +3086,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
@@ -3039,6 +3137,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
@@ -3068,6 +3173,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)
@@ -3129,6 +3240,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
@@ -3158,6 +3275,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)
@@ -3184,6 +3310,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
@@ -3264,6 +3403,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
@@ -3281,6 +3456,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
@@ -3349,6 +3527,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)
@@ -3369,6 +3553,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
@@ -3382,8 +3567,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
/**
@@ -3407,7 +3592,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;
@@ -3426,7 +3611,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
@@ -3872,6 +4057,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
@@ -3944,7 +4138,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
@@ -3953,3 +4147,8 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
#elif ENABLED(DISABLE_JTAG) && !defined(JTAG_DISABLE)
#error "DISABLE_JTAG is not supported for the selected MCU/Board."
#endif
// Check requirements for upload.py
#if ENABLED(XFER_BUILD) && !BOTH(BINARY_FILE_TRANSFER, CUSTOM_FIRMWARE_UPLOAD)
#error "BINARY_FILE_TRANSFER and CUSTOM_FIRMWARE_UPLOAD are required for custom upload."
#endif

View File

@@ -25,7 +25,7 @@
* Release version. Leave the Marlin version or apply a custom scheme.
*/
#ifndef SHORT_BUILD_VERSION
#define SHORT_BUILD_VERSION "2.0.9.4"
#define SHORT_BUILD_VERSION "2.1.0.1"
#endif
/**
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2022-06-04"
#define STRING_DISTRIBUTION_DATE "2023-07-19"
#endif
/**
@@ -52,7 +52,7 @@
* to alert users to major changes.
*/
#define MARLIN_HEX_VERSION 02000904
#define MARLIN_HEX_VERSION 02010000
#ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif

View File

@@ -540,6 +540,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

View File

@@ -432,7 +432,7 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
const bool is_inch = parser.using_inch_units();
const AxisEnum a = TERN(LCD_SHOW_E_TOTAL, axis == E_AXIS ? X_AXIS : axis, axis);
const uint8_t offs = a * (is_inch ? XYZ_SPACING_IN : XYZ_SPACING);
lcd_put_wchar((is_inch ? X_LABEL_POS_IN : X_LABEL_POS) + offs, XYZ_BASELINE, axis_codes[axis]);
lcd_put_wchar((is_inch ? X_LABEL_POS_IN : X_LABEL_POS) + offs, XYZ_BASELINE, AXIS_CHAR(axis));
lcd_moveto((is_inch ? X_VALUE_POS_IN : X_VALUE_POS) + offs, XYZ_BASELINE);
if (blink)

View File

@@ -72,7 +72,7 @@ void DWIN_String::add(const char *tpl, const int8_t index, const char *cstr/*=nu
else if (ch == '$' && cstr)
add(cstr);
else if (ch == '@')
add_character(axis_codes[index]);
add_character(AXIS_CHAR(index));
else
add_character(ch);
}

View File

@@ -79,9 +79,9 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
dwin_string.set();
if (blink)
dwin_string.add(value);
else if (!TEST(axis_homed, axis))
else if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axis_trusted, axis))
else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else
dwin_string.add(value);
@@ -103,11 +103,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
if (blink)
dwin_string.add(value);
else {
if (!TEST(axis_homed, axis))
if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else {
#if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
if (!TEST(axis_trusted, axis))
if (!TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else
#endif

View File

@@ -31,6 +31,37 @@
#if ENABLED(DWIN_LCD_PROUI)
#if DISABLED(LIMITED_MAX_FR_EDITING)
#warning "LIMITED_MAX_FR_EDITING is recommended with ProUI."
#endif
#if DISABLED(LIMITED_MAX_ACCEL_EDITING)
#warning "LIMITED_MAX_ACCEL_EDITING is recommended with ProUI."
#endif
#if ENABLED(CLASSIC_JERK) && DISABLED(LIMITED_JERK_EDITING)
#warning "LIMITED_JERK_EDITING is recommended with ProUI."
#endif
#if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
#warning "INDIVIDUAL_AXIS_HOMING_SUBMENU is recommended with ProUI."
#endif
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
#warning "LCD_SET_PROGRESS_MANUALLY is recommended with ProUI."
#endif
#if DISABLED(STATUS_MESSAGE_SCROLLING)
#warning "STATUS_MESSAGE_SCROLLING is recommended with ProUI."
#endif
#if DISABLED(BAUD_RATE_GCODE)
#warning "BAUD_RATE_GCODE is recommended with ProUI."
#endif
#if DISABLED(SOUND_MENU_ITEM)
#warning "SOUND_MENU_ITEM is recommended with ProUI."
#endif
#if DISABLED(PRINTCOUNTER)
#warning "PRINTCOUNTER is recommended with ProUI."
#endif
#if HAS_MESH && DISABLED(MESH_EDIT_MENU)
#warning "MESH_EDIT_MENU is recommended with ProUI."
#endif
#include "dwin.h"
#include "menus.h"
#include "dwin_popup.h"
@@ -162,7 +193,12 @@
#define DWIN_SCROLL_UPDATE_INTERVAL SEC_TO_MS(2)
#define DWIN_REMAIN_TIME_UPDATE_INTERVAL SEC_TO_MS(20)
#define BABY_Z_VAR TERN(HAS_BED_PROBE, probe.offset.z, HMI_data.ManualZOffset)
#if HAS_MESH
#define BABY_Z_VAR TERN(HAS_BED_PROBE, probe.offset.z, HMI_data.ManualZOffset)
#else
float z_offset = 0;
#define BABY_Z_VAR z_offset
#endif
// Structs
HMI_value_t HMI_value;
@@ -200,11 +236,28 @@ uint8_t index_file = MROWS;
bool hash_changed = true; // Flag to know if message status was changed
constexpr float max_feedrate_edit_values[] = MAX_FEEDRATE_EDIT_VALUES;
constexpr float max_acceleration_edit_values[] = MAX_ACCEL_EDIT_VALUES;
constexpr float max_feedrate_edit_values[] =
#ifdef MAX_FEEDRATE_EDIT_VALUES
MAX_FEEDRATE_EDIT_VALUES
#else
{ 1000, 1000, 10, 50 }
#endif
;
constexpr float max_acceleration_edit_values[] =
#ifdef MAX_ACCEL_EDIT_VALUES
MAX_ACCEL_EDIT_VALUES
#else
{ 1000, 1000, 200, 2000 }
#endif
;
#if HAS_CLASSIC_JERK
constexpr float max_jerk_edit_values[] = MAX_JERK_EDIT_VALUES;
constexpr float max_jerk_edit_values[] =
#ifdef MAX_JERK_EDIT_VALUES
MAX_JERK_EDIT_VALUES
#else
{ DEFAULT_XJERK * 2, DEFAULT_YJERK * 2, DEFAULT_ZJERK * 2, DEFAULT_EJERK * 2 }
#endif
;
#endif
static uint8_t _percent_done = 0;
@@ -815,6 +868,8 @@ void update_variable() {
else
DWINUI::Draw_Icon(ICON_Zoffset, 187, 416);
}
#else
DWINUI::Draw_Icon(ICON_Zoffset, 187, 416);
#endif
_draw_xyz_position(false);
@@ -2292,48 +2347,45 @@ void ApplyFlow() { planner.refresh_e_factor(0); }
void SetFlow() { SetPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, ApplyFlow); }
// Bed Tramming
TERN(HAS_BED_PROBE, float, void) Tram(uint8_t point) {
char cmd[100] = "";
#if HAS_BED_PROBE
void TramXY(const uint8_t point, const float &margin, float &x, float &y) {
switch (point) {
case 0:
LCD_MESSAGE(MSG_LEVBED_FL);
x = y = margin;
break;
case 1:
LCD_MESSAGE(MSG_LEVBED_FR);
x = X_BED_SIZE - margin; y = margin;
break;
case 2:
LCD_MESSAGE(MSG_LEVBED_BR);
x = X_BED_SIZE - margin; y = Y_BED_SIZE - margin;
break;
case 3:
LCD_MESSAGE(MSG_LEVBED_BL);
x = margin; y = Y_BED_SIZE - margin;
break;
case 4:
LCD_MESSAGE(MSG_LEVBED_C);
x = X_CENTER; y = Y_CENTER;
break;
}
}
#if HAS_BED_PROBE
float Tram(const uint8_t point) {
char cmd[100] = "";
static bool inLev = false;
float xpos = 0, ypos = 0, zval = 0, margin = 0;
char str_1[6] = "", str_2[6] = "", str_3[6] = "";
if (inLev) return NAN;
margin = HMI_data.FullManualTramming ? 30 : PROBING_MARGIN;
#else
int16_t xpos = 0, ypos = 0;
int16_t margin = 30;
#endif
switch (point) {
case 0:
LCD_MESSAGE(MSG_LEVBED_FL);
xpos = ypos = margin;
break;
case 1:
LCD_MESSAGE(MSG_LEVBED_FR);
xpos = X_BED_SIZE - margin; ypos = margin;
break;
case 2:
LCD_MESSAGE(MSG_LEVBED_BR);
xpos = X_BED_SIZE - margin; ypos = Y_BED_SIZE - margin;
break;
case 3:
LCD_MESSAGE(MSG_LEVBED_BL);
xpos = margin; ypos = Y_BED_SIZE - margin;
break;
case 4:
LCD_MESSAGE(MSG_LEVBED_C);
xpos = X_BED_SIZE / 2; ypos = Y_BED_SIZE / 2;
break;
}
planner.synchronize();
#if HAS_BED_PROBE
TramXY(point, margin, xpos, ypos);
if (HMI_data.FullManualTramming) {
planner.synchronize();
sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%sY%sF5000\nG0Z0F300"),
dtostrf(xpos, 1, 1, str_1),
dtostrf(ypos, 1, 1, str_2)
@@ -2341,6 +2393,20 @@ TERN(HAS_BED_PROBE, float, void) Tram(uint8_t point) {
queue.inject(cmd);
}
else {
// AUTO_BED_LEVELING_BILINEAR does not define MESH_INSET
#ifndef MESH_MIN_X
#define MESH_MIN_X (_MAX(X_MIN_BED + PROBING_MARGIN, X_MIN_POS))
#endif
#ifndef MESH_MIN_Y
#define MESH_MIN_Y (_MAX(Y_MIN_BED + PROBING_MARGIN, Y_MIN_POS))
#endif
#ifndef MESH_MAX_X
#define MESH_MAX_X (_MIN(X_MAX_BED - (PROBING_MARGIN), X_MAX_POS))
#endif
#ifndef MESH_MAX_Y
#define MESH_MAX_Y (_MIN(Y_MAX_BED - (PROBING_MARGIN), Y_MAX_POS))
#endif
LIMIT(xpos, MESH_MIN_X, MESH_MAX_X);
LIMIT(ypos, MESH_MIN_Y, MESH_MAX_Y);
probe.stow();
@@ -2360,14 +2426,20 @@ TERN(HAS_BED_PROBE, float, void) Tram(uint8_t point) {
inLev = false;
}
return zval;
}
#else // !HAS_BED_PROBE
#else
sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%iY%iF5000\nG0Z0F300"), xpos, ypos);
void Tram(const uint8_t point) {
float xpos = 0, ypos = 0, margin = 30;
TramXY(point, margin, xpos, ypos);
char cmd[100] = "", str_1[6] = "", str_2[6] = "";
sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%sY%sF5000\nG0Z0F300"), dtostrf(xpos, 1, 1, str_1), dtostrf(ypos, 1, 1, str_2));
queue.inject(cmd);
}
#endif
}
#endif
void TramFL() { Tram(0); }
void TramFR() { Tram(1); }
@@ -3606,18 +3678,18 @@ void Draw_Steps_Menu() {
void SetBedLevT() { SetPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); }
#endif
uint8_t mesh_x = 0;
uint8_t mesh_y = 0;
#define Z_OFFSET_MIN -3
#define Z_OFFSET_MAX 3
void LiveEditMesh() { ((MenuItemPtrClass*)EditZValueItem)->value = &bedlevel.z_values[HMI_value.Select ? mesh_x : MenuData.Value][HMI_value.Select ? MenuData.Value : mesh_y]; EditZValueItem->redraw(); }
void ApplyEditMeshX() { mesh_x = MenuData.Value; }
void SetEditMeshX() { HMI_value.Select = 0; SetIntOnClick(0, GRID_MAX_POINTS_X - 1, mesh_x, ApplyEditMeshX, LiveEditMesh); }
void ApplyEditMeshY() { mesh_y = MenuData.Value; }
void SetEditMeshY() { HMI_value.Select = 1; SetIntOnClick(0, GRID_MAX_POINTS_Y - 1, mesh_y, ApplyEditMeshY, LiveEditMesh); }
void SetEditZValue() { SetPFloatOnClick(Z_OFFSET_MIN, Z_OFFSET_MAX, 3); }
#if ENABLED(MESH_EDIT_MENU)
uint8_t mesh_x = 0, mesh_y = 0;
#define Z_OFFSET_MIN -3
#define Z_OFFSET_MAX 3
void LiveEditMesh() { ((MenuItemPtrClass*)EditZValueItem)->value = &bedlevel.z_values[HMI_value.Select ? mesh_x : MenuData.Value][HMI_value.Select ? MenuData.Value : mesh_y]; EditZValueItem->redraw(); }
void ApplyEditMeshX() { mesh_x = MenuData.Value; }
void SetEditMeshX() { HMI_value.Select = 0; SetIntOnClick(0, GRID_MAX_POINTS_X - 1, mesh_x, ApplyEditMeshX, LiveEditMesh); }
void ApplyEditMeshY() { mesh_y = MenuData.Value; }
void SetEditMeshY() { HMI_value.Select = 1; SetIntOnClick(0, GRID_MAX_POINTS_Y - 1, mesh_y, ApplyEditMeshY, LiveEditMesh); }
void SetEditZValue() { SetPFloatOnClick(Z_OFFSET_MIN, Z_OFFSET_MAX, 3); }
#endif
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)

View File

@@ -238,9 +238,7 @@ void Draw_Tramming_Menu();
#if HAS_BED_PROBE
void Draw_ProbeSet_Menu();
#endif
#if HAS_FILAMENT_SENSOR
void Draw_FilSet_Menu();
#endif
void Draw_FilSet_Menu();
#if ENABLED(NOZZLE_PARK_FEATURE)
void Draw_ParkPos_Menu();
#endif

View File

@@ -39,37 +39,6 @@
#define DASH_REDRAW 1
#endif
#if DISABLED(LIMITED_MAX_FR_EDITING)
#error "LIMITED_MAX_FR_EDITING is required with ProUI."
#endif
#if DISABLED(LIMITED_MAX_ACCEL_EDITING)
#error "LIMITED_MAX_ACCEL_EDITING is required with ProUI."
#endif
#if ENABLED(CLASSIC_JERK) && DISABLED(LIMITED_JERK_EDITING)
#error "LIMITED_JERK_EDITING is required with ProUI."
#endif
#if DISABLED(FILAMENT_RUNOUT_SENSOR)
#error "FILAMENT_RUNOUT_SENSOR is required with ProUI."
#endif
#if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
#error "INDIVIDUAL_AXIS_HOMING_SUBMENU is required with ProUI."
#endif
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
#error "LCD_SET_PROGRESS_MANUALLY is required with ProUI."
#endif
#if DISABLED(STATUS_MESSAGE_SCROLLING)
#error "STATUS_MESSAGE_SCROLLING is required with ProUI."
#endif
#if DISABLED(BAUD_RATE_GCODE)
#error "BAUD_RATE_GCODE is required with ProUI."
#endif
#if DISABLED(SOUND_MENU_ITEM)
#error "SOUND_MENU_ITEM is required with ProUI."
#endif
#if DISABLED(PRINTCOUNTER)
#error "PRINTCOUNTER is required with ProUI."
#endif
#include "../common/dwin_color.h"
#if ENABLED(LED_CONTROL_MENU)
#include "../../../feature/leds/leds.h"

View File

@@ -22,10 +22,10 @@
*/
#include "../../../inc/MarlinConfigPre.h"
#if BOTH(DWIN_LCD_PROUI, AUTO_BED_LEVELING_UBL)
#include "ubl_tools.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "../../marlinui.h"
#include "../../../core/types.h"
#include "dwin.h"
@@ -249,4 +249,4 @@ bool UBLMeshToolsClass::validate() {
}
#endif
#endif // DWIN_LCD_PROUI
#endif // DWIN_LCD_PROUI && AUTO_BED_LEVELING_UBL

View File

@@ -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)));
}

Some files were not shown because too many files have changed in this diff Show More